2012-08-17 3 views
7

저는 Clean Code: A Handbook of Agile Software Craftsmanship을 읽고 있는데, 예제 중 하나는 Portfolio 클래스와 TokyoStockExchange 클래스입니다. 그러나 Portfolio은 외부 API로 TokyoStockExchange에 의존하여 포트폴리오의 가치를 결정하기 때문에 테스트 할 수 없으며 매우 휘발성 조회이며 테스트에 도움이되지 않습니다.단위 테스트 더미 객체를 유용하게 사용하는 이유에 대해 혼란스러워합니다.

그래서 공통된 StockExchange 인터페이스를 만들어이를 해결하고 TokyoStockExchangeDummyStockExchange이 모두 기본 클래스를 구현합니다. 따라서 의존성 반전 원칙이 달성되고 PortfolioTest 클래스에서 DummyStockExchange을 인스턴스화하고 주식을 회사에 고정하고 DummyStockExchange 인스턴스를 포트폴리오에 할당 한 다음 해당 회사의 일부 주식을 포트폴리오에 추가 한 다음 기대 가치는 실제로 적절한 가치입니다.

public class PortfolioTest 
{ 
    private DummyStockExchange exchange; 
    private Portfolio portfolio; 

    protected void setUp() 
    { 
     exchange = new DummyStockExchange(); 
     exchange.fix("MSFT", 100); 
     portfolio = new Portfolio(exchange); 
    } 

    public void GivenFiveMSFTTotalShouldBe500() 
    { 
     portfolio.add(5, "MSFT"); 
     Assert.assertEquals(500, portfolio.value()); 
    } 
} 

내 질문은, 단순히 이유입니다 : 여기에 코드는?

클래스가 Portfolio 클래스와 함께 작동하는 경우 테스트를 시도했습니다. 우리가 주식 가격을 설정하고 그 포트폴리오의 포트폴리오 5 개를 제공하는 새로운 방법으로 또 다른 클래스를 생성한다면 모든 것이 효과적 일 것입니다. 그냥 쓸모없는 것 같습니다. 나는 TokyoStockExchange이 기본적으로 주식 가격이 바뀌기 때문에 Portfolio으로 테스트 할 수 없다는 것을 이해합니다. 그러나 오히려 쓸데없는 테스트에서의 서브빙이 상황을 어떻게 돕는 지 이해할 수 없습니다.

우리의 가산기 프로그램이 작동하는지 알지 못하는 것 같지만 무작위로 생성 된 숫자 만 있으므로 더미 클래스를 만들어서 2를주고 2 + 2 = 4을 테스트 해 봅니다. 그래, 분명히 사실이야. 우리는 여전히 TokyoStockExchange을 깨고 다른 클래스를 테스트하기 때문에 테스트를 계속할 수 있습니다. 이 모든 것이기만적인 것처럼 보이면 우리가 알고있는 것을 테스트하기 위해 추가 코드를 작성해야합니다.

이 부분에서 단위 테스트를 이해하는 데있어 가장 큰 문제라고 생각합니다. 나는 내가 틀렸던 것을 안다. 나는 단지 내가 추측하는 빛을 보지 못했다. 잘만되면 누군가 나를 도울 수 있습니다.

+0

참고로,'TokyoStockExchange'가 *'Portfolio'와 함께 작동하는지 테스트 중이라면, 당신은 단위 테스트의 범위 밖에 있습니다. 'Portfolio'와'TokyoStockExchange '는 단위이며, 단위 테스트는 가능한 한 많은 다른 것들 (바람직하게는 모두)과 개별적으로 * 단위 *를 테스트하기위한 것입니다. 그들 사이의 상호 작용은 * 통합 테스트 *에서 다루고 있습니다. – cHao

+2

+1은 "코드를 유지 관리하는 데 더 많은 노력이 필요합니다"라는 단위 테스트를 사용하는 대신 값을 이해하기 위해 +1을 사용합니다. –

+0

[programmers.se]에 대한 질문이 더 많습니다. –

답변

7

TokyoStockExchange에서 격리 된 Portfolio 클래스의 논리를 테스트하려는 것이 좋습니다. Moq 또는 Rhino Mocks와 같은 모의 프레임 워크를 사용하는 경우 TokyoStockExchange에서 다양한 출력 및 동작을 쉽게 시뮬레이션하고 단위 테스트를 작성하여 Portfolio이 올바르게 응답하는지 확인할 수 있습니다. TokyoStockExchange 클래스에 대해 별도의 단위 테스트를 작성합니다.

