포스팅에서 다룰 내용
본 게시글은 Unit Testing 도서 중 3장을 정리하였습니다.
- 단위 테스트 구조
- 좋은 단위 테스트 명명법
- 매개변수화된 테스트 작성
- Fluent Assertions 사용
단위 테스트를 구성하는 방법
AAA패턴을 사용하기
- 준비-실행-검증 세 부분으로 구성된 패턴이다.
- 준비 : SUT와 해당 의존성을 원하는 상태로 만들기
- 실행 : SUT에서 메소드를 호출하고 준비된 의존성을 전달하며 출력 값을 캡처하기
- 검증 : 결과를 검증하기
- 이 패턴은 모든 테스트가 균일한 구조를 가질 수 있도록 한다. 따라서 전체 테스트 스위트의 유지 보수 비용이 적게 든다.
- 유사한 패턴으로 Given-When-Then 패턴이 있다.
- 준비부터 테스트를 작성하는 것이 일반적이나 TDD를 실천할 때에는 아직 기능이 어떻게 동작할지 알지 못하기 때문에 검증부터 테스트를 작성하는 것도 가능하다.
여러 개의 준비, 실행, 검증 구절 피하기
검증구절 혹은 준비구절에 여러 개의 실행 구절이 있다면 여러 개의 동작 단위를 검증하는 테스트를 뜻하기 때문에 이는 단위 테스트가 아니라 통합 테스트가 되므로 지양해야 한다.
테스트 내 if문 피하기
if문은 테스트가 한 번에 많은 것을 검증한다는 표시이기에 안티 패턴이다. 따라서 단위 테스트는 분기가 없는 간단한 일련의 단계여야 한다.
구절의 크기
일반적으로 준비 구절이 가장 크며, 실행과 검증을 합친 것보다 크면 같은 테스트 클래스 내의 비공개 메소드나 별도의 팩토리 클래스로 도출하는 것이 좋다. 준비 구절에서 코드 재사용에 도움이 되는 두 가지 패턴으로 오브젝트 ㅏ더와 테스트 데이터 빌더가 있다.
실행 구절은 보통 한 줄이어야 한다. 하나의 행위에 대해 두 개의 메소드가 생기고 호출해야 하게 되면 캡슐화가 깨지게 되기 때문이다. 따라서 코드 캡슐화를 항상 지켜야 한다.
캡슐화
잠재적 모순으로부터 코드를 보호하는 행위
검증 구절에서 단일 동작 단위는 여러 결과를 낼 수 있기 때문에 하나의 테스트로 그 모든 결과를 평가하는 것이 좋다. SUT에서 반환된 객체 내에서 모든 속성을 검증하는 것보다는 == 연산자 등으로 동등 비교가 가능한 메소드를 정의하는 것이 좋다.
종료 단계
추가적으로 4번째 종료 구절을 따로 두는 경우도 있다. 예를 들어 테스트에 의해 작성된 파일을 지우거나 DB 연결을 종료하고자 할 때 이 구절을 사용한다. 보통 단위 테스트는 외부에 종속적이지 않기에 종료 구절을 사용하진 않는다.
테스트 간 테스트 픽스처 재사용
테스트 픽스처란, 테스트 실행 대상 객체로 각 테스트 실행 전에 알려진 고정 상태로 유지하기 때문에 동일한 결과를 생성한다.
테스트 코드를 작성할 때 공통 테스트 픽스처는 별도의 메소드로 추출하고 이를 여러 테스트 코드에서 재사용할 수 있다. 하지만 이렇게 되면 테스트 간 결합도가 높아지고 가독성이 떨어진다는 단점이 있다.
따라서 테스트 픽스처를 사용할 때에는 테스트 클래스에 비공개 팩토리 메소드를 두는 것이 좋다. 혹은 기초 클래스를 두어 클래스 생성자에서 DB 연결을 초기화하는 것도 권장된다.
단위 테스트 명명법
[테스트 대상 메소드]_[시나리오]_[예상결과] 형식으로 작성하면 좋다.
- 테스트 대상 메소드 : 테스트 중인 메소드명
- 시나리오 : 메소드를 테스트하는 조건
- 예상 결과 : 현재 시나리오에서 테스트 대상 메소드에 기대하는 것
혹은 아래와 같은 지침을 따를 수 있다.
- 엄격한 명명 정책보다는 자유롭게 작성하기
- 문제 도메인에 익숙한 비개발자들에게 시나리오를 설명하는 것처럼 작성하기
- 단어를 밑줄로 구분하기
예를 들어 배송 날짜가 미래인 것이 불가능한 테스트의 이름은 Delivery_with_a_past_date_is_invalid가 된다.
매개변수화된 테스트 리팩토링하기
대부분의 단위 테스트 프레임워크는 매개변수화된 테스트를 사용하여 유사한 테스트를 묶을 수 있는 기능을 제공한다. 이를 사용하면 테스트 코드의 양을 크게 줄일 수 있지만 비용이 발생한다. 덧붙여 테스트 메소드가 나타내는 사실을 파악하기 어렵다. 따라서 긍정적인 테스트 케이스는 고유한 테스트로 도출하고 가장 중요한 부분을 잘 설명하는 이름을 붙이면 좋다.
또한 xUnit에는 테스트 메소드에 공급할 사용자 정의 데이터를 생성하는 데에 사용할 수 있는 기능이 있다. 따라서 이를 사용하면 컴파일러의 제한을 극복하고 매개변수화된 테스트에서 모든 유형의 매개변수를 사용할 수 있다.
'Test' 카테고리의 다른 글
[Unit Testing] 단위 테스트에서의 런던파와 고전파 (0) | 2024.08.15 |
---|---|
[Unit Testing] 단위 테스트 소개 (목표, 커버리지 지표) (0) | 2024.08.13 |