단위테스트 (Unit Testing) - 블라디미르 코리코프 책을 읽고 정리한 내용
- 단위 테스트란?
- 작은 코드 조각 검증
- 빠르게 수행
- 격리된 방식으로 처리하는 자동화된 테스트
- 격리란? -> 런던파 / 고전파를 나누는 척도
하나의 클레스가 다른 클레스 또는 여러 클래스에 의존하면 해당 의존성을 테스트 대역(test double)으로 대체해야하는 것. 즉, 동작을 외부영역과 나누어야한다. 의존성이 걸려있는것은 따로 검사함으로써 묶여있는 문제를 해결할 수 있다. 앞 내용에서 외부 라이브러리로 인하여 여러 예외에 빠질수 있는 예시가 있었다.
3. 이점
각 의존성을 확인하려면 객체 그래프를 그리는 방법밖에 없다.
그러나 구조가 복잡함으로 그냥 하나의 class에 하나의 단위 테스트를 만들면 된다는 지침을 만든다.
4. 고전파
AAA(Arrange, Act, Assert) 패턴을 이용한다.
이때 준비 단계에서, 테스트 대상 시스템 (SUT, System Under Test)과 하나의 협력자를 준비한다.
이때 하나의 협력자란, 해당 책의 예시로 보면 고객이 구매시에 해당 물건의 재고가 있는지 확인하는 테스트를 하는데, 이때 협력자는 가게 ( 물건의 재고를 가지고있는 ) 이다.
이때 협력자는 운영용 인스턴스를 이용한다.
그러나 두 고객과 가게는 격리되어있지 않음으로 둘 중 하나의 코드에 버그가 있는 경우 테스트에 실패할 수 있다.
- 테스트 대역 / 목
- 런던 스타일로 작성된 단위 테스트
-> 특징, store 인스턴스를 생성하지 않음,
아래 예시를 확인해 보자
주석처리를 확인하였을때. 직접 인터페이스 메소드를 호출하는것을 확인할 수 있다.
usingMoq;
usingXunit;
namespaceBook.Chapter2.Listing2
{
publicclassCustomerTests
{
[Fact]
publicvoidPurchase_succeeds_when_enough_inventory()
{
//Arrange
varstoreMock=newMock<IStore>();
storeMock
.Setup(x=>x.HasEnoughInventory(Product.Shampoo, 5)) // 직접 인터페이스를 목으로 만들어서 사용
.Returns(true);
varcustomer=newCustomer();
//Act
boolsuccess=customer.Purchase(storeMock.Object, Product.Shampoo, 5);
//Assert
Assert.True(success);
storeMock.Verify(x=>x.RemoveInventory(Product.Shampoo, 5), Times.Once);
}
[Fact]
publicvoidPurchase_fails_when_not_enough_inventory()
{
//Arrange
varstoreMock=newMock<IStore>();
storeMock
.Setup(x=>x.HasEnoughInventory(Product.Shampoo, 5))
.Returns(false);
varcustomer=newCustomer();
//Act
boolsuccess=customer.Purchase(storeMock.Object, Product.Shampoo, 5);
//Assert
Assert.False(success);
storeMock.Verify(x=>x.RemoveInventory(Product.Shampoo, 5), Times.Never);
}
}
}
5. 공유 의존성, 비공개 의존성, 프로세스 의존성
테스트간의 공유되고 서로의 결과에 영향을 미칠 수단.
- 1.비공개 의존성 (private dependency)
- -> 공유하지 않는 의존성
- 2.프로세스 외부 의존성(out - of - process dependency)
- -> 애플리케이션 실행 프로세스 외부에서 실행되는 의존성. 아직 메모리에 없는 데이터에 대한 프록시이다.
- -> 데이터베이스를 프로세스 외부이면서 공유의존성이다.
각 테스트 실행 전에 도커 컨테이너로 데이터베이스를 시작하면 테스트가 더 이상 동일한 인스턴스로 작동하지 않기 때문에 프로세스 외부 이면서 공 유하지 않는 의존성이 된다.
6. 공유 의존성 대체
이유는 데스트 실행 속도를 높인다. 왜냐하면 공유 의존성은 거의 실행 프로세스 외부에 있기 때문이다. 이러한 호출 속도 때문에 공유 의존성을 가진 테스트의 단위 테스트 영역에서 통합 테스트 영역으로 넘어간다.
7. 고전파와 런던파의 결론
두 차이는 격리문제에 있다 . 격리문제를 포커싱한 런던파는 입자성과 세밀하다는 장점을 도출 할 수있다.
8. 그러나 저자의 결론은?
테스트는 코드 단위의 검증을 하면 안된다. 동작의 단위에 포커스를 맞춰야한다. 코드 단위로 테스팅이 이루어진다면 그 의미가 훼손되고 어떤것을 검증하는지 이해하기 어려워진다.
따라서 테스트를 진행하는데 복잡한 객체 그래프가 형성된다면,, 설계의 잘못임으로 본질로 돌아가자
개인적인 견해로는, 테스트코드를 명확히 짜보지 않아 세세한 의미를 파악하기 어렵다. 그러나 이론적인 배경을 알고 방향성을 알면 더욱 좋은 코드를 짤 수 있을 것 같다.
테스트코드는 짧은 시간에 좋은 검증을 해야한다. 이에 받치는것이 좋은 설계이므로 설계공부도 게을리하면 안될 것 같다.
'TIL' 카테고리의 다른 글
[Docker] 실습 :: 이미지 생성 (0) | 2022.08.19 |
---|---|
[Docker] 기초내용 (1) - 이미지, 컨테이너, 구성 (0) | 2022.08.15 |
[Docker] Basic - Docker 기본 정리 (0) | 2022.07.03 |
[git Error] There isn’t anything to compare.main and master are entirely different commit histories. (0) | 2022.07.02 |
[CapstoneDesign #1] DB Design (0) | 2022.03.30 |