좋은 단위 테스트를 구성하는 4대 요소

가치있는 테스트를 식별하는 방법

좋은 단위 테스트를 구성하는 4대 요소를 통해 가치있는 테스트를 식별할 수 있다. > 회귀 방지, 리팩터링 내성, 빠른 피드백, 유지 보수성

이상적인 테스트는 네 가지 특성 모두에서 최대 점수를 얻어야 하지만 회귀 방지, 리팩터링 내성, 빠른 피드백, 이 세가지 요소는 상호 배타적이라 모두 최대로 하는것은 불가능 하다.

회귀 방지 vs 빠른 피드백

리팩터링 내성은 갖고 있거나 or 없거나로 이분법 적이기 때문에 타협할 수 없어 무조건 챙겨야 한다.

즉, 회귀 방지빠른 피드백 사이에서 선택을 해야 한다는 것

테스트 피라미드에서는 테스트 유형마다 빠른 피드백회귀 방지 사이에서 다른 선택을 한다.

회귀 방지

테스트가 얼마나 버그(회귀)의 존재를 잘 나타내는지에 대한 척도 기능이 고장났지만 테스트는 통과하는 상태를 거짓 음성이라 한다.

"코드는 자산이 아니라 책임이다. " "코드베이스가 커질수록 잠재적인 버그에 더 많이 노출된다.

회귀란 이전에 문제 없이 작동하던 기능이 수정이나 추가 작업 후 새로운 문제가 발생하는 현상을 말한다.

회귀 방지 지표 평가 고려 사항

  • 테스트 중에 실행되는 코드의 양

    • 코드가 생성한 결과가 유효한지 확인하는 것이 중요

  • 코드 복잡도

    • 단순한 코드는 실수할 여지가 많지 않기에 테스트할 가치가 없다.

  • 코드 도메인 유의성

    • 비즈니스 로직에서 발생한 버그가 가장 치명적이기 때문에 훨씬 중요하다.

회귀 방지를 극대화 하려면?

  • 가능한 한 많은 코드를 실행하는 것을 목표로 해야 한다.

  • 테스트가 코드를 더 많이 실행할 수록 테스트에서 버그가 드러날 확률이 더 높아진다.

리팩터링 내성

테스트를 RED(실패)로 바꾸지 않고 코드를 리팩토링 할 수 있는지에 대한 척도

실제 기능이 제데로 동작하지만 테스트가 실패하는 경우를 거짓양성(허위경보) 이라 한다.

테스트가 코드 내부 구현 세부 사항과 결합도가 높기 때문에 코드의 일부분이 바뀌게 되면 테스트 실패로 이어진다. 즉, 리팩토링 하게되면 테스트가 실패하게 된다.

거짓양성 특징

  • 테스트가 타당한 이유 없이 실패하므로 코드 문제에 대응하는 의지가 꺾인다. 즉, 실패해도 신경을 쓰지 않게됨

  • 테스트에 대한 신뢰도가 떨어져 테스트는 더이상 안전망 역할을 하지 못하게 된다. 즉, 리팩터링을 안하게 됨

거짓양성을 줄이기 위해선?

  • 구현 세부 사항과 테스트 간의 결합도를 낮추면 된다. 즉, 코드의 내부 작업과 테스트 사이를 멀리 떨어뜨려 놓자.

  • 절차가 아니라 결과(식별할 수 있는 동작)을 테스트 해야 한다.

  • 최종 사용자에게 의미있는 결과를 목표로 테스트를 작성

회귀방지와 리팩터링 내성은 테스트 정확도에 기여한다.

테스트 정확도는 테스트가 올바른 추론을 하는지에 달려있다. 올바른 추론은 간단하다. 1. 기능이 동작하면 테스트 통과, 2.기능이 오동작하면 테스트 실패

올바른 추론을 하지 못하는 경우는 거짓음성과 거짓 양성으로 분류한다.

거짓 음성 → 테스트에서 오류가 발생하지 않는 것

거짓 양성 → 허위로 테스트가 실패했다고 하는 것

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

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

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

빠른 피드백

테스트가 얼마나 빨리 실행되는지에 대한 척도

테스트 속도가 빠를수록 테스트 스위트에서 테스트를 더 많이 실행할 수 있고 더 자주 실행할 수 있다.

테스트가 빠르게 실행되면 코드에 결함이 생기자마자 경고를 해주어 버그를 수정하는 비용을 줄일 수 있다.

유지 보수성

테스트가 얼마나 이해하기 어려운지, 테스트가 얼마나 실행하기 어려운지에 대한 척도

즉, 테스트는 읽기 쉽고 변경하기 쉬워야 하며, 외부 의존성이 적을수록 쉽게 실행된다.

테스트 피라미드

단위 테스트, 통합 테스트, E2E 테스트의 일정한 비율을 일컫는다. 각 층의 너비는 테스트 스위트에서 해당 테스트가 얼마나 보편적인지를 나타냄

비용(cost): Unit Test < Intergration Test < E2E Test

속도(speed): E2E Test < Intergration Test < Unit Test

테스트 피라미드

일반적으로 테스트 유형은 테스트 피라미드 형태로 유지된다.

E2E(엔드 투 엔드) 테스트

  • 많은 코드를 테스트하므로 회귀 방지에 탁월하다.

  • E2E 테스트는 상대적으로 수행속도가 크게 느려서 빠른 피드백을 받기 어렵다. 즉, 빠른 피드백 < 회귀 방지

통합 테스트

  • 코드가 아무리 단순하더라도 다른 하위 시스템과 통홥되어 잘 작동하는지 확인하는 것이 중요하다

  • 단일 외부 의존성(DB)에만 작동하는 환경에서는 E2E 테스트와 구별할 수 없다.

  • 유일한 차이는 진입점으로 최종 사용자 환경처럼 실제 브라우저에서 동작하냐 아니냐로 구분된다.

단위 테스트

  • 빠른 피드백 > 회귀 방지

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

회귀 방지
리팩터링 내성

화이트박스 테스트

👍

👎

블랙박스 테스트

👎

👍

블랙박스 테스트

시스템의 내부 구조를 몰라도 시스템의 기능을 검사할 수 있는 테스트 방식

어떻게 보다는 무엇을 해야하는지를 중심으로 구축된다.

리팩터링 내성은 타협할 수 없는 부분이라 블랙 박스 테스트를 사용해야 한다.

화이트박스 테스트

애플리케이션 내부 작업을 검증하는 테스트 방식, 요구사항 명세가 아닌 소스코드에서 파생됨

소스코드를 분석하면 외부 명세에만 의존할때에 놓칠 수 있는 많은 오류를 발견할 수 있지만 깨지기 쉽다.

테스트를 분석할 때는 화이트박스 테스트를 사용한다. 즉, 코드 커버리지 도구를 사용해서 어떤 코드 분기를 실행하지 않는지 구현 세부사항을 확인

깨지기 쉬운 테스트란 코드가 조금만 변경이 되어도 실패로 이어지는 구현 세부사항과 결합도가 높은 테스트

Last updated