# Reading/--- 개발서적

[Clean Code] 9장. 단위 테스트

jiniz.ll 2022. 3. 5. 18:41

📖 해당 글은 Clean Code(클린 코드) 책을 읽고 정리한 글입니다.

 

  • TDD. Test Driven Development
  • 우리는 단순히 테스트 코드를 추가하기 위해 제대로 된 테스트 케이스를 작성해야 한다는 중요한 사실을 놓쳐서는 안 된다.

TDD 법칙 세 가지

1. 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
3. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.
  • 이 규칙을 따르면 개발과 테스트가 30초 주기로 묶인다고 한다.
  • 테스트 코드가 실제 코드보다 불과 몇 초 전에 나온다는 것. 즉 테스트 코드 작성하고 실제 코드 작성하고 이런식으로 개발을 해야한다는 것이다.

 

사실 위의 세 가지 법칙은 무슨 말인지 잘 모르겠다 😀 하하하

 

깨끗한 테스트 코드 유지하기

  • 테스트를 하지 않는 것 보다 지저분한 테스트 코드라도 돌리는 것이 낫다는 판단은 결코 좋지 못하다.
  • 그 이유는 실제 코드가 변화하면 테스트 코드도 변해야 하는데 테스트 코드가 지저분할수록 변경하기 어려워지기 때문이다.
  • 앞선 장들에서 깨끗한 코드를 유지해야 했던 이유와 같이 테스트 코드가 지저분하고 복잡할수록 실제 코드를 짜는 시간보다 테스트 케이스를 추가하는 시간이 더 걸리게 될 것이다. 
  • 또한 마찬가지로 점차 테스트 케이스를 유지 보수하는 비용이 늘어날 것이며 복잡한 테스트 코드를 수정하기 어려워져 시스템 코드를 변경하기 꺼려지게 될 것이다.
  • 따라서 여기서 말하고자 하는 것은 테스트 코드도 실제 코드 못지 않게 깨끗하게 짜야한다는 것이다.

 

테스트는 유연성, 유지보수성, 재사용성을 제공함

  • 코드에 유연성, 유지보수성, 재사용성을 제공하는 것이 바로 단위 테스트이다.
  • 테스트 케이스가 없다면 변경이 두려워지며 모든 변경이 잠정적인 버그가 된다.
  • 반대로 테스트 케이스가 있다면 변경이 쉬워진다.
테스트 코드가 지저분하면 코드를 변경하는 능력이 떨어지며 코드 구조를 개선하는 능력도 떨어진다. 테스트 코드가 지저분할수록 실제 코드도 지저분해진다. 결국 테스트 코드를 잃어버리고 실제 코드도 망가진다

 

깨끗한 테스트 코드

  • 깨끗한 코드를 만드는데 가장 중요한 것은 가독성이다.
  • 가독성을 높이기 위해서는 명료성, 단순성, 풍부한 표현이 필요하다.
  • 최소한의 표현으로 많은 것을 나타내야 한다.

 

  • BUILD-OPERATE-CHECK 패턴 (p. 160-161 참고)
  • 첫 부분은 테스트 자료를 만들며
  • 두 번째 부분은 테스트 자료를 조작하고
  • 세 번째 부분은 조작한 결과가 올바른지 확인한다.

 

  • 테스트 코드는 잡다한 코드를 제거하고 테스트에 진짜 필요한 자료 유형과 함수만 사용해야 읽는 사람이 코드가 수행하는 기능을 빨리 이해할 수 있다.

 

도메인에 특화된 테스트 언어

  • 목록 9-2(p.160) 는 도메인에 특화된 언어(DSL)로 테스트 코드를 구현하는 기법을 보여주는데 시스템 조작 API를 사용하는 대신 API 위에 함수와 유틸리티를 구현한다.
  • 테스트 코드 작성 시 이렇게 구현한 함수와 유틸리티를 사용하여 테스트 코드를 짜거나 읽기 쉽게 만들어준다.

 

이중 표준

  • 결국 하고자 하는 말은 테스트 코드 역시 단순하고, 간결하고, 표현력이 풍부해야 하지만, 실제 코드만큼 효율적일 필요는 없다는 것이다.
  • 실제 애플리케이션이 실시간 임베디드 시스템이라면 컴퓨터 자원과 메모리가 제한적일 가능성이 높다. 하지만 테스트 환경은 자원이 제한적일 가능성이 낮다.
  • 따라서 메모리나 CPU 효율과 관련이 있는 경우 코드의 깨끗함과는 무관하게 테스트 코드는 덜 효율적이어도 된다는 것이다.

 

테스트 당 assert 하나

  • 목록 9-5(p. 163)을 보면 assert 문이 하나 뿐인 함수는 결론이 하나이기 때문에 코드를 쉽고 빠르게 이해할 수 있다.
  • 하지만 목록 9-2(p. 160)에서 하나의 함수에 있는 두 개의 assert 문을 하나로 합치는 방법은 좋지 않아보인다. 하지만 이런 경우 테스트를 두 개로 쪼개서 각자 하나의 assert 를 수행하면 된다.

 

  • 목록 9-7(p. 164) 는 목록 9-2의 코드를 테스트 두 개로 나눴는데 함수 이름 또한 given-when-then 이라는 관례를 사용하였다.
  • 이렇게 변경하면 테스트 코드를 읽기 쉬워지지만 테스트를 분리하면 중복되는 코드가 많아진다.
  • TEMPLATE METHOD 패턴을 사용하여 중복을 제거할 수 있다.

