문제

내부에서 테스트를 받을 수 있는 방법이 있나요? TestCase 특정 순서로 실행하려면?예를 들어, 객체의 수명 주기를 생성에서 사용, 폐기까지 분리하고 싶지만 다른 테스트를 실행하기 전에 먼저 객체가 설정되었는지 확인해야 합니다.

도움이 되었습니까?

해결책

테스트에 디자인 문제가 있을 수 있습니다.

일반적으로 각 테스트는 다른 테스트에 의존해서는 안 되므로 순서에 관계없이 실행될 수 있습니다.

각 테스트는 실행하는 데 필요한 모든 것을 인스턴스화하고 파괴해야 합니다. 이는 완벽한 접근 방식이 될 것입니다. 테스트 간에 개체와 상태를 공유해서는 안 됩니다.

N 테스트에 동일한 객체가 필요한 이유에 대해 더 구체적으로 설명할 수 있습니까?

다른 팁

PHPUnit은 다음을 통해 테스트 종속성을 지원합니다. @의존 주석.

다음은 종속성을 충족하는 순서로 테스트가 실행되는 문서의 예입니다. 각 종속 테스트는 인수를 다음 테스트에 전달합니다.

class StackTest extends PHPUnit_Framework_TestCase
{
    public function testEmpty()
    {
        $stack = array();
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
     * @depends testEmpty
     */
    public function testPush(array $stack)
    {
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack)
    {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEmpty($stack);
    }
}

그러나 해결되지 않은 종속성이 있는 테스트는 ~ 아니다 실행됩니다(이렇게 하면 실패한 테스트에 빠르게 주의를 끌 수 있으므로 바람직합니다).따라서 종속성을 사용할 때는 세심한 주의를 기울이는 것이 중요합니다.

이에 대한 정답은 테스트에 적합한 구성 파일입니다.나는 동일한 문제가 있었고 필요한 테스트 파일 순서로 테스트 스위트를 생성하여 문제를 해결했습니다.

phpunit.xml:

<phpunit
        colors="true"
        bootstrap="./tests/bootstrap.php"
        convertErrorsToExceptions="true"
        convertNoticesToExceptions="true"
        convertWarningsToExceptions="true"
        strict="true"
        stopOnError="false"
        stopOnFailure="false"
        stopOnIncomplete="false"
        stopOnSkipped="false"
        stopOnRisky="false"
>
    <testsuites>
        <testsuite name="Your tests">
            <file>file1</file> //this will be run before file2
            <file>file2</file> //this depends on file1
        </testsuite>
    </testsuites>
</phpunit>

테스트에서 다양한 도우미 개체와 설정을 공유하려면 다음을 사용하세요. setUp(), tearDown() 에 추가하다 sharedFixture 재산.

PHPUnit에서는 종속 테스트 사례를 지정하고 종속 테스트 사례 간에 인수를 전달할 수 있는 '@dependents' 주석을 사용할 수 있습니다.

내 생각에는 특정 리소스의 생성 및 삭제를 테스트해야 하는 다음 시나리오를 생각해 보세요.

처음에는 두 가지 방법이 있었습니다.testCreateResource 및 b.테스트파괴자원

ㅏ.테스트생성자원

<?php
$app->createResource('resource');
$this->assertTrue($app->hasResource('resource'));
?>

비.테스트파괴자원

<?php
$app->destroyResource('resource');
$this->assertFalse($app->hasResource('resource'));
?>

testDestroyResource는 testCreateResource에 의존하기 때문에 이것은 나쁜 생각이라고 생각합니다.그리고 더 나은 연습은 다음과 같습니다

ㅏ.테스트생성자원

<?php
$app->createResource('resource');
$this->assertTrue($app->hasResource('resource'));
$app->deleteResource('resource');
?>

비.테스트파괴자원

<?php
$app->createResource('resource');
$app->destroyResource('resource');
$this->assertFalse($app->hasResource('resource'));
?>

대체 솔루션:재사용 가능한 요소를 생성하려면 테스트에 static(!) 함수를 사용하세요.예를 들어 (저는 Selenium IDE를 사용하여 테스트를 기록하고 phpunit-selenium(github)을 사용하여 브라우저 내에서 테스트를 실행합니다)

class LoginTest extends SeleniumClearTestCase
{
    public function testAdminLogin()
    {
        self::adminLogin($this);
    }

