이번 미션을 하면서 페어의 코드를 이어서 작업을 했다. 그러면서 또 많이 배웠다. 이때까지 사실 테스트 코드를 깔끔하게 유지하려는 노력을 많이 하지 않았다. 그래서 프로덕션 코드를 유지보수하는 것보다 테스트 코드를 유지보수하는게 더 노력이 많이 들어서 테스트를 작성하기 싫을때가 있었다. 하지만 페어의 코드에는 테스트 코드도 깔끔하게 유지하려는 모습이 많이 보였고, 실제로 테스트 하기가 좋았다.
지난 번 지하철 노선도 미션에서 리뷰어께서 각 테스트들의 중복된 속성을 제거해보라고 하셨다. 그래서 AcceptanceTest에 공통적으로 필요한 속성들을 정의해놓고 AcceptanceTest를 상속받아서 그 속성들을 사용함으로써 테스트 간 중복을 줄였다.
브라운의 ATDD 강의에서도 나온 얘기지만 인수테스트에서는 상황이 복잡할 수 있고 그에따라 테스트 코드도 복잡해질 수 있으니 가독성에 신경 써야 한다.
나의 코드
정말 그냥 그대로 RestAssured를 썼다. 이게 메서드를 통해서 노선을 생성하고 검증하는 하나의 코드다.
페어 코드
httpPost라는 메서드를 이용해서 요청하고 응답을 받는 과정을 메서드로 분리하였다.
예시 코드에서는 한번 요청을 보내고 응답을 받는 상황이지만, 여러번 요청을 보내는 상황이면 이렇게 메서드로 분리를 하면 가독성이 많이 향상될 것이다.
반대로 단순한 상황이면 RestAssured 내에서 then() 뒤에 헤더필드, 상태값 등을 검증할 수 있으니 그걸 써도 좋을 것 같다.
픽스처 관리를 하지 않은 코드1
픽스처 관리를 하지 않은 코드2
위의 코드는 픽스처 관리를 하지 않아 테스트 클래스 별 중복이 많이 발생했다.
픽스처 관리를 한 코드
이런식으로 픽스처 관리를 해주면 여러 테스트에서 공용으로 사용할 수 있다.
테스트 코드를 작성할 때 메서드명이나 변수에 한글을 적절히 섞으면 가독성이 더 좋아지는 것을 체감했다. 특히 한글로 된 이름을 영어로 (강남 -> gangnam) 이런식으로 작성하는 것보다 아예 한글로 적는 것이 더 낫다.
JsonPath는 독립적으로 존재하는 라이브러리지만 RestAssured에도 내장되어있다.
만약 JsonPath를 사용하지 않았다고 생각해보자. 응답이 내부적으로 구조가 복잡하다면 body에서 x.get().get()... 등으로 파고 들어가야 한다.
JsonPath를 사용하니 Json 구조에서 원하는 부분만 가져올 수 있다. 원하는 부분만 가져온 뒤 AssertJ의 extracting()을 활용하면 더 쉽게 필드를 가져올 수 있다.
실제 결과값 그룹에서 길이가 얼마나인지 테스트한다. 페어와 코드를 하나보니 항상 리스트로 결과가 나오는 경우 hasSize()로 기본적으로 길이 체크를 하고 거기에 이어서 내용도 검증을 해줬다. 좋은 것 같다.
AssertJ에서 유용한 기능 중 하나이다.
여러 필드를 가지고 있는 객체들의 리스트가 있다고 가정하자. 이 리스트에서 특정 필드 값만 뽑아서 비교를 할 때 extracting을 사용할 수 있다. 실제로 위의 예시 코드에서도 Response에서 stations를 뽑아온뒤 거기서 name 필드들만 다 뽑아오고 있다.
참고 블로그 - AssertJ 필수 기능 정리 (JAVA)
extracting을 이용해서 일부 필드값만 추출하니 예전의 객체와 바로 비교할 수 없다. 그래서 이렇게 임시로 객체 형식을 만들어 줄 수 있따.
예시 코드에서는 containsExactly를 사용하고 있다. 그래서 결과값이 정확히 다른 것을 포함하지 않고 순서대로 주어진 인자만을 가지고 있는지 테스트할 수 있다.
원래는 속성 중 id 값만을 이용해서 eq/hc를 재정의 했다. 하지만 db에 저장되지 않았을 때는 id 속성을 가지지 않는다. 테스트를 위해서 id를 억지로 넣어주기보다 다른 방식으로 비교할 수 있다.
또한 Dto와 도메인을 비교할 때 타입이 다르지만 필드는 거의 비슷하기 때문에 유용하게 사용할 수 있다.
내부적으로 필드 대 필드를 재귀적으로 비교한다.
예시에서는 내부 필드인 stations는 빼고 비교하게 만들었다.
👍👍👍👍