코드는 작성되면 될수록 점점 나빠지는 경향이 있다. 코드베이스에 변경이 생길 때마다 엔트로피는 증가한다.그렇기때문에 지속적인 정리와 리팩토링을통해 관리를 해 나가야하고 이와같은 관리가 되지 않으면 프로젝트는 점점 복잡해지고 보수하기 어려워진다. 흔히 이러한 경향을 해소하기위한 방법으로 테스트를 한다. 테스트는 안전망 역할을 하며 회기에 대한 보험을 제공하는 도구라 할 수 있다.
코드 커버리지 또는 분기 커버리지 점수가 높다고 절때 안정성이나 테스트가 완료된 것이라고 보기 힘들다 그 이유는 점수를 위한 테스트를 칠 수 있기때문이다. 개발을 해본 사람은 이를 뜻하는 것이 무엇인지 알거라고 봅니다.
성공적인 Test shuit는 다음과 같다.
- 개발 주기에 통합돼 있다.
- 코드베이스 중 가장 중요한 부분만을 대상으로 한다.
- 최소한의 유지비용으로 최대의 가치를 끌어낸다.
단위테스트란?
단위테스트는 생각보다 많은 견해가 있고 크게 두가지 견해가 있는데 고전파와 런던파가 있다. 고전파는 모든사람이 단위테스트와 테스트 주도 개발에 원론적으로 접근하는 방식이기 때문에 고전이라고 하고 런던파는 런던의 프로그래밍 커뮤에서 시작됐다.
하지만 단위테스트는 다음과같은 세가지 중요사항이 있다.
- 작은 코드 조각을 검증
- 빠르게 수행하고
- 격리된 방식으로 처리하는 자동화된 테스트런던파코드 조각을 격리된방식으로 검증을하려면 테스트 대상 시스템의 의존서을 테스트 대역으로 대체하면 테스트 대상 시스템만 검증하는데 집중할 수 있을 뿐만 아니라 규모가 큰 상호 연결 객체 그래프를 분할 할 수 있다. 그리고 단위테스트 격리를통해 더이상 코드베이스를 테스트하는 방법을 고민할 필요가 없어진다. 예를들어 클래스가 있는지 체크하기위해 클레스에 해당하는 단위테스트 클레스를 생성하면 될테니..
mock
목은 테스트 대상 시스템과 협력자 간의 상호 작용을 검사할 수 있는 특별한 테스트 대역입니다.
- 테스트 대역은 실행과 관련없이 모든 종류의 가짜 의존성을 설명하는 포괄적인 용어
- 목은 그러한 의존성의 한 종류일 뿐.
- 목을 사용할때 협력자에서 격리된 테스트 대상 시스템에는 인터페이스가 필요하다.*
이렇든 런던 스타일은 테스트 대역(목)으로 테스트 대상 코드 조각을 분리해서 격리 요구사항에 다가간다.각각의 테스트를 격리하는 것은 여러 클래스가 모두 메모리에 상주하고 공유상태에 도달하지 않는 한, 여러클래스를 한번에 테스트해도 괜찮다는 뜻이 된다. 예를 들어 어떤 테스트 준비 단계에서 데이터베이스에 직접 수정을 하는 두 테스트가 있는데 이 테스트를 병렬로 실행하면 실패할 확률이 올라간다. 이것은 제품코드가 고장난 것이 아닌 테스트끼리의 간섭 때문인 것이다. 보통 테스트 간에 공유 상태를 일으키는 의존성에 대해서만 사용한다. - 공유 의존성과 휘발성 의존성
- 고전파
- 공유 의존성
- 테스트 대상 클래스 간이 아니라 단위테스트 간에 공유한다. 그런 의미에서 싱글톤 의존성은 각 테스트에서 새 인스턴스를 만들 수 있기만 하면 공유되지 않는다.
- 공유의존성을 가진 테스트는 단위 테스트 영역에서 통합 테스트의 영역으로 넘어간다.
- 휘발성 의준성은 다음 속성중 하나를 나타는 의존성이다
- 개발자 머신에 기본 설치된 환경 외에 런타임 환경의설정 및 구성을 요구 EX) DB와 API처럼 시스템에 기본적으로 있지않음
- 비결정적 동작을 포함한다. 호출에대한 의존성을 띄는 클레스 EX)난수생성기, 날짜와 시간을 반환하는 클레스
이렇듯 런던파와 고전파로 나눠진 원이은 격리 특성때문
격리 주체 | 단위의 크기 | 테스트대역 사용 대상 | |
---|---|---|---|
런던파 | 단위 | 단일클래스 | 불변 의존성 외 모든 의존성 |
고전파 | 단위 테스트 | 단위클래스 또는 클래스 세트 | 공유의존성 |
값객체?
불변객체를 값객체 또는 값이라 하는데 값객체의 주요 특징은 각가의 정체성이 없다는 것이다. 내용에 의해서만 식별된다. 그 결과 동일한 내용을 갖고 있다면 어떤 객체를 사용하든 상관없다.
값 객체는 그 자체로 값을 나타내는 객체로, 주로 불변(Immutable)하며 동일한 값을 가진 객체는 모두 동등하다고 간주됩니다. 이것은 객체 지향 프로그래밍에서 데이터를 표현하고 처리하는 데 사용됩니다.
한번에 한 클레스만 테스트하기
"우리집 강아지를 부르면 바로 나에게 온다"
와
"우리집 강아지를 부르면 먼저 왼쪽 앞다리를 움직이고 이어서 오른쪽 앞다리 움직이고 꼬리를 흔들흔드........
위 두 문장을 비교했을때 두번째 문작은 그래서 강아지가 나에게 오는건지 알기가 힘들다 이렇든 실재 동작 대신 개별 클래스에대한 테스트를 늘려 입자성을 높이게되면 테스트가 무엇을 검증하게되는지 전체적인 흐름을 감지하기가 힘들어진다.
통합테스트의 일부인 엔드 투 엔드 테스트
통합 테스트는 공유의존성, 프로세스 외부 의존성 뿐 아니라 조직내 다른 팀이 개발한 코드드오가 통합해 작동하지는지도 검증하는 테스트다
엔드투 엔드 테스트는 프로세스 외부 의존성을 전부 또는 대사수 갖고 작동한다. 즉 시스템의 최종 사용자 관점에서 검증하는것을 의미한다.
엔드투 엔드 테스트는 유지보수 측면에서 가장 비용이 많이 들기 때문에 모든 다뉭테스트와 통합테스트를 통과한 후 빌드 프로세스 후반에 실행하는것이 좋다.
출처 : Unit Testing 책
블라디미르 코리코프
'Unit Testing' 카테고리의 다른 글
가치 있는 테스트를 위한 리팩터링 (0) | 2024.03.03 |
---|---|
단위 테스트작성 스타일과 함수형 어키텍처 (1) | 2024.02.24 |
목(mock)사용하는 테스트의 취약성 (1) | 2024.02.18 |
이상 적인 단위테스트의 4대 요소 (1) | 2024.02.11 |
단위테스트(2) 단위테스트 구조 (0) | 2024.02.04 |