2011-01-03 13 views
10

Ich versuche, mich ein wenig auf Unit-Tests mit PHPunit zu konzentrieren.PHP-Test mit Datenbank

Ich habe ein sehr gutes Tutorial gefunden hier über http://blog.nickbelhomme.com/php/phpunit-training-course-for-free_282

Aber es gibt etwas, was ich vermisse und noch nicht verstehen, wie zu tun.

Ich habe ein Anwendermodul wich alle Informationen über Benutzer unterhält. Und es gibt eine Funktion speichern, die den Benutzer in der Datenbank speichert. Also habe ich eine testFunction

public function testCanCreateUser() 
{ 
    $userData = array(
     'userName' => 'User1', 
     'firstName' => 'Joey', 
     'lastName' => 'Hendricks', 
     'email'  => '[email protected]', 
     'password' => 'f$tfe8F' 

    ); 
    $user = new Model_User($userData); 
    $user->save(); 

} 

Das erste Mal, wenn ich meinen Test laufen lassen werde diese Arbeit. Da die Datenbank leer ist. Aber wenn ich meine Tests zum zweiten Mal starte, wird es nicht funktionieren, da mein System den gleichen Benutzer nicht zweimal in der Datenbank erlaubt. Um dies zu tun, muss ich meine Testdatenbank jedes Mal neu erstellen, bevor ich meine Tests ausführe. Was ist der beste Weg, dies zu tun? Oder soll dieses Problem anders gelöst werden?

Tnx.

Antwort

21

Wenn Sie Ihre Geschäftslogik testen: Mock die Datenbank-Klasse entfernt und zurück gefälschte Daten

Wenn Sie die Klasse testen wollen, dass die SQL-Anweisungen feuert (und imho könnten Sie teste das auch, da ich irgendwie will wissen, ob mein Code mit einem echten db im Backend funktioniert gut) es wird ein wenig kompliziert, aber es gibt Möglichkeiten, es zu tun:

  • mit setUp () und tearDown(), um einen konsistenten Zustand für Ihre Daten zu erhalten, bevor Sie Ihre Tests ausführen, ist (imho) eine gute Möglichkeit, db-getriebene Unit-Tests zu schreiben. Es kann jedoch lästig sein, viele benutzerdefinierte SQL von Hand zu schreiben.

  • Um Ihr Leben ein wenig einfacher zu machen, können Sie in die DbUnit extension schauen und sehen, ob das für Ihre Anwendung funktioniert.

  • Wenn Sie wirklich in Unittesting Datenbank-Interaktionen über das Thema die beste Lese tauchen wollen ist (imho) das Kapitel über db-Unittesting in Sebastian Bergmanns phpqa book.

  • Könnte Ihre Anwendung einen benutzerdefinierten Datenbanknamen und eine automatische Einrichtung aller Tabellen zulassen, ist es auch möglich, die Datenbank einmal mit vielen Testdaten einzurichten und diese Daten in allen Ihren Tests zu verwenden. Sie könnten vorsichtig sein, obwohl dieser eine Test nicht auf Daten basiert, die von einem anderen geschrieben wurden.

+2

Nur frage mich, wie Sie wissen es einen guten Artikel in Sebastion Bergmanns Buch ist, während es noch nicht aus ist. Aber es bleibt eine komplizierte Sache. – sanders

7

Führen Sie Tests mit anderen Kopie der Datenbank, die leer und/oder in setUp() oder tearDown() Methoden gelöscht ist, aber seien Sie vorsichtig, was nicht zu tun github did.

Wenn Sie eine gute Datenbank verwenden (dh nicht mit MyISAM-Tabellen MySQL) können Sie Test in einer Transaktion wickeln und es rollen wieder nach dem Test:

function setUp() { $this->db->exec("BEGIN"); } 
function tearDown() { $this->db->exec("ROLLBACK"); } 

Der Nachteil ist, dass man nicht Testcode, der Transaktionen verwendet (es sei denn, Sie abstrahieren das und emulieren mit Sicherungspunkten, aber das ist zweifelhaft).

Im Idealfall sollten Sie Dependency Injection und Lauftests auf gefälschte Datenbank-Klasse verwenden:

$fakedb = new DatabaseThatDoesntReallySaveThings(); 
$user = new Model_User($fakedb, $userData); 
$user->save(); 
$this->assertTrue($fakedb->wasAskedToSaveUser()); 
2

Ich glaube, Sie tearDown() Methode verwenden, können die gespeicherten Daten zu reinigen.

protected $_user; 

public function testCanCreateUser() 
{ 
    ... 

    $this->_user = new Model_User($userData); 
    $this->_user->save(); 
} 

public function tearDown() 
{ 
    $this->_user->delete(); 
}