자바 유닛 단위 테스트
단위 테스트시 빠르게 코드를 점검할 수 있다
테스트클래스의 이름은 테스트할 클래스 이름 앞이 test를 붙여서 명명한다
asserThat으로 해당 값이 맞는지 판단한다 TDD 개발을 위해서 악의적인 테스트 실패코드를 작성해야한다
대부분의 단언은 실제 값과 비교한다
테스트 코드일 경우에는 try/catch보다는 예외를 던지는 방식으로 코딩해라
태스트 코드를 AAA방식으로 일관성 유지한다.(준비 실행 단언) 추가적으로 사후 단계도 필요하다(할당했던 자원 정리)
단위테스트는 개별 메소드 테스트가 아니라 클래스의 종합적인 동작을 테스트 해야한다
코드구조는 테스트를 별도의 디렉토리로 분리하지만 같은 패키지에 넣는다. 메이븐에서도 이를 권장함.
코드의 작은 변화가 수많은 테스트 코드를 깨트린다. 프로그래머는 당황한다. 일이 계속 많아질 수 있어서 프로덕션 코드의 리팩토링을 꺼리게 된다.
프라이빗메소드를 테스트 하는것은 설계가 잘못된걱이다. 차라리 private 메소드를 추출하여 다른 클래스로 이동시키면 그 클래스의 유용한 퍼블릭 메소드가 된다
일관성있는 이름으로 테스트 문서화
테스트 하려는 맥락을 제안하기 보다는 어떤 맥락에서 일련의 행동을 호출했을 때 어떤 결과가 나오는 지를 명시하세요.
makeSingleWithdrawal -> withdrawalReducesBalanceByWithdrawnAmount
multipleDeposits -> multipleDepositsIncreaseBalanceBySumOfDeposits
단어 7개정도로 길수 있다.
@Before 은 매번 테스트 메서드 실행에 앞서 실행된다. 여러개의 @Before을 선언할 수도 있지만 실행순서를 보장하지 않는다.
@After 은 테스트에 발생하는 부산물들을 정리하는 역할을 한다.
테스트는 항상 녹색을 유지해야한다. 이를 위해서는 빠른 테스트가 중요하다. 만약 외부 자원(DB)에 접근하는 테스트가 많다면 속도가 느려진다. JUnit은 Categories기능을 제공하여 특정 카테고리에 해당하는 테스트만 별도로 실행 할 수 있다.
만약 테스트를 제외시키고 싶다면 주석이 아닌 @Ignore 어노테이션을 달아라. 주석을 쳐버리면 나중에 잊어버리기 때문에 관리가 어렵다.
문제 있는 테스트코드
- 테스트를 사용하는 사람에게 어떤 정보도 주지 못하는 테스트
- 산발적으로 실패하는 테스트
- 어떤 가치도 증명하지 못하는 테스트
- 실행하는 데 오래 걸리는 테스트
- 코드를 충분히 커버하지 못하는 테스트
- 구현과 강하게 결합되어 있는 테스트, 따라서 작은 변화에도 다수의 테스트가 깨진다.
- 수많은 설정 고리로 점프하는 난해한 테스트
좋은 테스트의 FIRST속성
Fast : 빠른
Isolated : 고립된
Repeatable : 반복 가능한
Self-validating : 스스로 검증 가능한
Timely : 적시의
=> 테스트 코드를 먼저 작성하고 코드를 작성한다. 이것을 TDD라고 한다.
F
테스트를 만들다 보면 외부 자원을 사용하게 되고 이는 테스트를 느리게 한다. 그렇다 보니 2500개의 테스트 실행에 8분 이상이 걸릴수 있다.
우선 가장 먼저 느린 테스트에 대한 의존성을 줄여야한다. 모든 테스트가 DB자원을 사용하면 전체 테스트가 느려질 것이다.
따라서 컨트롤러에 질의하지 않고 먼저 데이터를 가져오고, 그 데이터를 메서드의 인수로 넘긴다.
그럼 영속성 저장소는 조회하지 않고 메모리상의 해쉬맵만 사용하여 테스트를 할 수 있다.
즉, 코드를 클린 객체 지향 설계 개념과 맞출 수록 단위 테스트 작성도 쉬워진다.
I
직간접적으로 테스트 코드와 상호작용하는 코드가 많을 수록 문제가 발생할 소지가 늘어난다.
외부저장소와 상호작용하는 코드가 있다면 가용성 혹은 접근성 이슈로 실패할 가능성이 있다.
따라서 테스트 코드는 어떤 순서나 시간에 관계없이 실행 할 수 있어야한다. 따라서 작은 양의 동자게만 집중하면 테스트 코드를 집중적이고 독립적으로 유지하기 쉬워진다.
테스트도 SRP원칙을 가지면 좋다. 만약 하나이상의 이유로 테스트가 깨진다면 분할을 고려해라
R
반복 가능한 테스트는 실핼 할 때마다 결과가 같아야한다. 따라서 반복 가능한 테스트를 만들려면 직접 통제할 수 없는 외부 환경에 있는 항목들과 격리시켜야 한다.
S
테스트는 스스로 검증 가능해야한다. 따라서 로그를 통한 검증이 아닌 기대하는 것이 무엇인지 단언하는 형태가 되어 자동화되어야한다.
T
단위 테스트로 코드를 검증하는 것을 미룰수록 문제는 가라앉기만 한다. 소스 저장소에 올려놓으면 그것을 되돌려 테스트를 작성하기는 더 까다로워진다.
이렇다 보니 어떤 팀에서는 리뷰 프로세스, 심지어 충분한 테스트가 없을 때 코드를 거부하는 자동화된 도구도 사용한다.
(*옛날 코드에 대한 테스트는 시간 낭비가 될 수도 있다. 큰 결함이 없다면 말썽이 많은 역동적인 부분에 TDD를 적용해라)
'개발' 카테고리의 다른 글
[Java] static과 final의 차이가 뭘까?(feat. JVM 메모리) (2) | 2022.03.07 |
---|---|
JAVA의 스레드를 공부하자 (0) | 2022.02.26 |
[JUnit5] JUnit5를 공부해보자(Spring Boot, REST API) (0) | 2022.02.24 |
JAVA의 Servlet이 뭐지? (0) | 2022.02.19 |
JAVA 인터페이스는 왜 쓰는 걸까? (0) | 2022.02.18 |