박종훈 기술블로그

테스트 주도 개발 (TDD) 스터디 2회차 (9-17장)

테스트 주도 개발 - 켄트 벡

tdd-korean-book-cover


테스트 속도 조절하기

p96.

Franc 생성자에서 currency를 받도록 수정하였더니 Money의 franc 팩토리 메소드와 times 메소드 두 곳이 깨짐

(갑자기 든 생각 : times에도 팩토리 메소드를 넣으면 좋지 않을까?, 안그러면 약쪽에 다 “currency”를 하드코딩 해줘야 함.) 지금 이걸 고쳐야 하나? 아니면 지금 하는일이 끝날때까지 기다려야 할까? 원칙적으로는 기다리는 것이 맞음. 하지만 나는 짧은 중단이 필요할 경우에는 흔쾌히 받아들인다.

times를 먼저 수정 -> franc 팩토리 에서 currency를 전달할 수 있게됨.

하기로 한 것 끝까지 하는 것이 좋은 것인가? 중간에 더 좋은 방향이 있으면 변경 하는 것이 좋은 것인가?

혼자서 할 때 여럿이서 할 때에 따라 다르려나? 나 혼자서도 할때도 엄격하게 해야할까?

상황에 따라 속도를 조절. 테스트 사이의 간격 조절하기

불안하면 스텝 간격을 좁게 자신있으면 스텝 간격을 넓게

TDD가 경제적으로 되려면

p 145.

TDD로 구현할 땐 테스트 코드의 줄 수와 모델 코드의 줄 수가 거의 비슷한 상태로 끝난다. TDD가 경제적이기 위해서는 매일 만들어 내는 코드의 줄 수가 두 배가 되거나 동일한 기능을 구현하되 절반의 줄 수로 해내야 할 것이다

처음에 무슨 뜻인지 잘 이해가 안되었음.

처음에는 중복을 제거하란건가 싶기도 했는데 지금은 다음과 같이 이해했음.

본문에 따르면 내가 평소에 짜는 코드의 양이 1이라 했을 때, TDD를 사용했을 때 테스트 코드의 줄 수와 모델 코드의 줄 수가 거의 비슷한 상태라고 했으므로 각각 0.5 / 0.5 라고 볼 수 있다. 따라서 TDD를 사용하면서도 평소 작업량을 맞추려면 (경제적 이기 위해선) 코드의 줄수를 2배로 늘려서 1을 맞추거나 동일한 기능을 절반의 줄 수로 해내야 한다는 이야기라고 생각된다.

따라서 TDD를 적용하였을 때 작업량이 어떠한지 비용계산을 해봐야 한다는 뜻으로 보인다.

이 부분을 읽고 생각 난 것이 (직접적인 연관성은 없지만)
최근에 유명 IT 업체의 QA 분과 이야기를 할 기회가 있었다.

회사의 개발 문화(특히 테스트와 관련된)에 대해서 이야기를 하다가 말씀해주시길 사실 개발자들이 테스트 코드를 잘 안 짠다고 이야기 해주셨다.
왜냐하면 피쳐를 개발하기도 바쁘기 때문에 테스트 코드 짤 시간이 없다는 것이다.
대신 QA, TE 들이 안정성을 보장하기 위해 투입된다고 이야기 해주셨다.

이러한 상황 가운데서
문제 발생하면 QA 가 미리 못 발견해서, 문제 없으면 개발자가 잘 개발해둬서
가 되버리는 경우가 많다는 것이다.

물론 회사마다 다를 것이고, 부서마다 다를것이다.

픽스처

p146.

픽스처 : 일부 항목, 장치 또는 소프트웨어를 일관되게 테스트하는 데 사용되는 장치

  • 반복 코드 줄이기

junit 3 버전대에는 TestCase 라는 클래스를 상속했었음.
TestCase에는 setup / teardown 이라는 함수가 있었고 이 setup 과 teardown 이란 단어는 현재도 다양한 테스팅 분야에서 사용됨.

참고로 현재는 현재는 5버전이며 어노테이션을 사용 해서 지정할 수 있음.

  • 해당 파일 실행시 @BeforeAll
  • 내부 테스트 실행시 @BeforeEach
  • 해당 파일 실행시 @AfterAll
  • 내부 테스트 실행시 @AfterEach

