1. 개요
1) 단위테스트와 협력객체
단위테스트의 특징
- 작은 코드 조각(단위)를 검증한다
- 빠르게 수행 가능하다
- 격리된 방식으로 처리한다
통합과 고립(Sociable and Solitary)
- 협력 객체를 실제 객체로 사용하는지(통합) 또는 Mock 객체로 사용하는지(격리)에 따라 테스트 구현이 달라진다
- 협력 객체가 없는 단위테스트는 작성하기가 쉽다.
2) 테스트 대역 (Test Double)
- 실제 객체 대신 사용되는 모든 종류의 객체에 대한 일반 용어
- 즉, 실제를 가짜로 대체한 것
- 대역 종류 (참고링크)
- 1) Stub: 지정한 응답을 주는 객체 (간접 입력)
- 2) Fake: 의존성 계약을 준수하는 가벼운 구현체 (테스트용 가짜 객체)
- 3) Mock: 테스트 대상 내부의 행위(상호작용)을 검증
- 4) Spy: 테스트 대상의 간접 출력을 기록
3) 협력 객체를 어떻게 구성할 것인가?
1. 가짜 객체(테스트 대역)를 사용하는 경우
- 장점: 테스트 대상을 검증할 때 외부 요인으로부터 격리할 수 있다
- 단점: 테스트가 협력 객체의 구현에 의존적이게 된다
2. 실제 객체를 사용하는 경우
- 장점
- 협력 객체의 구현에 의존하지 않는다
- 테스트 코드가 프로덕션 코드에 덜 의존적이므로 유지보수성이 높아진다
- 단점: 테스트가 협력 객체의 정상 동작 여부에 영향을 받게 된다
4) TDD 방식: Outside In vs Inside Out
1. Outside In (컨트롤러 -> 도메인)
- OOP와 TDD가 익숙하지 않은 사람들이 쉽게 시작할 수 있다
- 도메인에 대한 이해가 높지 않은 상태에서 진행이 가능하다
2. Inside Out (도메인 -> 컨트롤러)
- 도메인 설계가 충분히 이루어진 다음에 코드를 작성할 수 있다
- TDD 사이클을 이어나가기가 상대적으로 어렵다
- 프로덕션 코드에 덜 의존적인 테스트가 작성된다
2. 2주차 리뷰
1) 피드백
테스트에서만 사용되는 프로덕션 코드를 허용해도 될까?
- 테스트만을 위한 프로덕션 코드는 지양하는 것이 좋다
- 하지만 과하게 사용하는 것이 아니라면 제한적으로 허용하는 것이 좋다
- ex) 단위테스트를 위해 JPA 엔티티에 ID를 포함한 생성자 추가
- 그러나 반드시 필요한 것이 아닐 수 있으므로 다른 방법도 고민해보자
- ex) JPA 엔티티에 ID를 포함한 생성자 추가하는 방식 대신 equals와 hashCode 재정의
의존
- 의존은 무조건적으로 안 좋은 것이 아니다
- 의존이 없으면 하나의 객체가 모든 것을 다 처리해야 하므로 너무 비대해질 수 있다
- 하지만 의존이 너무 많아지면 변경 요구사항이 발생할 때 복잡해지는 문제가 있다
- 따라서 객체간의 책임을 잘 생각해보고 적절하게 분리하는 것이 좋다
- 불필요한 의존은 반드시 제거하자
- Service에서 다른 Service를 의존하기 vs Repository를 의존하기
2) PR
- https://github.com/next-step/atdd-subway-path/pull/445
- https://github.com/next-step/atdd-subway-path/pull/469
- https://github.com/next-step/atdd-subway-path/pull/484
3) 리뷰 정리
- 매직 리터럴은 상수로 분리하자
- 블럭 없는 분기문은 가독성과 코드의 일관성 측면에서 좋지 않다
- 명확한 종료 조건이 없는 무한 반복문은 사용을 지양하자
- NPE를 방지하기 위해 엔티티의 필드 초기화를 해주자 (일급 컬렉션 포함)
- 메서드 하나의 길이는 15라인 이하로 작성하는 것이 가독성 측면에서 좋다
- 구현을 노출시키는 메서드 시그니쳐를 지양하자
- 매개변수 전달 영역에 로직을 작성하면 가독성과 디버깅 측면에서 좋지 않다
public class PathResponse {
// ...
// 매개변수에 로직을 작성한 예
public static PathResponse of(List<Station> stations, double distance) {
return new PathResponse(
stations.stream()
.map(StationResponse::from)
.collect(Collectors.toList())
, (int) distance
);
}
}
3. 느낀 점
이번 주차 미션은 2주동안 진행되었다. 평소 코드의 간소화를 위해 매개변수 전달 영역에 로직을 작성하는 경향이 있었는데, 리뷰를 통해 고칠 수 있는 계기(?)가 되었다. 일급컬렉션 같은 경우엔 1주차 미션에서도 사용을 권고받아서 이번에 처음 사용해봤는데, 컬렉션이 도메인 로직을 가질 수 있다는 측면이 좋았던 것 같다. 실제로 실무에 적용했더니 코드의 응집성이 높아지는 효과와 단위테스트 작성이 쉬워지는 효과를 경험할 수 있었다. 여러모로 도움이 되었던 2주차 미션이었다.
'테스트코드 > ATDD, 클린 코드 with Spring' 카테고리의 다른 글
[ATDD, 클린 코드 with Spring 6기] 4주차 정리 (2) | 2023.03.13 |
---|---|
[ATDD, 클린 코드 with Spring 6기] 3주차 정리 (0) | 2023.03.02 |
[ATDD, 클린 코드 with Spring 6기] 1주차 정리 (0) | 2023.02.05 |