TDD : NUnit 2.5의 새로운 기능 : Parameterized Tests CSharp


NUnit에 대한 기초 설명은 필요없을테고, 홈페이지 에서 참고하시구요.

NUnit 2.5를 사용해야 할 10가지 이유 를 보시면, 사용해 보고 싶을겁니다.
개인적으로는 5. Lambda support, 6. Out-of-Process execution and runtime selection, 7. PNUnit, 10. Threading attributes 가 맘에 듭니다.

우선 NUnit 2.5의 설명 문서를 보시고, 기존과 달리 새로운 기능 중에 제가 생각하기에 유용한 기능을 몇가지 꼽아보겠습니다.


1. Parameterized Tests

   MbUnit의 RowTestAttribute, RowAttribute라는 게 있어서, 테스트 메소드에 테스트 하고자 하는 값을 인자로 전달 할 수 있다고 했죠? 
  이번 NUnit 2.5에서는 이와 관련한 상당히 많은 Attribute가 추가 되었습니다.

  TestCaseAttribute 는 MbUnit 과 마찮가지로, 함수 인자에 설정할 값들을 지정해서 사용합니다.

[TestCase(10, 5, 2)]
[TestCase(12, 3, 4)]
public void DivideTest(int n, int d, int expected)
{
Assert.AreEqual(expected, n / d);
}

결과값을 갖도록 하려면 TestCase 에 Result를 사용하면 됩니다.

[TestCase(10, 5, Result=2)]
[TestCase(12, 3, Result=4)]
public int DivideTest(int n, int d)
{
return (n / d);
}

TestCaseAttribute의 단점은 입력 파라미터가 많을 때, 경우의 수를 모두 적시해야 하는 단점이 있습니다. 이런 입력 변수에 대한 경우의 수를 다른 곳에 정의해 두고, 참고해서 사용할 수 있는 기능이 TestCaseSourceAttribute를 사용하는 것입니다.

[Test, TestCaseSource("DivideCases")]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual(q, n / d);
}
static object[] DivideCases = { new object[] { 12, 3, 4},
                                             new object[] { 12, 2, 6},
                                             new object[] { 15, 5, 3}};
 
이 것보다 더 강력한 기능은 테스트 함수의 각각의 인자마다 값을 자동 생성하게 하는 기능입니다. 각각의 인자는 Random, Range, Values 방식으로 지정이 가능합니다.

[Test]
public void MyTest( [Values(1,2,3) int x, [Range(0.2, 0.6, 0.2) double d)
{
    ...
}

자 그럼 복수의 인자들의 값은 생성되는데, 그 값들의 조합은 어떻게 할까요? NUnit은 기본적으로 조합을 사용합니다.
즉 x 인자의 경우의 수와 d 인자 값의 경우의 수를 조합해서 테스트를 수행한다는 소리지요. 이렇게 되면 수많은 데이타의 조합에 대해 테스트가 가능해지므로, 심도있는 테스트가 가능해 질 것입니다.

이렇게 복수의 인자들의 조합을 하는 방식은 CombinatorialAttribute, PairwiseAttribute, SequentialAttribute로 조합 방식을 지정할 수 있습니다. 기본은 CombinatorialAttribute입니다.

[Test, Combinatorial]
public void MyTest ( [Values(1,2,3)] int x, [Values("A", "B")] string s )
{
    ...
}

위와 같은 테스트 함수는 

MyTest(1, "A")
MyTest(1, "B")
MyTest(2, "A")
MyTest(2, "B")
MyTest(3, "A")
MyTest(3, "B")
이렇게 6번의 테스트를 수행하게 된다는 뜻입니다.

테스트 코드 작성하는 것도 어려운데 (사실 테스트 시나리오 만드는 거죠) 데이타까지 신경써야 합니까? 라고 묻는다면, 
꼭 그렇게 해야 합니다... 이렇게 자동으로 많은 경우에 대해 테스트를 수행해주는 자동화 툴이 있는데 왜 사용을 안하십니까?
저는 이런한 테스트가 자신이 만든 코드를 더욱 견고하게 만들 수 있는 기회를 제공해주는 축복이라 생각합니다.