데이터 정리

테스트는 서로 독립적으로 동작할 수 있어야 함. 근데 teardown에서 제대로 리소스(e.g. 데이터베이스)를 해제하지 못하면 어떻게 될까?

블라디미르 코리코프의 단위 테스트
10장 데이터베이스 테스트 - 10.3.2 테스트 실행 간 데이터 정리
에서는 다음과 같이 이야기 함.

테스트 실행 간에 남은 데이터를 정리하는 방법은 네 가지가 있다.

  • 각 테스트 전에 데이터베이스 백업 복원하기: 이 방법은 데이터 정리 문제를 해결할 수 있지만 다른 세 가지 방법보다 훨씬 느리다. 컨테이너를 사용하더라도 컨테이너 인스턴스를 제거하고 새 컨테이너를 생성하는 데 보통 몇 초 정도 걸리기 때문에 전체 테스트 스위트 실행 시간이 빠르게 늘어난다.
  • 테스트 종료 시점에 데이터 정리하기: 이 방법은 빠르지만 정리 단계를 건너뛰기 쉽다. 테스트 도중에 빌드 서버가 중단하거나 디버거에서 테스트를 종료하면 입력 데이터는 데이터베이스에 남아있고 이후 테스트 실행에 영향을 주게 된다.
  • 데이터베이스 트랜잭션에 각 테스트를 래핑하고 커밋하지 않기: 이 경우 테스트와 SUT에서 변경한 모든 내용이 자동으로 롤백된다. 이 접근 방식은 정리 단계를 건너뛰는 문제를 해결하지만 또 다른 문제를 제기한다. 이는 작업 단위를 재사용할 때와 같은 문제인데, 추가 트랜잭션으로 인해 운영 환경과 다른 설정이 생성되는 것이다.
  • 테스트 시작 시점에 데이터 정리하기: 이 방법이 가장 좋다. 빠르게 작동하고 일관성이 없는 동작을 일으키지 않으며, 정리 단계를 실수로 건너뛰지 않는다.

그래서 나는 테스트 시작 시점에 데이터 정리하기 이 방법으로 현재 테스트 코드를 작성하고 있음.

테스트 추가해나가기

p 150.

난 “끝났다”는 말을 믿지 않는다. 만약 시스템이 크다면, 당신이 늘 건드리는 부분들은 절대적으로 견고해야 한다. 그래야 나날이 수정할 때 안심할 수 있기 때문이다.

“다음에 할인은 무엇인가?”에 관련된 또 다른 질문은 “어떤 테스트들이 추가로 더 필요할까?”다.

때로는 실패해야 하는 테스트가 성공하는 경우가 있는데, 그럴 떈 그 이유를 찾아내야 한다. 또는 실패해야 하는 테스트가 실제로 실패하기도 하는데, 이때는 이를 이미 알려진 제한사항 또는 앞으로 해야할 작업 등의 의미로 그 사실을 기록해둘 수도 있다.

무분별한 퍼징 테스트, 랜덤에 의한 테스트는 삼가면 좋다고 생각됨. 먼저는 정확한 범위를 분석하고 그 범위에 대해서 정확한 테스트를 진행해야 함.

실험에서도 독립변수(조작되는 값), 통제변수(유지되는 값) 로 나누어 실험을 진행하듯 이와 마찬가지로 무분별한 퍼징 테스트, 랜덤에 의한 테스트는 제대로 된 테스트가 아니게 되기 쉬움.

실제로 개발을 하면서 테스트도 계속 실행시키면 정신없지 않을까?

책에서는 이 예제를 실행하면서 테스트를 125번 실행했다고 한다. “실제로 개발을 하면서 테스트도 계속 실행시키면 정신없지 않을까?” 라는 의문이 있었는데

이에 대해서 한 프론트 개발자 분께서 이야기 해주시길
jest(js test 라이브러리)에서는 watch 모드라고 하는게 있다고 한다.
watch 모드로 테스트를 실행해두면 수정된 부분만 테스트를 자동으로 실행시켜 준다고 한다.

자바에서도 이와 같은것이 있으려나 하고 찾아봤는데 없는 것을 보인다. IDE 단에서 지원을 해주면 가능하려나 싶기도 한데 아직까지는 발견을 못했다.