수업을 단위로 테스트했습니다. 이제 통합 테스트를 시작하려면 어떻게해야합니까?


19

MailChimpRecipient라는 MailChimp 목록에서 수신자를 관리하는 클래스를 작성했습니다. 타사 API 래퍼 인 MCAPI 클래스를 사용합니다.

http://apidocs.mailchimp.com/api/1.3/ http://apidocs.mailchimp.com/api/downloads/

MCAPI 객체를 MailChimpRecipient 객체의 생성자로 전달하므로 PHPUnit을 사용하여 자체 클래스의 모든 논리를 테스트하는 단위 테스트를 작성했습니다 (MCAPI 클래스는 테스트하지 않음). 코드 범위가 100 %이며 모든 테스트를 통과했습니다. 이것은 MCAPI 객체를 조롱하고 스터 빙함으로써 수행됩니다.

다음 단계는 PHPUnit을 사용하여 통합 테스트를 작성하는 것입니다. 여기서 실제 MCChim 개체를 사용하여 MailChimpRecipient 픽스처를 구성하고 실제 MailChimp 목록을 사용하도록 설정했습니다.

필자는 통합 테스트라고 생각하는 것을 작성했습니다. 기본적으로 테스트는 다음과 같이 객체의 공용 인터페이스를 다시 실행합니다.

public function testAddedRecipientCanBeFound()
{
    $emailAddress = 'fred@fredsdomain.com';
    $forename = 'Fred';
    $surname = 'Smith';

    // First, delete the email address if it is already on the list
    $oldRecipient = $this->createRecipient();
    if($oldRecipient->find($emailAddress))
    {
        $oldRecipient->delete();
    }
    unset($oldRecipient);

    // Add the recipient using the test data
    $newRecipient = $this->createRecipient();
    $newRecipient->setForename($forename);
    $newRecipient->setSurname($surname);
    $newRecipient->setEmailAddress($emailAddress);
    $newRecipient->add();
    unset($newRecipient);

    // Assert that the recipient can be found using the same email address
    $this->assertTrue($this->_recipient->find($emailAddress));
}

"통합"테스트는 클래스 내부를 테스트하지 않습니다. 실제 MCAPI 객체가 제공되면 광고 된대로 동작하는지 확인합니다.

이 올바른지? 이것이 통합 테스트를 실행하는 가장 좋은 방법입니까? 결국 내부는 단위 테스트로 테스트되었습니다. 통합 테스트가 실제로 작동하는 방식을 테스트하기 위해 통합 테스트가 있다고 생각하는 것이 맞습니까?

한 단계 더 나아 가기 위해 MailChimpRecipient 클래스는 인터페이스를 구현하며 다른 클래스에서도 구현됩니다. 아이디어는 팩토리를 사용하여 다른 유형의 메일 링리스트 수신자 오브젝트를 내 코드로 전달하는 것인데, 다른 메일 링리스트 제공자를 사용하더라도 모두 동일한 작업을 수행합니다. 통합 테스트에서 해당 인터페이스를 테스트하므로 인터페이스를 구현하는 모든 클래스에 대해 해당 인터페이스를 사용하는 것은 어떻습니까? 그런 다음 나중에 교환 할 수있는 새 클래스를 디자인하면 프로젝트에 삽입하기 전에 동일한 통합 테스트를 실행할 수 있습니다.

이것이 합리적으로 들립니까? 단위 테스트는 물체의 내부를 테스트하고, 통합 테스트는 그것이 광고 된대로 동작하는지 확인합니까?


4
테스트에 너무 많은 논리가 있다고 생각합니다. 어설 션을 수행 할 때까지 많은 코드를 실행합니다. 수신자의 삭제를 먼저 테스트하고 싶을 것입니다. 그러나 그것은 당신의 질문에 대답하는 것이 아니라 단지 의견입니다.
hakre

1
setUp테스트를 수행 할 근거를 설정하려면 이 기능을 사용해야 합니다. 입력이 정의되어 있지 않으면 실제로 테스트 할 수 없습니다. 입력은 정확하고 엄격해야하며 항상 동일해야합니다. 테스트의 전제 조건이 충족되지 않으면 테스트를 건너 뜁니다. 그런 다음 건너 뛴 이유와 추가 테스트를 추가해야하는 경우 및 / 또는 setUp올바르게 수행되지 않은 경우를 분석하십시오 .
hakre

1
또한 자체 테스트 내에서 테스트 값을 하드 코딩하지 말고 해당 클래스 멤버를 만들어 테스트 전체에서 공유하고 (중앙 위치에서 변경) 사용 DataProvider(테스트에 매개 변수로 입력을 제공하는 기능)하십시오.
hakre

1
테스트 기능이 작동하는 모든 것의 의미로 입력하십시오. 수신자 추가를 테스트 할 때 이미 존재하지 않는지 확인하려는 경우 삭제가 발생할 경우 삭제를 확인해야합니다. 그렇지 않으면 테스트의 전제 조건을 테스트 할 수 없습니다.
hakre

1
좋은 질문에 +1하지만 프로그래머에게 이전하기로 투표했습니다. 테스트 전략에 대한 질문이있는 곳
GordonM

답변:


17

