wake-up-neo.com

Jedes echte Word-Beispiel darüber, wie setUp () und tearDown () in PHPUnit verwendet werden sollten?

Die Methoden setUp() und tearDown() werden vor und nach jedem Test aufgerufen. Gibt es wirklich ein echtes Wortbeispiel, warum sollte ich das brauchen?

Bei der Überprüfung anderer Tests sehe ich immer etwas wie:

public function setUp()
{
    $this->testsub = new TestSubject();
}

public function tearDown()
{
    unset($this->testsub);
}

public function testSomething()
{
    $this->assertSame('foo', $this->testsub->getFoo());
}

Natürlich gibt es praktisch keinen Unterschied zwischen diesem Weg und dem "alten" lokalen Variablenweg.

25
gremo

Wenn Sie jede Testmethode einzeln durchführen, wird Ihr Testcode viele Zeilen enthalten, in denen einfach das zu testende Objekt erstellt wird. Dieser gemeinsam genutzte Code kann (aber nicht SOLLTE) in die Setup-Methode übernommen werden.

Alles, was zum Erstellen des zu testenden Objekts getan werden muss, gilt auch für die Setup-Methode. Beispielsweise werden Mock-Objekte erstellt, die in den Konstruktor des getesteten Objekts eingefügt werden.

Nichts davon muss abgerissen werden, da beim nächsten Aufruf von setup die Klassenmitgliedervariablen mit einem neuen Satz von Objekten initialisiert werden.

Die einzige Sache, die abgerissen werden muss, ist, wenn der Test dauerhaft etwas hinterlässt, z. B. erstellte Dateien oder Datenbankeinträge. Es ist wirklich keine gute Idee, Tests zu schreiben, die solche Dinge tun, aber irgendwann kann man nicht mehr abstrahieren und muss Dinge wie die Festplatte, Datenbank oder das reale Netzwerk anfassen.

Es ist also viel mehr Setup als zum Abreißen erforderlich, und ich lösche die Abreißmethode immer, wenn für diesen Test keine Arbeit zu erledigen ist.

In Bezug auf Mocks arbeite ich so:

private $_mockedService;
private $_object;
protected function setUp()
{
    $this->_mockedService = $this->getMock('My_Service_Class');
    $this->_object = new Tested_Class($this->_mockService);
}

public function testStuff()
{
    $this->_mockedService->expects($this->any())->method('foo')->will($this->returnValue('bar'));
    $this->assertEquals('barbar', $this->_object->getStuffFromServiceAndDouble());
}
27
Sven

Sie können eine Reihe von Fixture-Objekten instanziieren und als Instanzvariablen in jedem Test verfügbar machen, anstatt sie für jeden Test einzeln zu konstruieren.

Sie können Ressourcen wie ein Dateihandle in setUp erstellen und sicherstellen, dass Sie sie in tearDown schließen. Wenn Sie temporäre Dateien schreiben, können Sie sicherstellen, dass Sie sie löschen. Wenn Sie eine Datenbankverbindung öffnen, können Sie sie schließen (obwohl Sie dies an anderer Stelle tun möchten - setupBeforeClass/tearDownAfterClass, die für jede Testdatei und nicht für jeden Testfall aufgerufen werden.)

Es ist nur ein Vorher/Nachher-Haken, was generell eine groovige Sache ist. Verwenden Sie es, um Ihr Leben zu erleichtern, oder verwenden Sie es nicht.

4
Koobz

Sie können dies fast immer verwenden, wenn Sie eine Abhängigkeit innerhalb der Klasse haben, die Sie testen. Ein klassisches Beispiel hierfür ist eine Art Objekt, in dem der Anwendungsstatus gespeichert wird (ein Sitzungsobjekt, ein Einkaufswagen usw.).

Angenommen, ich hatte beispielsweise eine Klasse, die die Versandkosten für den Inhalt eines Warenkorbs berechnet, der durch ein Einkaufswagenobjekt definiert wurde. Angenommen, dieser Einkaufswagen wird über Abhängigkeitseinspritzung in die Versandberechnungsklasse übergeben. Um die meisten Methoden der Klasse zu testen, müssen Sie möglicherweise ein Wagenobjekt instanziieren und in die Klasse setzen, um die verschiedenen Methoden zu testen. Sie müssen möglicherweise auch Artikel in den Warenkorb hinzufügen. Möglicherweise haben Sie ein solches Setup:

public function setUp()
{
    $this->cart = new cart();
    $this->cart->add_item('abc');
    $this->cart->add_item('xyz');
}

Nehmen wir außerdem an, Ihre Testmethoden könnten die Artikel des Warenkorbs tatsächlich ändern und sie mit Versandkosteninformationen versehen. Sie möchten keine Informationen von einem Test, der in den nächsten blutet, so dass Sie den Einkaufswagen am Ende einfach abmontieren.

public function tearDown()
    unset($this->cart);
}
1
Mike Brant

In angegebenem Beispiel in akzeptierter Antwort liegt ein Speicherverlust vor. Sie sollten tearDown hinzufügen:

protected function tearDown()
{
    $this->_mockedService = null;
}

PHPUnit erstellt für jeden Testmethodenaufruf ein neues Testfallobjekt. Wenn also 4 Testmethoden vorhanden sind, gibt es 4 Objekte, und es werden 4 MockedService-Objekte erstellt. Und sie würden nicht bis zum Ende des Skripts entfernt (gesamte Testsuite). Sie müssen also alle Objekte löschen und alle Variablen in tearDown aufheben, um Speicherverluste zu verhindern.

1
Nick