    public function testLogout()
    {
        self::adminLogin($this);
        self::logout($this);
    }

    public static function adminLogin($t)
    {
        self::login($t, 'john.smith@gmail.com', 'pAs$w0rd');
        $t->assertEquals('John Smith', $t->getText('css=span.hidden-xs'));
    }

    // @source LoginTest.se
    public static function login($t, $login, $pass)
    {
        $t->open('/');
        $t->click("xpath=(//a[contains(text(),'Log In')])[2]");
        $t->waitForPageToLoad('30000');
        $t->type('name=email', $login);
        $t->type('name=password', $pass);
        $t->click("//button[@type='submit']");
        $t->waitForPageToLoad('30000');
    }

    // @source LogoutTest.se
    public static function logout($t)
    {
        $t->click('css=span.hidden-xs');
        $t->click('link=Logout');
        $t->waitForPageToLoad('30000');
        $t->assertEquals('PANEL', $t->getText("xpath=(//a[contains(text(),'Panel')])[2]"));
    }
}

좋아요, 이제 다른 테스트에서 이 재사용 가능한 요소를 사용할 수 있습니다 :) 예를 들면 다음과 같습니다.

class ChangeBlogTitleTest extends SeleniumClearTestCase
{
    public function testAddBlogTitle()
    {
      self::addBlogTitle($this,'I like my boobies');
      self::cleanAddBlogTitle();
    }

    public static function addBlogTitle($t,$title) {
      LoginTest::adminLogin($t);

      $t->click('link=ChangeTitle');
      ...
      $t->type('name=blog-title', $title);
      LoginTest::logout($t);
      LoginTest::login($t, 'paris@gmail.com','hilton');
      $t->screenshot(); // take some photos :)
      $t->assertEquals($title, $t->getText('...'));
    }

    public static function cleanAddBlogTitle() {
        $lastTitle = BlogTitlesHistory::orderBy('id')->first();
        $lastTitle->delete();
    }
  • 이러한 방식으로 테스트의 계층 구조를 구축할 수 있습니다.
  • 각 테스트 케이스가 서로 완전히 분리되어 있다는 속성을 강철로 유지할 수 있습니다(각 테스트 후에 DB를 정리하는 경우).
  • 그리고 가장 중요한 점은 예를 들어 향후 로그인 변경 방법이 LoginTest 클래스만 수정하고 다른 테스트에서는 올바른 로그인 부분이 필요하지 않은 경우(LoginTest 업데이트 후에 작동해야 함) :)

테스트를 실행하면 스크립트가 시작부터 DB 광고를 정리합니다.위에서는 내 SeleniumClearTestCase 클래스(저는 거기에 스크린샷()과 다른 멋진 기능을 만듭니다)은 다음의 확장입니다. MigrationToSelenium2 (github에서 seleniumIDE + ff 플러그인 "Selenium IDE:내 클래스 LaravelTestCase(Illuminate\Foundation esting estCase의 복사본이지만 PHPUnit_Framework_TestCase를 확장하지 않음)의 확장인 PHP Formatters")는 테스트가 끝날 때 DB를 정리할 때 eloquent에 액세스할 수 있도록 laravel을 설정합니다. PHPUnit_Extensions_Selenium2TestCase의 확장입니다.laravel eloquent를 설정하려면 SeleniumClearTestCase 함수 createApplication(에서 호출됨)에도 있습니다. setUp, 나는 이 함수를 laral test/TestCase에서 가져옵니다)

테스트를 특정 순서로 실행해야 한다면 실제로 문제가 있는 것입니다.각 테스트는 다른 테스트와 완전히 독립적이어야 합니다.결함 위치 파악에 도움이 되며 반복 가능한(따라서 디버깅 가능한) 결과를 얻을 수 있습니다.

점검 이 장소 이러한 종류의 문제를 피하는 방식으로 테스트를 고려하는 방법에 대한 수많은 아이디어/정보를 제공합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top