이 포스팅에서는 아래와 같은 안티 패턴들을 알아보도록 하겠습니다.비공개 메서드 단위 테스트비공개 상태 노출테스트로 유출된 도메인 지식코드 오염구체 클래스 목 처리 비공개 메서드 단위 테스트 비공개 메서드를 직접 테스트하는 것은 구현 세부 사항에 결합되어 리팩토링 저항성을 잃습니다. 대신, 공용 API를 통한 간접 테스트를 권장하며, 복잡한 로직은 별도 클래스로 추출해야 합니다.테스트를 위해 비공개 메서드를 노출하는 행위는 관찰 가능한 동작만을 테스트해야 한다는 근본적인 원칙을 침해합니다. 이는 테스트를 코드의 구현 세부 사항에 결합시켜, 테스트의 가장 중요한 속성인 리팩토링 저항성을 손상시킵니다.비공개 메서드는 직접 테스트하는 대신, 메서드가 속한 클래스의 관찰 가능한 동작의 일부로서 간접적으로 테스트되..
데이터베이스는 관리형 종속성(managed dependency)에 해당합니다. 이러한 종속성은 애플리케이션 외부에서 직접 접근할 수 없고, 외부에서 그 상호작용을 관찰할 수 없는 특성을 지닙니다. 따라서 통합 테스트에서는 반드시 관리형 종속성의 실제 인스턴스를 사용해야 하며, 이를 목 객체로 대체해서는 안 됩니다. 이는 데이터베이스와의 통신이 애플리케이션의 구현 세부 사항에 속하기 때문입니다. 데이터베이스 테스트를 위해서는 다음과 같은 전제 조건이 필요합니다.형상 관리 시스템에 데이터베이스 유지모든 개발자를 위한 별도의 데이터베이스 인스턴스 사용데이터베이스 배포에 마이그레이션 기반 방식 적용 형상 관리 시스템에 데이터베이스 유지모델 데이터베이스를 두어 운영 데이터베이스와 비교하여 스키마를 유지하는 것은 ..
목은 비관리형 종속성(unmanaged dependencies)에만 적용해야 하며, 비관리형 종속성은 외부 애플리케이션에 상호작용이 관찰 가능한 경우입니다. 목을 사용하여 상호작용을 검사함으로써 애플리케이션이 외부 계약을 유지하는지 확인합니다. 목의 가치를 극대화하는 것은 테스트의 회귀 방어와 리팩토링 저항성을 높이는 핵심 전략이며, 이를 위해 몇 가지 구체적인 방법이 필요합니다. 시스템 경계(Edges)에서 상호작용 검증목킹 시 항상 지켜야 할 지침은 비관리형 종속성과의 상호작용을 시스템의 바로 그 경계에서 검증해야 한다는 것입니다. 이러한 전략은 목킹의 가치를 다음 두 가지 측면에서 극대화합니다. 리팩토링 저항성 극대화 시스템 경계에서 상호 작용을 검증하는 것은 테스트가 생산 코드의 구현 세부 사항..
통합 테스트의 정의와 역할통합 테스트는 단위 테스트의 기준(작은 단위, 빠른 실행, 격리성) 가운데 하나라도 충족하지 못하는 모든 테스트컨트롤러 영역의 코드를 대상으로 하여 프로세스 외부 종속성과의 연동을 검증 다시 보는 테스트 피라미드테스트 피라미드는 소프트웨어 테스트 스위트 내에서 다양한 유형의 테스트 간에 특정 비율을 유지해야 한다고 주장하는 개념이며, 일반적으로 세 가지 주요 테스트 유형으로 시각적으로 표현됩니다.단위 테스트 (Unit tests): 피라미드의 가장 넓은 하단 부분을 차지하며, 빠르고 저렴하고 유지 보수 비용이 낮아 다양한 엣지 케이스를 다루기에 적합하다.통합 테스트 (Integration tests): 피라미드의 중간 부분을 차지하며, 시스템이 데이터베이스·메시지 버스 등 ..
모든 운영 코드는 다음 두 가지 기준으로 분류될 수 있습니다.복잡성 또는 도메인 중요성: 코드의 의사 결정(분기) 지점 수로 정의협력자 수: 협력자는 가변이거나 프로세스 외부 의존성인 종속성을 의미하며, 협력자가 많을수록 테스트 비용이 증가 이러한 두 기준의 조합으로 다음과 같은 네 가지 유형의 코드가 나뉩니다.도메인 모델 및 알고리즘(Domain model and algorithms): 복잡하거나 도메인적으로 중요한 코드, 협력자가 거의 없으며 가장 높은 가치를 제공하는 단위 테스트의 대상간단한 코드(Trivial code): 복잡성이나 도메인 중요성이 낮으며 협력자도 거의 없다. 테스트할 가치가 거의 없다.컨트롤러(Controllers): 복잡성은 낮지만, 많은 협력자와의 조율을 담당하며 주로 통합 ..
단위 테스트는 세 가지 스타일이 있으며, 하나의 테스트에서 하나 또는 둘, 세 가지 스타일 모두를 함께 사용할 수 있습니다.출력 기반 테스트(output-based testing)상태 기반 테스트(state-based testing)통신 기반 테스트(communication-based testing) 출력 기반 테스트입력을 주고 반환값을 확인전역 또는 내부 상태를 변경하지 않는 코드에만 적용 가능사이드 이펙트가 없는 함수형 스타일에 적합// SUTclass PriceEngine { fun calculateDiscount(products: List): Double { return if (products.size >= 2) 0.1 else 0.0 // 2개 이상이면 10% 할인 }..
목(Mock)은 테스트 대상 시스템(SUT)과 그 협력자 사이의 상호 작용을 검사할 수 있는 데이터 대역입니다. 목(Mock)과 스텁(Stub) 구분테스트 더블(Test Double) 개념테스트 더블은 실제 의존성 대신 사용하는 가짜 의존성을 의미하며, 테스트를 쉽게 하기 위해 도입된다.더미(Dummy), 스텁(Stub), 스파이(Spy), 목(Mock), 페이크(Fake)로 나뉘며, 크게 목(Mock)과 스텁(Stub) 두 유형으로 나눌 수 있다.목(Mock)과 스텁(Stub)의 핵심 차이목(Mock): SUT가 외부 시스템을 호출하는 상호작용을 모방하고, 그 호출이 올바르게 발생했는지 검증한다. 즉, 사이드 이펙트를 검사하는 데 사용된다.스텁(Stub): SUT가 데이터를 얻기 위해 호출하는 내부로..
좋은 단위 테스트에는 다음 네 가지 특성이 있습니다.회귀 방지 (Protection against regressions)리펙터링 내성 (Resistance to refactoring)빠른 피드백 (Fast feedback)유지 보수성 (Maintainability) 회귀 방지회귀(regression)는 새로운 기능 추가나 변경 후 기존 기능이 의도대로 동작하지 않는 소프트웨어 버그를 의미하며, 테스트가 회귀에 약하면 기능은 잘못 동작하는데도 테스트가 통과하는 거짓 음성(false negative)이 발생합니다. 회귀 방지 지표를 평가하는 요소실행되는 코드의 양: 더 많은 코드를 실행할수록 회귀 발견 가능성이 높아진다.코드 복잡성: 복잡한 비즈니스 로직일수록 회귀 시 피해가 크므로 테스트 우선순위가 ..
단위테스트는 일반적으로 준비(arrange), 실행(act), 검증(assert)로 이루어진 AAA패턴을 사용한다. AAA패턴단위 테스트를 구조화하는 데 사용되는 일반적인 접근 방식입니다.Given-When-Then 패턴과 테스트 구성 측면에서 차이가 없으며, Given-When-Then 패턴은 비기술자들과 공유하는 테스트에 더 적합합니다.// Calculator 클래스 예시class Calculator { fun sum(first: Double, second: Double): Double { return first + second }}class CalculatorTests { @Test fun `Sum of two numbers`() { // Arrang..
단위 테스트(Unit Test)의 정의 단위 테스트에 대한 정의는 불필요한 요소를 제거하고 나면 가장 중요한 세 가지 속성으로 요약할 수 있습니다.작은 코드 조각(즉, 단위)을 검증하고,빠르게 실행되며,고립된 방식으로 수행된다. 사람들 사이에서 의견이 크게 갈리는 부분은 고립성(isolation)입니다.고립성은 단위 테스트에서 "단위"를 어디까지로 볼 것인가? 라는 질문으로, 이 고립성 문제가 바로 고전 방식과 런던 방식의 차이를 낳는 근본적인 원인입니다. 두 학파를 설명하기 전에 먼저 예시를 살펴보겠습니다. 온라인 상점의 샘플 애플리케이션에는 고객의 구매 과정을 다루는 간단한 기능이 있습니다. 이 기능은 다음과 같이 동작합니다. 상점에 재고가 충분한 경우구매는 성공으로 처리된다.상점의 재고는 구매 수량..
