- 테스트를 자동화 해주는 툴에는 Java에 junit, C/C++에는 gtest, Javascript에는 mocha 등 각종 언어에 여러가지가 있습니다.
- 각 언어에 있는 Unit 계열의 테스트 자동화 툴을 XUnit이라고 합니다.
- 유의할 것은, 테스트 툴이 없다고 해서 테스트를 제작하지 못하는 것은 아니라는 점입니다.
- 예를 들어... (사실 위 코드에서도 보실 수 있습니다.)
// 사용 언어는 Java입니다.
import java.util.*;
public class Gugudan
{
public Gugudan()
{
// TODO Auto-generated constructor stub
}
public static void main(String[] args)
{
System.out.println("Hello World");
Gugudan module = new Gugudan();
module.test();
//module.run();
}
private void test()
{
String ret = dan(1);
if (ret.equals("1 * 1 = 1\n2 * 1 = 2\n3 * 1 = 3\n4 * 1 = 4\n5 * 1 = 5\n6 * 1 = 6\n7 * 1 = 7\n8 * 1 = 8\n9 * 1 = 9\n"))
{
System.out.println("S");
}
else
{
System.out.println("F");
}
}
private void run()
{
System.out.println("Hello World!");
System.out.println(dan(1));
}
String dan(int level)
{
String ret = "";
for (int i = 1; i < 10; i++)
{
ret += (String.format("%d * %d = %d", i, level, i * level)) + "\n";
}
return ret;
}
}
- 다음과 같은 경우에는 테스트 툴을 사용하진 않았지만, 테스트를 제작했습니다.
- TDD를 쓰면 빠른 피드백을 받을 수 있는 장점이 있습니다. 또한, 테스트를 위한 코드를 계속해서 만들어가면 설계 구조가 자연스럽게 되는 점도 있습니다.
보너스로 Failure를 Success로 바꿀 때의 성취감을 얻을 수 있습니다.
- 다만, 사람이 좀 피곤해진다는 단점도 있을 수 있습니다.....
- TDD는 다음의 과정을 거칩니다.
- 초기에 Failure가 되는 테스트를 제작한다.
- 최대한 빠르게 이 테스트를 Success로 만드는 코드를 만든다.
- 코드 리팩토링 과정을 거친다.
- 참고로, 리팩토링 과정은 본 코드와 테스트 코드 전체에 걸쳐 이루어져야합니다.
- 반복한다.
- 직접 만들어봅시다! (사용 언어는 Java이고, JUnit을 사용했습니다.)
import org.junit.Test;
import static org.junit.Assert.*;
public class MoneyTest
{
@Test
public void testMoney()
{
//Given
//When
Money money = new Money();
//Then
assertNotNull(money);
}
}
- 당연히 Money라는 클래스가 없으므로 컴파일 오류가 나면서, 테스트를 실행해보면 Failure가 뜹니다. 이제 이것을 Success로 고치기 위해 Money라는 클래스를 만들어봅시다.
public class Money
{
public Money()
{
}
}
- 이제 테스트를 실행해보면 Success가 됩니다.
- 다음으로 이제 리팩토링을 해야하지만, 이 코드의 경우 너무나도 간단하므로 생략합니다.
- 이렇게 하면 한 과정을 끝냈습니다! 이제 이 과정을 반복하면 됩니다.
- 자, 다음으로 이제 Money 인스턴스를 만드는 것을 끝내고 나니, Money 인스턴스를 만들 때 초기 금액이 필요할 것 같습니다. 이 기능을 추가하기 위해 테스트를 하나 더 만들어봅시다.
..........
@Test
public void testMoneyWithDraw()
{
//Given
Money money = new Money(10000);
//When
double amount = money.getAmount();
//Then
assertNotNull(money);
assertEquals(10000, amount, 0.000001);
}
...........
- 일단 당연히 Money 클래스에는 getAmount라는 메서드가 없으므로 Failure가 납니다. 이제 이것을 Success로 고쳐봅시다. Money 클래스에 다음을 추가합니다.
.....
private double amount;
public Money(double draw, Currency currency)
{
this.amount = draw;
}
........
public double getAmount()
{
return 10000;
}
......
- 뭔가 이상하지만, 일단 다시 테스트를 실행해보면 Success가 됩니다. 이제 리팩토링 과정을 거치게 되는데, 코드를 다음과 같이 고쳐봅니다.
......
public double getAmount()
{
return this.amount;
}
......
- 다시 테스트를 돌려보면 Success가 됩니다. 또 다시 한 과정을 모두 끝냈습니다!
- 이렇게, 테스트가 주도가 되어 개발하는 것을 TDD라고 합니다.
- 추가로, 이런 테스트 코드는 다음과 같은 장점을 줍니다.
- 자신이 코드를 수정했을 때, 그것이 버그를 발생시키는 지에 대한 여부를 바로 파악할 수 있습니다.
- 테스트용 코드 각각이 별도의 사용 설명서를 겸하는 예시 코드가 됩니다.