단위 테스트 4장( 좋은 단위 테스트의 4대 요소)

이현광·2022년 3월 30일
0

단위 테스트

목록 보기
5/6
post-thumbnail

좋은 단위 테스트의 4대 요소

  • 회귀 방지
  • 리팩터링 내성
  • 빠른 피드백
  • 유지 보수성

회귀 방지

회귀는 소프트웨어 버그이다. 코드 수정 후 기능이 의도한 대로 작동하지 않는 경우를 말한다.

  • 테스트 중에 실행되는 코드의 양
  • 코드 복잡도
  • 코드의 도메인 유의성

일반적으로 실행되는 코드가 많을수록 회귀가 나타날 가능성이 높다.

코드의 양뿐만이 아니라 복잡성과 도메인 유의성도 중요하다. 즉 비지니스 로직 코드가 보일러플레이트(반복적인 코드 작성을 줄이기 위해 재사용이 가능한 코드)보다 더 중요하다.

리팩토링 내성

테스트를 실패로 바꾸지 않고 기본 어플리케이션 코드를 리팩터링 할 수 있는지에 대한 척도이다.

리팩터링은 식별 할 수 있느 동작을 수정하지 않고 기존 코드를 바꾸는 것을 말한다.
ex) 메서드 이름을 바꾸거나 코드 조각을 새로운 클래스로 추출 하는 것

기반 코드를 수정하면 테스트를 빨간색으로 바뀌게끔 작성이 되어있다면 실제로 기능이 작동하지 않는지는 상관이 없다...
이런 상황을 거짓 양성이라고 한다. 기능은 의도한 대로 작동하지만 테스트는 실패를 나타내는 결과다.

테스트가 지속 간능한 성장을 하는 메커니즘은 회귀 없이 주기적으로 리팩터링하고 새로운 기능을 추가할 수 있는 것이다. 이 때에는 아래와 같은 장점을 가진다.

  • 기존 기능이 고장 났을 때 테스트가 조기 경고를 제공
  • 코드 변경이 회기로 이어지지 않을 것이라고 확신

하지만 거짓 양성을 이 두가지 모두를 방해한다.

  • 테스트가 이유 없이 실패한다면 나중에는 실패를 무시하게 된다.
  • 거짓 양성이 빈번하면 테스트 코드에 신뢰가 점점 떨어지고 더 이상 테스트로서의 의미를 잃게 된다.

거짓 양성의 원인

테스트와 테스트 대상 시트템(SUT)의 구현 세부 사항이 많이 결합할수록 허위 경보가 더 많이 생긴다.

이 문제의 해결 방법은 해당 구현 세부 사항에서 테스트를 분리하는 것뿐이다.


위의 그림과 같이 구현 세부 사항 대신 최종 결과를 목표로 한다면 거짓 양성을 줄 일 수 있다.

회귀 방지와 리팩터링 내성의 관계

프로젝트가 시작한 직후에는 회귀방지가 리팩터링내성의 필요성이 더 크다.

테스트 정확도 극대화

거짓 양성을 피하는 데에는 리팩터링 내성이 도움이 된다.

회귀 방지와 리팩터링 내성은 테스트 스위트의 정확도를 극대화하는 것을 목표로 한다.

  • 테스트 버그가 있음을 얼마나 잘 나타내는가?
  • 테스트가 버그 없음을 얼마나 잘 나타내는가?

거짓 양성과 거짓 음성의 중요성

초기에는 리팩터링이 바로 중요하지 않기에 거짓 양성의 중요성이 떨어진다.
하지만 시간이 지나면 코드 베이스는 나빠진다. 점점 복잡해지고 체계성이 떨어지게 된다.
이런 경향을 줄이기 위해 정기적으로 리팩터링을 해야한다. 그렇기에 후반으로 갈 수록 거짓 양성의 중요성이 올라가게된다.

빠른 피드백과 유지 보수성

당연하게도 테스트는 빠를 수록 좋다.

유지 보수성 지표는 유지비를 평가하고 아래와 같은 두가지 주요 요소로 구성되어있다.

  • 테스트가 얼마나 이해하기 어려운가
    테스트 크기와 관련이 있다. 작은 테스트는 필요할 때 변경하기 쉽지만 반대는 어렵다.
  • 테스트가 얼마나 실행하기 어려운가
    외부 종속성으로 작동하면 의존성을 상시 운영하는데 시간을 들여야한다.

이상적 테스트

모든 면에서 좋은 이상적 테스트는 만들 수 없다.

회귀 방지, 리팩터링 내성, 빠른 피드백은 상호 배타적이기 때문에 셋 중 하나를 희생해야 나머지 둘을 최대로 할 수 있다.

극단적 사례를 살펴보자

  • 엔드 투 엔드 테스트
    회귀 오류와 거짓 양성에 대한 방지를 휼룡히 해내지만 속도가 떨어진다.
  • 간단한 테스트
    우수한 리팩터링 내성과 빠른 피드백을 제공하지만 회귀 방지가 없다.
  • 깨지기 쉬운 테스트
    실행이 빠르고 회귀를 잡을 가능성이 높지만 거짓 양성이 많은 테스트를 작성하기가 매우 쉽다.

대중적인 테스트 자동화 개념

테스트 피라미드 분해

피라미드의 상단으로 갈 수 록 회귀 방지에 유리한 반면 하단은 실행 속도를 강조한다.

어느 계층도 리팩터링 내성을 포기하지는 않는다.

테스트 피라미드에는 예외를 가지고 있다. 모든 어플리케이션이 비즈니스 규칙이나 기타 복잡도가 거의 없는 기본적인 CRUD작업이라면 테스트는 '피라미드'는 단위 테스트와 통합 테스트의 수가 같고 엔드 투 엔드 테스트가 없는 직사각형 처럼 보일 것이다.
또 외부 의존성 하나만 연결하는 API 또한 예외를 가진다.

화이트 박스 테스트와 블랙 박스 테스트

  • 화이트 박스: 내부 작업을 검증하는 테스트 방식이고 테스트는 요구 사항이나 명세가 아닌 소스코드에서 파생
  • 블랙 박스: 시스템의 내부 구조를 모르더라도 시스템 기능을 검사할 수 있는 소프트웨서 테스트 방법, 어떻게가 아닌 무엇을 해야 하는지 중심으로 구축된다.

테스트를 작성할 때는 블랙박스 테스트가 바람직하지만 테스트를 분석할 때는 화이트 박스 방법을 사용할 수 있다. 코드 커버리지 도구를 사용해서 어떤 코드 분기를 실행하지 않았는지 확인한 다음 코드 내부 구조에 대해 전혀 모르는 것처럼 테스트 해라!

"프로그래밍을 하는 삶에 있어서 불행한 사실은 코드가 자산이 아니라 책임이라는 점이다."

profile
cccooodddiiinnngg

0개의 댓글