통합 테스트가 두 클래스 사이에 필요하지 않다는 의미는 아닙니다. 모의 객체를 사용하지 않고 모든 시나리오를 올바르게 검증하기는 어렵습니다.

예제와 같이 간단한 클래스로 값을 이해하기는 어렵지만 "실제"클래스에서 배열하기가 어렵거나 불가능한 상황에 대한 테스트 케이스를 검증해야하는보다 복잡한 클래스가 주어집니다. 테스트가 훨씬 더 중요해진다.

+3

+1 정확합니다. TokyoStockExchange를 테스트하지 않고 Portfolio 클래스가 올바르게 작동하는지 테스트하고 있습니다. – CaffGeek

+0

추가 : 테스트가 실패 할 때 근본 원인을 찾는 것이 더 쉬워 지므로 격리하여 테스트하고 싶습니다. 20 개의 서로 다른 클래스로 구성된 통합 테스트를 실행하고 "실패"하면 근본 원인에 대해 20 개의 클래스를 조사하는 데 많은 시간을 할애 할 수 있습니다. 한 무리의 스터프 (예 : 19 개)를 하나의 클래스로 세분화하면 검색/수정해야 할 표면적이 크게 줄어 듭니다. –

+0

또한 절대 알려진 ** 종속성 **을 작성하여 테스트 질문에서 ** 변동성 **을 제거합니다. 이렇게하면 "이 객체는 표준 또는 예상 입력이 주어지면 예상대로 정확하게 작동합니다"라고 말할 수있는 기준선을 만듭니다. 의존성이 데이터베이스 연결을 생성하지만 어떤 이유로 연결이 실패한다고 생각해보십시오 ...이 테스트가 여러분이 테스트중인 것을 대표하지 않기 때문에 실패하지 않기를 바랍니다. –

3

단위 테스트와 통합 테스트의 두 가지 테스트가 있습니다.

단위 테스트는 코드 단위를 개별적으로 테스트하는 흰색 상자 테스트로되어 있습니다. 일반적으로 이것은 각 클래스의 공용 인터페이스를 나타냅니다.의존성을 모방하여 알려진 데이터 집합이 주어지면 유닛이 예측 가능한 결과를 반환한다는 것을 확신 할 수 있습니다.

단위 테스트에서 "분명히 모든 것이 작동합니다"라고 말하면됩니다. 이는 코드에 버그가 없다는 것을 전제로합니다. 그 가정을 할 수 있다면 처음부터 아무 것도 테스트 할 필요가 없습니다! 또한 모든 것을 단위 테스트 할 필요가 없습니다. Portfolio이 API 메소드를 호출하고 결과를 전달하는 StockExchange 상단의 얇은 레이어 일 경우 유닛 테스팅에 신경 쓰지 않아야합니다.

한편, Portfolio에 실제 논리가있는 경우 단위 테스트를 원할 수 있습니다. PortfolioStock Exchange에서 데이터를 가져 와서 데이터를 분석하고 주가가 급격히 떨어지기 시작하면 주식 가격에 이상이있을 때 사용자에게 경고 메시지를 보내는 방법이 있다고 가정 해 보겠습니다. 예상되는 상황에서 경보가 실제로 울리게되는지 확인하고 싶지만 앉아서 다음 주식 시장의 충돌을 기다리고 싶지는 않습니다. 따라서 단위 테스트에서 경고를 트리거 할 값의 종류를 생성하는 모의 Stock Exchange을 만든 다음 실제로 발생하는지 확인하십시오. 그렇지 않으면 위대한 버그를 발견했습니다.

통합 테스트는 두 장치를 직렬로 테스트하며 중요합니다. 그러나 통합 테스팅에서 어떤 종류의 시나리오를 시뮬레이션하는 것이 더 어렵습니다. 버그가 실제로 숨어있는 곳을 찾는 데는 도움이되지 않습니다. 응용 프로그램에 대한 통합 테스트를 실행 한 결과 경고가 전송되지 않았 음을 발견하면 문제가 어디에 있습니까? 타사 API에 버그가 있습니까? 주식 거래가 당신에게 나쁜 가치를 보내고 있습니까? 경고 시스템에서 잘못된 주소로 메시지를 보내고 있습니까? 분석 방법에 문제가 있음을 파악하는 데 다소 시간이 걸릴 수 있습니다.

관련 문제