TDD 스터디를 마치고 실제 회사에서는 어떤 방식으로 테스트를 진행하는지 궁금증을 가지던 중에
인프런에 테스트에 대한 신규 강의와 수강평이 좋아 수강을 하게 되었다.
해당 글은 내가 테스트 강의를 들으면서 공감이 되는 부분을 중점으로 기술한다.
테스트는 왜 필요할까?
강사의 테스트 생각 : 귀찮다.
나의 생각 : 고려해야 할 것이 많다.
QA에 대한 테스트
- 커버할 수 없는 영역이 발생한다.
- 경험과 감에 의존한다.
- 늦은 피드백이 발생한다.
- 유지보수의 어려움
- 소프트웨어 신뢰도가 낮아진다.
테스트를 하는 이유
- 빠른 피드백
- 자동화
- 소프트웨어 신뢰도 상승
테스트 코드를 작성하지 않을 경우
- 변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 한다.
- 변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야한다.
- 빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.
테스트 코드가 병목이 된다면
- 프로덕션 코드의 안정성을 제공하기 힘들어진다.
- 테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.
- 잘못된 검증이 이루어질 가능성이 생긴다.
올바른 테스트 코드는
- 자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.
- 소프트웨어의 빠른 변화를 지원한다.
- 팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.
- 가까이 보면 느리지만, 멀리 보면 가장 빠르다. -> 소프트웨어의 검증이 코드로 한번 더 검증이 된다는 것은 질 좋은 소프트웨어임을 증명한다.
테스트하기 어려운 영역
- 관측할 때마다 다른 값에 의존하는 코드
- 현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등
- 외부 세계에 영향을 주는 코드
- 표준 출력, 메시지 발송, 데이터베이스에 기록하기 등
강의에서는 LocalDateTime.now()를 사용하지 않고 특정 시점에 대해서 테스트를 했다. 즉, 테스트를 할때마다 변하는 시간에 대해서 테스트를 하는 것은 올바른 설계가 아니다. (물론 예외 상황도 존재할 수 있다)
@NotBlank, @NotNull, @NotEmpty
- @NotNull = “ ”
- @NotEmpty = “”, “ “
- @NotBlank = 문자가 필수로 필요한 경우 (공백을 인정하지 않음)
컨트롤러에 필요한 Validation인지 Service에서 필요한 Validation처리인지 역할을 구분해야한다.
책임분리를 고려하여 Service의 dto와 controller의 dto를 분리할 수 있다.
나는 현재까지 @Valid에 대한 테스트를 컨트롤러가 아닌 Service Layer에서 처리했다. 이는 잘못된 설계였다. 강사님은 Controller와 Service에 대한 DTO도 분리하였다. (개인적으로 가장 많이 배운 설계) 객체 지향적 설계로 각각의 Layer는 다른 Layer에 종속적이지 않은 하나의 '모듈'이 되어야한다. Controller의 Request와 Service Request가 동일하지 않게 가져오는 것이 객체지향 SOLID에서 SRP원칙으로 하나의 클래스는 하나의 책임을 가지도록 했다. 하지만, 이는 특정 상황에 필요한 설계로 MSA와 같은 분리가 필요한 상황에서 필요하기에 프로젝트의 성격에 따라 다른 적절한 설계 방식을 사용해야한다.
Test Double - 이는 TDD 스터디에서 정리했기에 간단하게 정리한다.
Dummy : 아무 것도 하지 않는 깡통 객체
Fake : 단순한 형태로 동일한 기능은 수행하나, 프로덕션에서 쓰기에는 부족한 객체
Stub : 테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체 그 외에는 응답하지 않는다.
Spy : Stub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체 일부는 실제 객체처럼 일부만 Stubbing 할 수 있다.
Mock : 행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체
결론
강사님께서 강의중 가장 많이 이야기한 것은 "테스트는 문서다"이다.
현재 새로운 회사에서 개발을 임하면서 테스트에 대해서 깊게 생각을 하게 되었고 실제 다른 회사에서는 어떤 방식으로 테스트를 하는지 궁금하여 수강하게된 강의에서 많은 것을 배우면서 가장 많이 배운 것은 "테스트는 문서의 역할을 가지게 해야한다"이다. 현재 내가 맡은 프로젝트의 이전 개발자는 코드에 대해서 컨벤션도 엉망이며 테스트는 물론 코드에 대한 메타 데이터도 존재하지 않다. 이를 하나하나 이해하며 새롭게 바꾸면서 테스트 코드의 중요성을 깨우치고 있다. 단순히 테스트 코드는 나에게 빌드할때 한번 더 검증하는 수단이었으나, 테스트 코드는 이 프로젝트를 맡게되는 이후의 개발자와의 소통이다. 테스트 코드를 통해 로직의 깊이 있게 검증하며 이해할 수 있다. 실제로, TDD 스터디를 통해 테스트 로직이 얼마나 비즈니스 로직을 이해하는 것에 도움이 된다는 것을 몸소 느겼다. 테스트는 그 어떠한 설명서보다 이해하기 쉽게 만들어지는 소프트웨어의 설명서이다.
출처