Frage

Gibt es eine Möglichkeit, die Tests in ein zu integrieren? TestCase in einer bestimmten Reihenfolge laufen?Ich möchte zum Beispiel den Lebenszyklus eines Objekts von der Erstellung über die Verwendung bis zur Zerstörung trennen, muss aber sicherstellen, dass das Objekt zuerst eingerichtet wird, bevor ich die anderen Tests durchführe.

War es hilfreich?

Lösung

Möglicherweise liegt bei Ihren Tests ein Designproblem vor.

Normalerweise darf jeder Test nicht von anderen Tests abhängen, sodass er in beliebiger Reihenfolge ausgeführt werden kann.

Jeder Test muss alles, was er zum Ausführen benötigt, instanziieren und zerstören. Das wäre der perfekte Ansatz. Sie sollten niemals Objekte und Zustände zwischen Tests teilen.

Können Sie genauer erläutern, warum Sie für N Tests dasselbe Objekt benötigen?

Andere Tipps

PHPUnit unterstützt Testabhängigkeiten über @kommt darauf an Anmerkung.

Hier ist ein Beispiel aus der Dokumentation, in dem Tests in einer Reihenfolge ausgeführt werden, die Abhängigkeiten erfüllt, wobei jeder abhängige Test ein Argument an den nächsten übergibt:

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);
    }
}

Es ist jedoch wichtig zu beachten, dass dies bei Tests mit ungelösten Abhängigkeiten der Fall ist nicht ausgeführt werden (wünschenswert, da dies die Aufmerksamkeit schnell auf den fehlgeschlagenen Test lenkt).Daher ist es wichtig, bei der Verwendung von Abhängigkeiten genau darauf zu achten.

Die richtige Antwort hierfür ist eine geeignete Konfigurationsdatei für Tests.Ich hatte das gleiche Problem und habe es behoben, indem ich eine Testsuite mit der erforderlichen Reihenfolge der Testdateien erstellt habe:

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>

Wenn Sie möchten, dass Ihre Tests verschiedene Hilfsobjekte und Einstellungen gemeinsam nutzen, können Sie Folgendes verwenden setUp(), tearDown() zum hinzufügen sharedFixture Eigentum.

PHPUnit ermöglicht die Verwendung der Annotation „@depends“, die abhängige Testfälle spezifiziert und die Übergabe von Argumenten zwischen abhängigen Testfällen ermöglicht.

Stellen Sie sich meiner Ansicht nach das folgende Szenario vor, in dem ich die Erstellung und Zerstörung einer bestimmten Ressource testen muss.

Anfangs hatte ich zwei Methoden, a.testCreateResource und b.testDestroyResource

A.testCreateResource

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

B.testDestroyResource

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

Ich halte das für eine schlechte Idee, da testDestroyResource von testCreateResource abhängt.Und eine bessere Vorgehensweise wäre es

A.testCreateResource

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

B.testDestroyResource

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

Alternative Lösung:Verwenden Sie in Ihren Tests statische(!) Funktionen, um wiederverwendbare Elemente zu erstellen.Zum Beispiel (ich verwende Selenium IDE, um Tests aufzuzeichnen, und PHPUnit-Selenium (Github), um Tests im Browser auszuführen.)

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]"));
    }
}

Ok, und jetzt kann ich diese wiederverwendbaren Elemente in anderen Tests verwenden :) Zum Beispiel:

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();
    }
  • Auf diese Weise können Sie eine Hierarchie Ihrer Tests erstellen.
  • Sie können die Eigenschaft beibehalten, dass jeder Testfall vollständig voneinander getrennt ist (wenn Sie die Datenbank nach jedem Test bereinigen).
  • Und das Wichtigste: Wenn sich beispielsweise die Art der Anmeldung in Zukunft ändert, ändern Sie nur die Klasse LoginTest und benötigen in anderen Tests keinen korrekten Anmeldeteil (diese sollten nach der Aktualisierung von LoginTest funktionieren) :)

Wenn ich test ausführe, bereinige ich die Datenbank und den Anfang meines Skripts.Oben verwende ich meine SeleniumClearTestCase Klasse (ich mache dort Screenshot() und andere nette Funktionen), von der es eine Erweiterung ist MigrationToSelenium2 (von Github, um aufgezeichnete Tests in Firefox mit SeleniumIDE + ff-Plugin „Selenium IDE“ zu portieren:PHP Formatters"), eine Erweiterung meiner Klasse LaravelTestCase (es ist eine Kopie von Illuminate\Foundation esting estCase, erweitert aber nicht PHPUnit_Framework_TestCase), die Laravel so einrichtet, dass es Zugriff auf eloquent hat, wenn wir die Datenbank am Ende des Tests bereinigen möchten). Erweiterung von PHPUnit_Extensions_Selenium2TestCase.Um Laravel Eloquent einzurichten, habe ich in SeleniumClearTestCase auch die Funktion createApplication (die unter aufgerufen wird). setUp, und ich übernehme diese Funktion von laral test/TestCase)

Es gibt wirklich ein Problem mit Ihren Tests, wenn sie in einer bestimmten Reihenfolge ausgeführt werden müssen.Jeder Test sollte völlig unabhängig von den anderen sein:Es hilft Ihnen bei der Fehlerlokalisierung und ermöglicht es Ihnen, wiederholbare (und damit debuggbare) Ergebnisse zu erhalten.

Kasse Diese Seite für eine ganze Menge Ideen/Informationen, wie Sie Ihre Tests so faktorisieren können, dass Sie solche Probleme vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top