단위 테스트 사용 방법: Junit 참조 가이드
Gradle 프로젝트에 jacoco 설정하기 | 우아한 형제들
중구난방 테스트 코드 통일하자
AS-IS
Controller -> RestDocs 기반 통합 테스트 진행
Service → DB 혹은 다른 Layer와 의존성을 가지는 단위 테스트와 Mock 기반 테스트가 혼재되어 있음
Repository → 일부 작성
Entity, Dto → 미작성
Utils → 일부 작성
Github Pre-Commit (git hook 을 활용한 pre commit, pre push) - Remote Branch Push 전 테스트 강제
Jenkins 배포 시점 ( 현재 Gradle 빌드 시점에 Default로 적용되고 있음 )
구현 코드의 패키지 구조와 동일하게 구성
Unit test naming best practices - 단위 테스트 명명 규칙 모범 사례
Naming standards for unit tests - Roy Osherove - 애자일 컨설턴트의 단위 테스트 명명 규칙 가이드
[TDD/스크랩&번역] 7가지 유닛테스트 네이밍 - 7가지 유닛테스트 네이밍
클래스
테스트 대상 클래스 이름 + Test
Ex.
MembersControllerTest ( Controller )
MembersServiceTest ( Service )
BusinessMembersRepositoryTest ( Repository )
PasswordUtilsTest ( Utils )
메서드
메서드명테스트상태기대결과 (Ex. isAdult_AgeLessThan18_False)
-> 코드 리팩토링으로 메서드명 변경시 테스트명 또한 변경되어야 한다.
메서드명기대결과테스트상태 (Ex. isAdult_False_AgeLessThan18)
-> 1번과 비슷한 형태지만, 일부 개발자들은 해당 컨벤션 사용을 추천, 메서드명 변경시 테스트명또한 변경되어야한다.
test[테스트할 기능](Ex. testIsNotAnAdultIfAgeLessThan18)
-> 테스트할 기능이 테스트명의 일부로 사용되어 쉽게 읽을 수 있도록 해 준다. 그러나 "테스트" 접두사가 중복된다는 주장도 있다.
테스트할 기능
→ 테스트할 기능만 간단하게 쓰는 것이 더 낫다는 의견이 많다. 또한 코드의 악취를 방지하고, 문서화된 형태의 유닛 테스트를 수행하므로 권장되는 방법이다.
should기대결과_When테스트상태 (Ex. IsNotAnAdultIfAgeLessThan18)
-> 이러한 형태의 네이밍은 많은 사람들이 테스트에 대해 쉽게 이해할 수 있기 때문에 많이 사용된다.
when테스트상태_Expect기대결과
-> should_ThrowException_When_AgeLessThan18
given사전조건_When테스트상태Expect기대결과
-> BDD 기반의 네이밍 컨벤션이지만 테스트명이 너무 길어진다.
Ex.Given_UserIsAuthenticated_When_InvalidAccountNumberIsUsedToWithdrawMoney_Then_TransactionsWillFail
Dev-Tips/Spring-Boot-레이어별 테스트.md - (Naver Z) Layer 별 테스트
Controller - RestDocs를 이용하여 테스트 코드 작성중(강제)이며 @SpringBootTest 를 이용한 통합테스트로 작성한다.
Service -
테스트 하고자 하는 포인트에 집중할 수 있도록 Service Layer외에 모든 의존성을 끊어야 한다고 생각한다. 다른 Layer 개입하는 순간 Service 비즈니스 로직 테스트에 대한 관점이 흐려지고 타 Layer 를 신경쓰게 된다. (JPA Flush 존재하는 부분은 어떻게 테스트 할 것인가?)
각 테스트에는 given, when, then 으로 나누어 무엇을 기반으로, 어떤 것을 테스트 했을때, 어떤 결과를 기대하는지, 명확히 알 수 있도록 작성한다.
다른 Layer(Repository 혹은 다른 Service) 의존관계는 Mock 처리하며, DB 데이터검증은 Repository 테스트에서 진행한다.
Repository - @DataJpaTest 이용 하여 In-Memory 기반 테스트 코드 작성을 통해 나머지 Layer와 의존성을 끊자 (Repository ↔︎ Database)
Dto, Entity - Dto, Entity의 경우 클래스 내부 멤버 메서드들에 대한 코드 작성 필요 (Valid 관련 부분도 테스트 해야하나?)
Utils - AssertJ 기반 테스트 진행
Jacoco 이용해서 테스트 커버리지가 일정수치 넘지 않으면 commit 되지 않아야 하지 않을까? 너무 빡빡한가
Testable Code - 테스트 하기 쉬운 코드
How to Write more testable code - 어떻게 더 테스트하기 쉽게 코드를 작성할 수 있는가?
Service Layer의 단위 테스트를 진행할 때, 메서드의 호출 여부와 더불어 해당 메서드의 반환 값을 통해 테스트 유효성 검증이 일어나게 된다. 이 때 메서드의 반환 값이 void 일 경우 테스트 검증을 단순 메서드 호출여부로만 이루어져야 하기 때문에 테스트에 적합한 메서드의 리턴 값이 필요하다.
Select - 조회 대상 리턴
Insert - 생성된 데이터 혹은 키 값 리턴
Update - 업데이트 데이터 리턴
Delete - 삭제 대상 데이터 혹은 키 값 리턴