코드를 테스트 할 때는 다음 세 가지 영역에주의를 기울여야합니다.

  • 시나리오 테스트
  • 기능 테스트
  • 단위 테스트

일반적으로 각 범주에서 보유하는 테스트의 양은 피라미드 모양으로 하단에 많은 단위 테스트, 중간에 일부 기능 테스트 및 몇 가지 시나리오 테스트를 의미합니다.

단위 테스트를 사용하면 테스트중인 클래스가 사용하는 모든 것을 모의하고 순수 격리 된 상태에서 테스트 할 수 있습니다 (이것은 클래스 내에서 모든 종속성을 검색하여 테스트 할 때 교체 할 수 있도록하는 것이 중요합니다).

단위 테스트를 통해 '행복한 경로'뿐만 아니라 모든 오류 조건을 모두 테스트 할 수 있습니다.

모든 장치가 독립적으로 작동하는지 완전히 확신하는 경우 몇 가지 테스트 (기능 테스트)를 작성하여 장치가 결합 될 때도 작동하는지 확인하십시오. 그런 다음 모든 기능 모듈 간의 배선을 테스트하는 시나리오 테스트를 작성합니다.

예를 들어 자동차를 테스트한다고 가정합니다.

차량 전체를 조립할 수 있으며 운전자는 가능한 모든 상태를 점검하지만 실제로는 어려울 수 있습니다.

대신 모든 가능성으로 엔진의 작은 부분을 테스트합니다 (단위 테스트)

그런 다음 기능 테스트가 될 전체 엔진 (자동차와 분리 된)을 테스트합니다.

마지막 시험으로, 열쇠를 넣고 차를 시동하여 주차장으로 운전합니다. 그것이 작동하면 모든 부품 (배터리, 연료, 엔진 등)이 연결되어 있음을 알고 있으며 개별적으로 테스트했기 때문에 전체 자동차가 올바르게 작동하는지 확인할 수 있습니다.

따라서 귀하의 경우, 모든 오류 조건과 단위 테스트의 행복한 길을 테스트했으며 배선이 올바른지 확인하기 위해 '실제 구성 요소'로 엔드 투 엔드 테스트 만하면된다는 것을 알고 있습니다.

다른 몇 가지 요점

  • 단위 테스트에서 조건부 논리를 피하십시오. 정리해야하는 경우 일종의 전역 상태를 사용하고 테스트가 갑자기 서로 영향을 줄 수 있습니다.
  • 테스트와 관련이없는 데이터를 지정하지 마십시오. 성이나 성을 변경하면 테스트가 실패합니까? 중요한 이메일 주소이기 때문에가 아니라 테스트에서 명시 적으로 언급했기 때문에 확실하지 않습니다. 테스트 데이터를 작성하고 실제로 중요한 것을 명시하기 위해 빌더 패턴을 살펴보십시오.

고마워, 그것은 내가 생각한 것을 많이 확인합니다. 명확히하기 위해-이것은 단위 테스트가 아닙니다. 객체를 완전히 격리하여 테스트하고 100 % 코드 적용 범위를 갖는 단위 테스트를 이미 작성했습니다. 이것은 실제 MCAPI 객체를 주입 할 때 작동하는지 확인하기 위해 통합 테스트를 의미했습니다. 목록에 추가 된 수신자를 모두 삭제하면됩니다. 모든 정리가 완료되었으므로 테스트가 서로 영향을 미치지 않도록 구현되었습니다. 대신 무엇을 제안 하시겠습니까?

1
네! 이미 단위 테스트를 수행 한 것으로 알고 있습니다. MCAPI 개체가받는 사람을 추적하고 정리해야합니까? 타사의 '문제'인 경우 통합 테스트에서 수행 할 수있는 작업이 없습니다. 다른 쪽에서 목록을 추적하는 경우 전역 데이터 (및 싱글 톤)를 피하여 테스트가 서로 영향을 미치지 않도록해야합니다. 완벽한 세상에서 테스트가 시작 / 종료 될 때 물건을 청소하고 디자인 결함을 지적하지만 실제 환경에서는 항상 피할 수는 없습니다.
Wouter de Kort

1
시나리오 테스트는 실제로 PHPUnit에 적합한 것이 아니라고 덧붙입니다. Yu는 Selenium과 같은 브라우저에서 실행할 수있는 도구 나 jMeter와 같은 브라우저를 시뮬레이션 할 수있는 도구를보고 싶을 수 있습니다.
GordonM

고마워요! 테스트 가능한 코드를 작성할 때 알아야 할 것이 많지 않습니다. 나 자신에게이 책의 사본을 주문했습니다 amazon.co.uk/...를 . 다행스럽게도, 당신이 말한 내용을 읽은 후에 조금 더 이해가 되길 바랍니다. @Wouter, 테스트로 인해 이메일 주소가 목록에 추가 되었기 때문에 수신자를 삭제하려고합니다. 목록이 해당 테스트의 영향을받지 않도록 삭제하고 있습니다.

1
@LewisBassett 나는 Php 개발자는 아니지만 xUnit 테스트 패턴 ( amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 )은 확실히 잘 읽었습니다. misko.hevery.com/code-reviewers-guide 의 기사 도 정말 흥미 롭습니다.
Wouter de Kort
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.