given/when 부분을 부모 클래스에 두고 then 부분을 자식 클래스에 두면 된다.

아니면 완전히 독자적인 테스트 클래스를 만들어 @Before 함수에 given/when 부분을 넣고 @Test 함수에 then 부분을 넣어도 된다.

 

이런 방법론적인 부분에서는 아직 이해가 되지 않지만 이후에 좋은 테스트 코드를 작성하기 위한 방법들에 대해 알아봐야겠다는 생각이 든다.

 

  • 이렇게 따지다보면 결국 목록 9-2 처럼 assert 문을 여러 개 사용하는 것이 좋다는 생각이 들 수 있다.
  • 저자는 ‘단일 assert 문’이라는 규칙이 좋다고 생각하나 때로는 함수 하나에 여러 개의 assert 문을 넣기도 한다고 한다.
  • 즉, 가능하다면 assert 문의 개수는 최대한 줄이는 것이 좋다는 생각이다.

 

테스트 당 개념 하나

  • 목록 9-8(p. 166) 를 보면 굉장히 많은 assert 문이 있다. 하지만 이 예제는 단순히 assert 문이 많다는 것이 문제가 아니라 여러 개념을 하나의 함수에서 테스트하고 있다는 것이다.
  • 그러므로 이 예제는 세 개의 테스트 함수로 분리되어야 한다.

 

  • 이 역시 이전 함수에서 말했던 내용과 일치하는 부분이라 생각한다.
가장 좋은 규칙은 "개념 당 assert 문 수를 최소로 줄여라"와 "테스트 함수 하나는 개념 하나만 테스트하라"라 하겠다.

 

F.I.R.S.T.

  • 깨끗한 테스트는 다섯 가지 규칙을 따른다.
  • Fast 빠르게 : 테스트가 빨라야하는 이유는 테스트가 느리면 자주 돌릴 수 없기 때문이다. 테스트 코드를 자주 돌려 문제를 빠르게 찾아내지 못하면 코드 품질이 망가지기 쉽다.
  • Independent 독립적으로 : 각 테스트는 서로 의존해서는 안된다. 각 테스트는 독립적으로, 어떤 순서로 실행해도 상관없어야 한다. 테스트가 서로 연결되어 있다면 중간에 문제가 생기더라도 원인을 찾기 어려워지며 후반 테스트가 찾아야 할 결함도 발견하지 못할 수 있다.
  • Repeatable 반복가능하게 : 테스트는 어떤 환경에서도 실행할 수 있어야한다. 실제 환경, QA 환경, 네트워크에 연결되지 않은 환경에서도 가능해야한다. 그렇지 못하면 테스트의 실패를 변명하거나 테스트를 수행하지 못하게 되는 경우가 발생한다.
  • Self-Validating 자가검증하는 : 테스트는 부울 값으로 결과를 내야한다. 성공 아니면 실패일 뿐이다.
  • Timely 적시에 : 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현해야 한다. 실제 코드를 작성한 뒤 테스트 코드를 작성하면 테스트 하기 어렵거나 테스트가 불가능할지도 모른다.

 

결론

이 책의 앞선 여러 장들의 결론들이 모아지는 기분이다. 테스트 코드 역시 코드다. 잘 작성된 테스트 코드는 실제 코드의 유연성, 유지보수성, 재사용성을 강화해준다. 테스트 코드 역시 다른 코드들과 마찬가지로 지속적으로 깨끗하게 관리해야 하며 표현력을 높이고 간결하게 정리해야한다. 

 

스위프트에서는 한글로 함수명이나 변수명을 작성할 수 있는데 테스트 코드를 빨리 이해하기 쉽도록 테스트 함수명을 한글로 작성하기도 한다. 가장 최근 프로젝트에서(그럼에도 시간이 꽤 지났지만) TDD 를 적용해본 적이 있다. 사실 정말 귀찮은 작업이고 여전히 좋은 테스트 코드란 것에는 많은 공부가 필요하지만 우리가 프로젝트를 하면서 공통적으로 느낀 것은 테스트 코드가 있다면 무심히 지나칠 수 있던 프로그램의 버그를 더욱 쉽고 빠르게 찾을 수 있다는 것이었다. 코드를 작성하거나 변경했을 때 무심히 돌린 테스트에서 (당연히 통과할 것이라고 생각한) 갑자기 실패가 뜨거나 깜박하고 테스트를 돌리지 않고 깃헙에 올린 경우에 미리 설정해둔 Github Action 의 테스트에서 실패가 뜰 때 아차 싶었던 경우가 꽤 많이 있었다. 최근 개인 프로젝트를 할 때도 TDD 를 적용해볼까도 싶지만 사실상 너무 귀찮은 나머지 테스트 코드를 작성하는 것을 포기할 때도 많다. 이 챕터의 내용은 ‘테스트 코드를 작성하라’가 아니라 ‘깨끗한 테스트 코드를 작성하라’이지만 이 책을 읽으면서 다시 한 번 테스트 코드를 작성해봐야겠다는 생각이 들었다. 기왕이면 깨끗한 테스트 코드로 말이다.

 


► 이전 글 : 

► 다음 글 : Clean Code 10장. 클래스

'# Reading > --- 개발서적' 카테고리의 다른 글

[Clean Code] 10장. 클래스  (0) 2022.03.09
[Clean Code] 6장. 객체와 자료 구조  (0) 2022.03.01
[Clean Code] 5장. 형식 맞추기  (0) 2022.02.28
[Clean Code] 4장. 주석  (0) 2022.02.25
[Clean Code] 3장. 함수  (0) 2022.02.23