- 안정감과 자신감
- 대상은? 현재와 미래의 나, 동료
- 요구사항
- 6개의 숫자를 반환, 중복되지 않는 숫자, 랜덤하게 반환
- 질문) 중복에 대해서도 테스트 되어야 하지 않을까요?
- 대답) 저는 Set 으로 구현해서 중복이 나올 수 가 없어요
- 위는 잘못됐다. 왜냐면 구현은 언젠가 어떻게든 변할 수 있기때문이다. (미래의 내가 망각할 수도, 미래 동료가 바꿀수도) -> 구현이 아닌 비즈니스 설계사항을 테스트해야지 안정감, 자신감을 얻을 수 있다
- 만약 private 메서드를 public 메서드로 바꿔서 테스트하고자하면 구현테스트를 하고 있을 가능성이 매우 큼
- 이럴경우에는 그 행위를 가지고 있는 안쪽의 비즈니스 테스트만 더해질 안쪽을 들여다볼 필요는없다. 만약 추가하는게 어색하다면 private 메서드가 안쪽에 있는게 이상한걸수도 ..
즉 요약하면, 우리가 구현이 아니라, 설계를 테스트해야한다.
-
"제어할 수 없는 영역"
-
예시
- Radndom, Shuffle, LocalDate.now()
- 외부 세계
- HTTP
- 외부 저장소
-
왜 테스트하기 힘든지?
- 테스트는 고정되어있는데 그사이에 외부세계는 변화될 수 있다. 그럴때 테스트가 실패하게된다.
- 제어할 수 없는 영역은 멱등한 결과를 보장할 수 없다.
-
로또 예제
"항상 성공할 수 있는것 항상 동일한 결과가 나올 수 있는 것을 테스트"
- 무엇을 테스트할것인가?
- 설계를 테스트하자.
- 항상 동일한 결과가 나올 수 있는것을 테스트하자.
테스트할 수 없는 메서드는 테트할 수 있는 메서드까지 오염을 시킨다.
![image-20230122170934084](../../../Library/Application Support/typora-user-images/image-20230122170934084.png)
![image-20230122170955938](../../../Library/Application Support/typora-user-images/image-20230122170955938.png)
- 여기서 가장 안쪽 있는 메서드에 LocalDateTime.now()는 제어할 수 없는 영역이 있다. -> 결국 전체가 테스트할 수 없는 코드로 오염이된다.
- isValid를 인수를 받을 수 있게 변경한다. 넘겨진 시간에 의해 제어가 되므로 테스트할 수 있게된다.
![image-20230122172936719](../../../Library/Application Support/typora-user-images/image-20230122172936719.png)
- 계속 올린다. 어디까지 올릴것인가?
- 여기서 Boundary Layer란? 한 모듈로서의 의미를 지니는 가장 바깥 쪽 (이건 설계에 따라 딱 정의하기 힘든 부분)
- ![image-20230122173144723](../../../Library/Application Support/typora-user-images/image-20230122173144723.png)
즉 "테스트 불가능한 영역을 Boundary Layer로 올려서 테스트 가능하도록 변경"
@SpringBootTest
"Context, Framework 종속적이지 않은 테스트 우선"
Test Double은 테스트 할 수 없는 영역에 대한 외부 요인을 부여할 수 있도록 도와줌
-
무엇을 Test Double로 처리해야할까?
-
그럼 Test Double을 어떻게 쓰지?
- Boundary Context 까지 끌어올렸는데 테스트할 수 없는 영역이 존재할때
- 편리하지만 사용을 의식하여 최소화
- 순수 자바 어플리케이션으로는 테스트할 수 없는 것
- -> 대부분 Embedded로 가능
- ex) 저장소 입출력검증(쿼리 잘나가는지), SPEC 검증(내부 controller, 외부 API)
- 종류
- Spring Framework Support
- MockMvc, REST Assured, WebTestClient
- 테스트의 목적은 요청과 응답 스팩 검증만으로 제한하는게 정신 건강에 좋을것이라고 생각 (뒤를 아예 모르게)
- 테스트간 서로 영향을 미치지 않도록 상호 독립적으로 작성
- 모든 테스트의 순서와 관계를 생각하여 테스트를 작성하기 어려움
- 공유되는 자원은 초기화하여 다른 테스트에 영향을 받지 않도록
- 단계가 필요하다면 JUnit5 의 Dynamic Testfㅡㄹ 추천
- 테스트 안에 의도와 목적이 들어나도록 작성
- 어떤 조건에서, 무엇을 수행했을때, 어떤 결과가 나올지 알 수 있어야한다. (개인적으로 @Before에 적으면 파악하기 힘듬)
- 테스트 코드 역시 가독이 중요
- 테스트 코드도 리팩토링 대상
- 코드양에 대한 이야기가 아닌 가 안정성, 요구사항 정리등 비즈니스 코드와 동일한 수준의 리팩토링이 함께 이루어져야 한다.