좋은 테스트 원칙
- 한번 작성된 테스트 코드는 영원히 유지보수 해야 한다. (유지 보수성을 고려)
- 내부 구현 사항을 테스트 하면 안된다. 너무 내부적인 사항까지 테스트하면 힘들다.
- 재사용성을 높이기 (테스트 유틸리티)
- 배포용 코드와 철저히 분리하기. 포함이 되지 않도록.
- 테스트 코드를 통한 문서화
테스트 코드의 구조
BeforeEach : 각각의 테스트가 수행되기 전에 호출됨
BeforeAll : 딱 한번만 호출 됨
AfterEach : 각각의 테스트가 수행된 후에 호출됨
AfterAll : 모든 테스트가 다 수행 된 다음에 마무리용으로 한번만 호출 됨
테스트 안에는
object를 생성하고 데이터를 준비하는 준비과정 (Given)
- 준비 과정을 여러개의 테스트에 걸쳐 반복해서 사용한다면, 재사용 할 수 있다면 따로 유틸 함수로 정의해서 사용하는 것이 좋다.
테스트 코드를 실행 (When)
- 의도적으로 실패했을 때 실패할 수 있도록 만든 다음에, 실패하지 않도록 하기 위해 확인해봐야 한다.
- 버그를 테스트 할 때 실패하는 상황을 먼저 검증한 다음 버그를 수정해서 테스트 코드가 성공할 수 있도록 만드는 것이 중요하다.
- 실패하지 않는 테스트 코드는 하나 마다이다.
실행된 값을 예상하고 비교하는 검증 (Then)
- 가장 마지막에 두는 것이 좋다.
- 하나의 테스트 안에서 검사하는 것이 많다면, 하나의 테스트에서 다 검사하려고 하지 않나? 분리할 수 없는 지? 고민해야 함.
Triple A 단계
describe('ProductSerivce - Stub', () => {
let productService;
beforeEach(() => {
productService = new ProductService(new StubProductClient());
});
//테스트 코드 수행 전 호출되는 코드
it('should filter out only available items', async () => {
//arrange, give
const productService = new ProductService(new StubProductClient());
필요한 무언가를 준비하는 단계!
//act, when
const items = await productService.fetchAvailableItems();
테스트 코드를 실행하는 단계
//asert, then
expect(items.length).toBe(1);
expect(items).toEqual([{ item: '🥛', available: true }]);
조건이 맞아야 한다는 것을 검증하는 단계
});
});
코드로 보면 좀 더 쉽다.
주석을 남겨두는 경우도 있지만, 요즘엔 라이브러리가 좋기 때문에 요즘엔 거의 없다.
좋은 테스트의 원칙
FIRST 원칙
F : fast 의 약자. 테스트가 빠르게 수행될 수 있도록 만듦
느린것에 대한 의존성 낮추기. 빈번하게 테스트를 수행해야 하기 때문에.
파일, 데이터베이스, 네트워크 사용하지 않도록한다. (mock, stub 사용)
I : isolated 의 약자. 고립적 독립적으로 만들어야 한다.
최소한의 유닛으로 검증하기. 독립적이고 집중적으로 유지한다.
R : repeatable 의 약자. 반복이 가능하게 만들자.
실행할 때 마다 동일한 결과를 유지할 수 있도록.
다른 테스트 코드에 의존하거나, 네트워크나 내부적 환경에 의존한다면 달라질 수 있기 때문에
환경에 영향을 받지 않도록 작성하는 것이 중요하다.
S : Self-Validating 의 약자.
스스로 결과를 검증하기 스스로 테스트 할 수 있도록.
스스로 코드가 실행한 값과 예상하는 결과를 비교해야 함. (수동적 비교 XX)
(+) 자동화를 통한 검증 단계 (CI/CD) 우리 레포지토리에 추가하면 실행하고 자동으로 검증되게!
T : Timely 의 약자
시기 적절하게 테스트 코드를 작성
사용자에게 배포되기 "이전에" 테스트 코드 작성
무엇을 테스트 해야할 지 모를 때의 원칙
Right-BICEP
- 모든 요구사항이 정상 동작하는 지 확인
모든 결과가 정확한지 확인
B : Boundary conditions
모든 코너 케이스에 대해 테스트 하기
잘못된 포맷이 들어왔을 때, null, 특수문자, 잘못된 이메일, 큰 숫자, 중복, 순서가 맞지 않음
I : Inverse relationship
역관계를 적용해서 결과값을 확인
일관성을 유지 (덧셈 -> 뺄셈, 추가 -> 제거)
C : Cross-check
다른 수단을 이용해서 결과값이 맞는 지 확인
추가된 과일 = 전체 과일 - 예전의 과일 갯수
E : Error conditions
불행한 경로에 대해 잘 처리하는가?
네트워크 에러, 메모리 부족, 데이터베이스 중지
P : Performance characteristics
성능 확인은 테스트를 통해 정확한 수치로 확인한다!! (중요한 부분)
성능 개선의 척도와 확인도 데이터를 통해 확인
테스트의 조건
CORRECT
C : conformance 특정 포맷을 준수 (전화번호, 이메일, 아이디, 파일 확장자)
O : ordering 순서 조건 확인하기 순서가 중요한 경우.
R : Range 숫자의 범위 예상하는 input의 범위가 제한된 범위보다 작거나 큰 경우
R : Reference 외부 의존성 유무, 특정한 조건의 유무 (~일 때, ~가 되어 있을 때, 어떤 특정한 상황/상태일 때, 가정한 상황이 아닐 때?)
E : Existence 값이 존재하지 않을 때 어떻게 동작? null, undefined, '', 0
C : Cardinality 0-1-N 법칙에 따라 검증. 하나도 없을 때, 하나만 있을 때, 여러개 있을 때
T : Time 상대, 절대, 동시의 일들 (순서가 맞지않을 때, 소비한 시간, 지역 시간, 특정한경우에.)
'React' 카테고리의 다른 글
[react] 리액트 컴포넌트 테스트 (0) | 2024.06.19 |
---|---|
[react] TDD (0) | 2024.06.18 |
[react] TDD - 유닛테스트 (0) | 2024.06.17 |
[react] TDD - 테스트란? (1) | 2024.06.16 |
react-native mac에서 android 설정할 때 Error (0) | 2024.04.25 |