본문 바로가기

.Net Technology/.NET TDD

(7) NUnit 시작하기 - Assert 클래스의 기능

대부분의 테스트 메서드에서는 예상 된 결과를 비교 하면서 테스트 결과를 테스트 프레임워크에 전달하게 된다. 이 때 이 역할을 수행해주는 것이 NUnit의 Assert 클래스이다. 지금까지의 테스트 예제에서는 Assert의 AreEqual이라는 메서드를 이용해서 두 값을 비교하면서 테스트 결과를 살펴봤었다.
 
하지만 AreEqual이나 AreSame과 같은 메서드는 실제 지금도 지원을 하고 있지만 오래된 문법이다. 실제 NUnit이 2.4로 버전업을 하면서 새로운 문법을 소개했었는데 그것은 바로 That이라는 문법이다. 그럼 상황에 따라서 어떻게 값을 비교할 수 있을지 살펴보도록 하자. 
 
 
팁! 값 타입과 참조타입의 == 키워드의 이용
 
알다시피 닷넷에서는 참조 타입과 값 타입 이렇게 두 개의 타입이 존재한다. 값 타입은 Stack 영역에 저장됨과 동시 그 값을 가지고 있다. 하지만 참조 타입은 Stack 영역이 아닌 Heap 영역에 저장되며 그 변수는 단순히 Heap 영역의 주소만 가지고 있게 된다. 때문에 값이 같다라는 것은 값 타입만 해당하는 것이다. 단, 예외는 있다. String의 경우 분명 참조 타입이지만 ==을 사용하여 값을 비교할 수 있다. 그 이유는 String 클래스의 경우 자신이 내부적으로 직접 == 키워드를 Equals 라는 메서드와 연결하기 때문이다.
 
다시 정리해서 String을 제외한 참조타입에서 == 를 실행할 경우에 그것은 같은 값이냐는 뜻이 아니라 같은 객체인지를 비교하게 된다. 조금 더 정확하게 말해서 같은 주소를 가지고 있냐라는 뜻이다.
 
두 값을 비교하고 싶은 경우
 
기존에 사용하던 AreEquals라는 단순한 문법을 최대한 활용하기 위해서 NUnit은 that 구문을 도입했고 두 개의 값을 비교하는데 있어서 Is.EqualTo 라는 문법을 사용하는 것이 가능해졌다. 먼저 숫자를 비교하는 예제는 아래와 같이 간단하게 작성할 수 있다.
 
Assert.That(2 + 2, Is.EqualTo(4.0)); Assert.That(2 + 2 == 4); Assert.That(2 + 2 != 5);
하지만 여기서 만약 같지 않다라는 구문을 넣고 싶다면 아래와 같이 작성할 수 있다. 
 
Assert.That(2 + 2, Is.Not.EqualTo(5));
 
여기서 만약 오차 범위를 허용하고 싶다고 가정해보자. 예를 들어서 5라는 값에서 플러스 마이너스 0.5까지는 허용하고 싶은 것이다. 이때 우리는 Within이라는 추가 메서드를 이용해서 구문 수식하는 것이 가능하다.
 
int result = 5;
Assert.That(5.5, Is.EqualTo(result).Within(0.5));
 
즉, 5.5라는 예상된 값을 비교하는데 있어서 0.5까지의 오차 범위를 허용하기 때문에 실제 값이 5일 경우에도 위의 테스트는 성공적으로 돌아가게 된다. 뿐만 아니라 Percent라는 수식어를 통해서 우리는 오차 범위가 실제 숫자가 아닌 예상한 값의 몇 프로까지 허용할지를 지정해줄 수 있다. 
 
int result = 5;
Assert.That(5.5, Is.EqualTo(result).Within(20.5).Percent);
 
위의 예제에서는 실제 결과값에서 20.5% 까지의 오차는 허용하겠다는 것이다.
 
 
문자열의 비교
 
문자열 또한 위와 같은 방법으로 비교가 가능하다. 특별히 대소문자를 구별할 것인지에 대한 옵션을 정의하는 것이 가능하다. 아래 코드를 살펴보자. 
 
Assert.That("Hello!", Is.Not.EqualTo("HELLO!"));
Assert.That("Hello!", Is.EqualTo("HELLO!").IgnoreCase);
 
두 테스트 모두 통과 된다. 두 번째 구문에서 우리는 IgnoreCase를 붙였기 때문에 가능하다. 그 외에도 특별히 추가적인 문자열을 가지고 있는지 여부를 StringContaining 메서드를 통해서 확인할 수 있다. 
 
string phrase = "Make your tests fail before passing!";
Assert.That(phrase, Is.StringContaining("tests fail"));
Assert.That(phrase, Is.Not.StringContaining("tests pass"));
 
물론 반드시 테스트에서 제공하는 기능을 써서 비교해야 한다는 것은 아니다. 우리가 원래 알고 있던 문법을 응용할 수 있으면 아래와 같이 작성해도 무방하다.
 
Assert.That(phrase.Contains("tests fail"));
 
기본적으로 String에서 제공하는 Contains가 true/false를 반환하기 때문에 위의 테스트는 당연히 true를 반환하게 되고 테스트는 통과될 수 있다.
 
 
날짜의 비교
 
실제 캐싱을 이용할 경우에 시간을 비교해서 캐시가 되고 있는지를 확인하는 경우가 종종 있다. 이때 우리는 날짜를 비교하게 되는데 Within을 지원하기 때문에 손쉽게 이 코드를 작성할 수 있다. 
 
DateTime now = DateTime.Now;
Thread.Sleep(1000);
Assert.That(now, Is.EqualTo(DateTime.Now).Within(2).Seconds);
 
즉, 여기서 now라는 시간이 현재 시간과 2초 안의 차이가 난다면 이 테스트는 통과 하게 된다.
 
 
배열의 값들을 비교
 
NUnit은 실제 배열 안의 값들이 같은지를 비교하는 것이 가능하다. 하지만 배열의 요소들은 같아도 각 배열 요소들의 순서가 다르면 다른 값으로 인식한다. 
 
int[] i3 = new int[] { 1, 2, 3 };
double[] d3 = new double[] { 1.0, 2.0, 3.0 };
int[] iunequal = new int[] { 1, 3, 2 };
Assert.That(i3, Is.EqualTo(d3));
Assert.That(i3, Is.Not.EqualTo(iunequal));
 
 
객체의 비교
 
객체가 같은지를 비교한다는 것은 가지고 있는 주소가 같은지를 비교한다는 것이다. 즉, 같은 객체를 바라보고 있는지 아닌지에 대한 여부이다. 이전 문법이라면 AreSame이라는 메서드를 이용하면 될 것이다. 하지만 여기서는 Is.EqualTo 대신 Is.SameAs 라는 구문을 이용하면 된다. 아래 예제를 살펴보자. 
 
Exception ex1 = new Exception();
Exception ex2 = ex1;
Assert.That(ex2, Is.SameAs(ex1));

Exception ex3 = new Exception();
Assert.That(ex3, Is.Not.SameAs(ex1));
 
 
이렇게 해서 NUnit을 다루는데 있어서 필요한 기본적인 지식을 어느 정도 전달했다. 이제 위의 지식들을 바탕으로 실전 프로그램을 한번 작성해보도록 하자.