테스트
테스트 케이스
- 테스트를 하기 위해 작성하는 테스트 코드
- 테스트를 위한 입력 데이터, 실행 조건, 기대 결과를 표현한 명세
테스트의 종류
- 기능 테스트
- 사용자가 애플리케이션의 전반적인 기능을 테스트
- Frontend + BackEnd + DB + (외부 서비스) 까지 모두 연동되어 있다.
- 통합 테스트
- 개발팀에서 클라이언트 측 툴 없이 테스트를 진행하는 것
- BackEnd + DB
- 애플리케이션의 여러 계층이 연관되어 있다.
- 슬라이스 테스트
- 각 계층별로 쪼개어 진행하는 테스트
- API 계층, 서비스 계층, 데이터 액세스 계층별로
- 단위 테스트
- 메서드 단위로 테스트
- 보통 비즈니스 로직에서 사용하는 클래스에 적용한다.
- 단위는 최대한 작을수록 좋다.
- 작은 단위일수록 빠르고 간단하게 테스트를 진행할 수 있기 때문에
단위 테스트
FIRST 원칙
단위 테스트를 위한 FIRST 원칙
- Independent
- 각각의 테스트 케이스는 독립적이여야 한다.
- 테스트의 순서와 상관없이, 모두 정상적인 실행이 보장되어야 한다.
- Repeatable
- 테스트 케이스는 어떤 환경에서도 반복적으로 실행 가능해야 한다.
- 따라서 외부 서비스/리소스의 연동을 끊어 어느 상황에서든 실행 가능하도록 해야한다.
- Self-validating
- 단위 테스트는 성공인지 실패인지 결과를 자체적으로 보여줘야 한다.
- Timely
- 단위 테스트는 기능을 구현하기 전에 작성되어야 한다.
Given-When-Then 표현
BBD 테스트 방식에서 사용하는 용어로, 테스트 케이스를 작성하는데 유용한 표현이다.
- Given
- 테스트에 필요한 전제 조건을 작성
ex) 입력 값, 테스트 데이터
- When
- Then
- 테스트의 결과를 검증
- 예상 결과(expected)와 수행 결과(actual)이 같은지 Assertion한다.
Assertion
- 테스트 검증
- 예상하는 결과가 참이길 바라는 것
JUnit
- 오픈소스 테스트 프레임워크 (사실상 거의 표준 테스트 프레임워크)
- Spring Boot의 디폴트 테스트 프레임워크는 JUnit이다.
애너테이션
- @BeforeEach/@BeforeAll: 테스트 케이스를 실행하기 전, 객체의 전처리 과정을 해야할 때 사용
- @BeforeEach: 매 테스트 케이스마다 실행됨
- @BeforeAll: 테스트 케이스가 실행되기 전에 딱 한번만 실행됨(초기화에 사용)
- @AfterEach, @AfterAll : 후처리 과정을 해야할 때 사용
Assertions
import static org.junit.jupiter.api.Assertions
import org.assertj.core.api.Assertions
도 있다.
아래의 메서드들은 JUnit에서 지원하는 Assertions의 메서드이다.
assertEquals(expected, actual);
assertNotNull(actual);
assertThrows(expectedType, executable);
- expectedType: 발생이 기대되는 예외 클래스
- executable: 메서드 호출
- 호출한 메서드에서 expectedType의 예외가 발생하면 passed
- expectedType의 상위 타입이여도 가능하다.
- Exception은 최상위 예외 클래스이므로 어떤 예외 클래스가 발생하더라도 passed이다.
- expectedType과 상속 관계가 아니거나, expectedType을 상속하는 하위 타입은 failed이다.
✔️ executable = 함수형 인터페이스
내부에 execute() 메서드 하나만 정의되어 있다.
Assumption 메서드
- Assumption : ~라고 가정하다.
- 테스트의 if문이라고 생각할 수 있다.
- assumeTrue()
- 테스트가 실패하면, 에러 발생
- 테스트가 성공하면, 아래의 코드를 실행한다.(if 문)
- assumeFalse() : 테스트가 성공하면, 에러 발생
Assertion vs Assumption
ex) 현재 OS가 무엇인지 모를 때,
assumeTrue(System.getProperty("os.name").startsWith("Windows"));
이렇게 작성한 후에, 맞다면 아래의 로직을 계속 수행하고 아니면 수행을 멈춘다.
Hamcrest
Hamcrest란?
- JUnit 기반의 단위 테스트에서 사용할 수 있는 Assertion Framework
- JUnit Assertion 메서드를 Hamcrest Assertion 메서드로 변경해서 사용한다.
Hamcrest를 사용하는 이유?
- 테스트 실패 메세지를 이해하기 쉽다.
- Assertion을 위한 다양한
매쳐(Matcher)
가 존재한다.
-> Assertion을 자연스러운 문장으로 만들어주어 가독성이 향상된다.
매쳐(Matcher)
http://hamcrest.org/JavaHamcrest/javadoc/2.2/
assertThat(actual, is(equalTo(expected)));
assertThat(actual, is(notNullValue()));
assertThat(actual, is(nullValue()));
- is()
- equalsTo()
- notNullValue()
- nullValue()
❗️ 주의
인텔리제이에 자동 import를 켜놨음에도 Assertion 메서드에 대한 import 문이 자동으로 import 되지 않았다. 또한, import를 하려고 해도 나에게 추천해주는 import문 중에 없어서 직접 import 문을 찾아 작성해야 했다.
-> 인텔리제이의 문제인지 잘 모르겠지만 해결 방법은 없을까?
[참고]
https://effortguy.tistory.com/123