FIRST : 좋은 테스트 조건이란?
- [F]ast
테스트는 빠르게 동작해야 한다. 느린 것에 의존하는 코드를 최소화하자. - [I]solated
직접적 혹은 간접적으로 테스트 코드와 상호 작용하는 코드가 많을수록 문제가 발생할 소지가 늘어난다. 다른 단위 테스트에 의존하지 않는 결합도를 낮은 테스트 코드를 작성하자.
각 테스트가 작은 양의 동작에만 집중하면 독립적인 테스트 코드로 유지하기 쉽다. 테스트 코드에도 단일 책임 원칙을 적용하자. 테스트 메서드가 하나 이상의 이유로 깨진다면 테스트를 분할하는 것을 고려하자. - [R]epeatable
테스트는 실행할 때마다 결과가 같아야 한다. 반복 가능한 테스트를 만들려면 직접 통제할 수 없는 외부 환경에 있는 항목들과 최대한 격리시켜야 한다. - [S]elf-validating
테스트는 스스로 검증 가능할 뿐만 아니라 준비할 수 있어야 한다. 테스트에 필요한 설정 단계를 자동화 해야 한다. - [T]imely
언제라도 단위 테스트를 작성해야 한다. 대규모의 개발을 할수록 단위 테스트를 미루면 안 된다.
Right-BICEP : 무엇을 테스트 할 것인가?
좋은 단위 테스트는 단지 코드에 존재하는 로직 전체에 대한 커버리지를 달성하는 것이 아니다. 때때로 작은 창의력을 꺼내는 노력이 필요하다. 끔찍한 결함들은 전혀 예상하지 못한 곳에서 나온다.
- [Right] (결과가 올바른가?)
테스트 코드는 무엇보다도 먼저 기대한 결과를 산출하는지 검증할 수 있어야 한다. - [B]oundary conditions (경계 조건)
입력 값의 양극단을 다루는 테스트 시나리오를 작성하라. 경계 조건은 다음과 같다.- 모호하고 일관성 없는 값(특수문자가 포함된 이름 파일)
- 잘못된 양식의 데이터(이메일 주소)
- 수치적으로 오버플로우를 일으키는 계산
- 비거나 빠진 값(0 또는 null)
- 이성적인 기댓값을 훨씬 벗어나는 값(나이 150세)
- 중복을 허용해서는 안 되는 경우
- 정렬이 안 된 리스트 혹은 그 반대
- 시간 순이 맞지 않는 경우
- [I]nverse relationship (역 관계)
역 관계를 검사한다. 논리적인 역 관계나 수학 계산에서 사용한다. - [C]ross-check (교차 검사)
다른 수단을 활용하여 교차 검사를 한다. 수많은 검증 방법 중 가장 효율적인 '1등 해법'만 프로덕션 테스트 코드로 선택되겠지만, 다른 방법들을 이용해 1등 해법을 교차 검사를 수행한다. - [E]rror conditions (오류 조건)
오류 조건을 강제로 일으키는 검사를 한다. 우리는 테스트 코드로 모든 실전 문제를 우아하고 이성적인 방식으로 다루기 원한다. 그렇게 하려면 테스트도 강제로 오류를 발생시켜야 한다. 고려해야 하는 몇 가지 시나리오는 다음과 같다.- 메모리가 부족할 때
- 디스크 공간이 부족할 때
- 벽시계 시간(서버와 클라이언트 간 시간이 달라서 발생하는 문제)에 관한 문제들
- 네트워크 가용성 및 오류들
- 시스템 로드
- 제한된 색상 팔레트
- 매우 높거나 낮은 비디오 해상도
- [P]erformance characteristics (성능)
성능 조건은 기준에 부합하는지 검사한다. 추측만으로 성능 문제에 바로 대응하기보다는 단위 테스트를 설계하여 진짜 문제가 어디에 있으며 예상한 변경 사항으로 어떤 차이가 생겼는지 파악해야 한다. 성능이 핵심 고려 사항이라면 단위 테스트보다는 좀 더 고수준에서 문제에 집중하는 것이 좋다. JMeter나 JUnitPerf 같은 서드파티 도구를 이용하자.
CORRECT : 경계 조건 암기법
- [C]onformance (준수)
많은 데이터가 특정 양식을 따라야 한다. 입력 값이 기대한 양식을 준수하고 있는지 확인하자. 브레인 스토밍을 통해 빠르게 더 많은 확인 방법을 떠올릴 수 있다. - [O]rdering (순서)
데이터 순서 혹은 컬렉션에 있는 데이터 한 조각의 위치는 쉽게 잘못될 수 있다. - [R]ange (범위)
기본형 자료형의 과도한 사용은 기본형 중독(primitive obession)을 야기한다. 자바 같은 객체 지향 언어의 장점은 사용자 정의 추상화를 클래스로 만들 수 있다는 점이다. 이를 활용해서 값의 범위를 제한하도록 하자.- 시작과 마지막 인덱스가 같으면 안 된다.
- 시작이 마지막보다 크면 안 된다.
- 인덱스는 음수가 아니어야 한다.
- 인덱스가 허용된 것보다 크면 안 된다.
- 개수가 실제 항목 개수와 맞아야 한다.
- [R]eference (참조)
어떤 상태에 대해 가정할 때는 그 가정이 맞지 않으면 코드가 합리적으로 잘 동작하는지 검사해야 한다.(??) 예를 들어 '주행 중에 주차로 기어 변속 요청을 무시하는가', '차량이 움직이지 않으면 주차로 기어 변속을 허용하는가' 같은 시나리오이다. - [E]xistence (존재)
주어진 값이 존재하는 가를 테스트한다. 스스로 물어봄으로써 잠재적인 결함을 발견할 수 있다. 어떤 인자나 필드 메서드 값이 null, blank 혹은 0 이라면 어떤 일이 일어날지 테스트한다. - [C]ardinality (기수)
'존재'의 '일부', '없음' 보다 더 구체적인 답변을 얻을 수 있는 기술적으로 특수한 '존재'인 기수이다. 0-1-n 법칙을 사용해 테스트한다. 항목이 없을 때, 하나만 존재할 때, 여러 개 존재할 때 테스트를 나누어 다루자. - [T]ime (시간)
메서드들의 호출 순서가 맞는지, 맞지 않았을 때 어떤 일이 일어날지 테스트한다. 또 상대적인 timeout 문제를 포함할 수 있다. 수명이 짧은 자원에 대해 코드가 얼마나 기다릴 수 있는지 결정해야 한다. 마지막으로 시간에 따라 서서히 퍼지는 문제점으로 동시성과 동기화된 접근 맥락에 관한 문제가 있다.
'Develop > Java' 카테고리의 다른 글
[Java] Lambda, Functional Interface 그리고 Stream API (0) | 2023.09.08 |
---|---|
Java JVM 아키텍쳐 (1) (2) | 2023.07.16 |
[Java] String to Json 파싱하기 | Jackson ObjectMapper (0) | 2023.04.02 |
TDD 테스트 주도 개발 (0) | 2023.02.19 |
SOLID 클래스 설계 원칙 (0) | 2023.02.13 |