Zend_Test_PHPUnit
Zend_Test_PHPUnit bietet einen Testfall für MVC-Anwendungen,
der Zusicherungen für Tests auf eine Vielzahl von Verantwortlichkeiten enthält. Um
zu verstehen, was man damit machen kann, ist es wahrscheinlich am einfachsten, sich das folgende
Beispiel anzusehen.
Example #1 Beispiel eines Testfalls für ein Anwendungs-Login
Das folgende ist ein einfacher Testfall für einen UserController,
um verschiedene Dinge zu prüfen:
-
Das Login-Formular soll nicht-authentifizierten Benutzern angezeigt werden.
-
Wenn sich ein Benutzer einloggt, soll er zu seiner Profilseite umgeleitet
werden und diese Profilseite soll relevante Informationen enthalten.
Dieses spezielle Beispiel setzt ein paar Dinge voraus. Zunächst verschieben wir das meiste
unseres Bootstrappings in ein Plugin. Das vereinfacht das Setup des Testfalls, da es uns
erlaubt, unsere Umgebung gezielt zu definieren und die
Anwendung mit einer einzigen Zeile zu starten. Außerdem setzt unser spezielles Beispiel auch
voraus, dass das automatische Laden von Klassen aktiviert ist, so dass wir uns nicht um das Laden
der benötigten Klassen kümmern müssen (wie die richtigen Controller, Plugins, usw).
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
public function setUp()
{
$this-> bootstrap = array($this, 'appBootstrap');
parent::setUp();
}
public function appBootstrap()
{
$this->frontController
->registerPlugin(new Bugapp_Plugin_Initialize('development'));
}
public function testCallWithoutActionShouldPullFromIndexAction()
{
$this->dispatch('/user');
$this->assertController('user');
$this->assertAction('index');
}
public function testIndexActionShouldContainLoginForm()
{
$this->dispatch('/user');
$this->assertAction('index');
$this->assertQueryCount('form#loginForm', 1);
}
public function testValidLoginShouldGoToProfilePage()
{
$this->request->setMethod('POST')
'username' => 'foobar',
'password' => 'foobar'
));
$this->dispatch('/user/login');
$this->assertRedirectTo('/user/view');
$this->resetRequest()
->resetResponse();
$this->request->setMethod('GET')
$this->dispatch('/user/view');
$this->assertRoute('default');
$this->assertModule('default');
$this->assertController('user');
$this->assertAction('view');
$this->assertNotRedirect();
$this->assertQuery('dl');
$this->assertQueryContentContains('h2', 'User: foobar');
}
}
Dieses Beispiel könnte auch einfacher geschrieben werden -- nicht alle der gezeigten
Zusicherungen sind notwendig. Hoffentlich zeigt es, wie einfach es sein kann, die eigene
Anwendung zu testen.
Bootstrapping der eigenen Testfälle
Wie im Login-Beispiel gezeigt, sollten
alle MVC-Testfälle
Zend_Test_PHPUnit_ControllerTestCase erweitern. Diese Klasse
ihrerseits erweitert PHPUnit_Framework_TestCase und gibt einem alle
Strukturen und Zusicherungen, die man von PHPUnit erwartet -- sowie einiges an Scaffolding und
Zusicherungen, die genau auf die Zend Framework MVC-Implementation zugeschnitten sind.
Um die eigene MVC-Anwendung zu testen, muß diese ein Bootstrap ausführen.
Es gibt verschiedene Wege, dies zu tun, wobei sich alle der öffentlichen
$bootstrap-Eigenschaft bedienen.
Erstens und möglicherweise am zielgerichtetsten kann man einfach eine Instanz von
Zend_Application erstellen, wie man es in der
index.php machen würde und diese der $bootstrap-Eigenschaft
zuweisen. Normalerweise macht man das in der setUp()-Methode;
anschließend muss man parent::setUp() aufrufen:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
public function setUp()
{
// Zuordnen und Initiieren in einem Schritt:
$this->bootstrap = new Zend_Application(
'testing',
APPLICATION_PATH . '/configs/application.ini'
);
parent::setUp();
}
}
Zweitens kann diese Eigenschaft so gesetzt werden, dass sie auf eine Datei zeigt. Wenn dieser
Weg gewählt wird, sollte diese Datei nicht den Front-Controller ausführen,
sondern stattdessen den Front-Controller konfigurieren und alles, was die Anwendung an
speziellen Anforderungen benötigt.
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
public $bootstrap = '/path/to/bootstrap/file.php'
// ...
}
Drittens kann ein PHP-Callback angegeben werden, der nach dem Bootstrap
der Anwendung ausgeführt wird. Diese Methode kann im Login-Beispiel gesehen werden. Wenn das
Callback eine Funktion oder statische Methode ist, könnte sie auch in der Klasse gesetzt
werden:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
public $bootstrap = array('App', 'bootstrap');
// ...
}
In Fällen, in denen eine Objektinstanz notwendig ist, empfehlen wir die Durchführung in der
eigenen setUp()-Methode:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
public function setUp()
{
// Verwende die 'start' Methode einer Bootstrap-Objektinstanz:
$bootstrap = new Bootstrap('test');
$this-> bootstrap = array($bootstrap, 'start');
parent::setUp();
}
}
Man beachte, dass parent::setUp() aufgerufen wird; das ist notwendig, da
die setUp()-Methode von
Zend_Test_PHPUnit_ControllerTestCase den Rest des Bootstrap-Prozesses
durchführen wird (was den Aufruf des Callbacks einschließt).
Während der normalen Anwendung wird die setUp()-Methode das
Bootstrap der Anwendung ausführen. Dieser Prozess wird zunächst das Löschen der Umgebung
enthalten, um einen sauberen Anfragestatus zu erhalten, das Zurücksetzen aller Plugins, Helfer
und Antwortobjekte. Sobald das getan wurde, wird sie anschließend die Datei mit
include() laden, die in $bootstrap angegeben
ist oder den spezifizierten Callback aufrufen.
Das Bootstrappen sollte so nahe wie möglich daran sein, wie die Anwendung das Bootstrap
durchführt. Trotzdem gibt es einige Fallstricke:
-
Wir bieten keine alternative Implementierung der Anfrage- und Antwortobjekte; diese
werden nicht verwendet. Zend_Test_PHPUnit_ControllerTestCase
verwendet eigene Anfrage- und Antwortobjekte,
Zend_Controller_Request_HttpTestCase und
Zend_Controller_Response_HttpTestCase. Diese Objekte stellen
Methoden zur Verfügung, um die Anfrageumgebung gezielt aufzusetzen und um auf
speziellem Weg die Antwort als Prüfgegenstand abzuholen.
-
Man sollte nicht erwarten Server-spezifisches zu testen. Mit anderen Worten, die Tests
garantieren nicht, dass der Code in einer speziellen Serverkonfiguration läuft, aber
dass die Anwendung wie erwartet funktionieren sollte und der Router eine gegebene
Anfrage routen kann. Aus diesem Grund sollten keine Server-spezifischen Header im
Anfrageobjekt gesetzt werden.
Sobald die Anwendung das Bootstrapping ausgeführt hat, kann damit begonnen werden, eigene
Tests zu erstellen.
Testen eigener Controller und MVC Anwendungen
Sobald man sein Bootstrap hat, kann man mit dem Testen beginnen. Testen funktioniert
grundsätzlich so, wie man es in einer PHPUnit-TestSuite erwarten würde, mit ein paar kleinen
Unterschieden.
Zuerst muss man eine URL ausführen, die getestet werden soll, indem die
dispatch()-Methode des Testfalls ausgeführt wird:
class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
// ...
public function testHomePage()
{
$this->dispatch('/');
// ...
}
}
Manchmal ist es trotzdem nötig, zusätzliche Informationen anzugeben --
GET und POST Variablen, COOKIE Informationen, usw.
Man kann die Anfrage mit folgenden Informationen ausstatten:
class FooControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
// ...
public function testBarActionShouldReceiveAllParameters()
{
// Setzt GET Variablen:
$this-> request-> setQuery(array(
'foo' => 'bar',
'bar' => 'baz',
));
// Setzt POST Variablen:
$this-> request-> setPost(array(
'baz' => 'bat',
'lame' => 'bogus',
));
// Setzt einen Cookie Wert:
$this->request->setCookie('user', 'matthew');
// or many:
$this-> request-> setCookies(array(
'host' => 'foobar',
));
// Setzt sogar Header:
$this->request->setHeader('X-Requested-With', 'XmlHttpRequest');
// Setzt die Anfrage Methode:
$this->request->setMethod('POST');
// Ausführung:
$this->dispatch('/foo/bar');
// ...
}
}
Jetzt wurde die Anfrage durchgeführt, es ist also Zeit Zusicherungen zu prüfen.
Controller Tests und der Redirector Action Helper
Important
Der Redirect Action Helper hat Probleme mit der Anweisung exit(),
wenn die Methode gotoAndExit() verwendet wird
und wird dann natürlich auch einen Test beenden, der für diese Methode läuft. Um die
eigene Anwendung testbar zu machen, sollte diese Methode nicht am Redirector
verwendet werden.
Durch seine Natur führt das Redirector Action Helper Plugin ein Redirect aus und steigt
nach diesem aus. Weil man Teile einer Anwendung nicht testen kann, wenn diese
Exit-Aufrufe durchführen, deaktiviert
Zend_Test_PHPUnit_ControllerTestCase den Exit-Teil des
Redirectors automatisch, was zu unterschiedlichen Verhaltensweisen in Tests und echter Anwendung
führen kann. Um sicherzustellen, dass der Redirect richtig arbeitet, sollte man diesen
auf folgendem Weg durchführen:
class MyController extends Zend_Controller_Action
{
public function indexAction()
{
if ($someCondition == true) {
return $this->_redirect(...);
} else if ($anotherCondition == true) {
$this->_redirector->gotoSimple("foo");
return;
}
// Mach was
}
}
Important
Abhängig von der eigenen Anwendung kann es sein, dass das nicht genug ist, da eine
zusätzliche preDispatch()- oder
postDispatch()-Logik ausgeführt werden könnte. Das kann
aktuell mit Zend_Test auf keine vernünftige Weise behandelt werden.
Zusicherungen
Zusicherungen sind das Herz der UnitTests; sie können verwendet werden um zu prüfen, ob
die Ergebnisse das sind was man erwartet. Zu diesem Zweck bietet
Zend_Test_PHPUnit_ControllerTestCase eine Anzahl an Zusicherungen, um
das Testen eigener MVC-Anwendungen und Controller einfacher zu machen.
CSS-Selektor-Zusicherungen
CSS-Selektoren sind ein einfacher Weg um zu prüfen, dass bestimmte
Teile im Inhalt der Antwort enthalten sind. Mit ihnen ist es auch trivial
sicherzustellen, dass Elemente vorhanden sind, die für Javascript-UIs und/oder
AJAX-Integrationen notwendig sind; die meisten JS-Toolkits bieten
einige Mechanismen für das Abholen von DOM-Elementen an, die auf
CSS-Selektoren basieren, so dass die Syntax die gleiche wäre.
Diese Funktionalität wird über Zend_Dom_Query
angeboten und in ein Set von 'Query'-Zusicherungen integriert. Jede dieser Zusicherungen
nimmt als erstes Argument einen CSS-Selektor mit optional
hinzugefügten Argumenten und/oder einer Fehlermeldung, basierend auf dem Typ der
Zusicherung. Die Regeln für das Schreiben der CSS-Selektoren kann im
Kapitel Theorie der Anwendung von
Zend_Dom_Query gefunden werden. Abfragezusicherungen enthalten:
-
assertQuery($path, $message): Nimmt an, dass ein
oder mehrere DOM Elemente, die dem gegebenen CSS-Selektor
entsprechen, vorhanden sind. Wenn eine $message vorhanden
ist, wird diese jeder fehlgeschlagenen Meldung einer Zusicherung vorangestellt.
-
assertQueryContentContains($path, $match, $message):
Nimmt an, dass ein oder mehrere DOM Elemente, die dem angegebenen
CSS-Selektor entsprechen, vorhanden sind, und dass
zumindest einer dem Inhalt entspricht, der in $match angegeben
wurde. Wenn eine $message vorhanden ist, wird diese
jeder fehlgeschlagenen Meldung einer Zusicherung vorangestellt.
-
assertQueryContentRegex($path, $pattern, $message):
Nimmt an, dass ein oder mehrere DOM-Elemente vorhanden sind,
die dem angegebenen CSS-Selektor entsprechen und dass
zumindest einer dem Regulären Ausdruck entspricht, der in $pattern
angegeben wurde, Wenn eine $message vorhanden
ist, wird diese jeder fehlgeschlagenen Meldung einer Zusicherung vorangestellt.
-
assertQueryCount($path, $count, $message): Nimmt
an, dass exakt $count DOM-Elemente dem angegebenen
CSS Selektor entsprechen. Wenn eine
$message vorhanden ist, wird diese jeder fehlgeschlagenen
Meldung einer Zusicherung vorangestellt.
-
assertQueryCountMin($path, $count, $message):
Nimmt an, dass zumindest $count DOM-Element dem angegebenen
CSS Selektor entsprechen. Wenn eine
$message vorhanden ist, wird diese jeder fehlgeschlagenen
Meldung einer Zusicherung vorangestellt. Achtung: Die
Spezifizierung eines Wertes von 1 für $count ist das Gleiche
wie die einfache Verwendung von assertQuery().
-
assertQueryCountMax($path, $count, $message):
Nimmt an, dass es nicht mehr als $count DOM-Elemente gibt, die
dem angegebenen CSS-Selektor entsprechen. Wenn eine
$message vorhanden ist, wird diese jeder fehlgeschlagenen
Meldung einer Zusicherung vorangestellt. Achtung: Die
Spezifizierung eines Wertes von 1 für $count ist das Gleiche
wie die einfache Verwendung von assertQuery().
Zusätzlich hat jede der obigen Methoden eine 'Not'-Variante, die eine negative Zusicherung
anbietet: assertNotQuery(),
assertNotQueryContentContains(),
assertNotQueryContentRegex() und
assertNotQueryCount(). (Es ist zu beachten, dass die min und max
Zählen keine dieser Varianten haben, was aus logischen Gründen so ist.)
XPath-Zusicherungen
Einige Entwickler sind mit XPath vertrauter als mit CSS-Selektoren,
und deshalb werden für alle Abfrage
Zusicherungen auch XPath-Varianten engeboten. Diese sind:
-
assertXpath($path, $message = '')
-
assertNotXpath($path, $message = '')
-
assertXpathContentContains($path, $match, $message =
'')
-
assertNotXpathContentContains($path, $match, $message =
'')
-
assertXpathContentRegex($path, $pattern, $message = '')
-
assertNotXpathContentRegex($path, $pattern, $message =
'')
-
assertXpathCount($path, $count, $message = '')
-
assertNotXpathCount($path, $count, $message = '')
-
assertXpathCountMin($path, $count, $message = '')
-
assertNotXpathCountMax($path, $count, $message = '')
Umleitungszusicherungen
Oft wird eine Aktion umgeleitet. Statt der Umleitung zu folgen, erlaubt es
Zend_Test_PHPUnit_ControllerTestCase, diese Umleitungen mit einer
handvoll von Zusicherungen zu Testen.
-
assertRedirect($message = ''): Nimmt einfach an, dass
eine Umleitung stattgefunden hat.
-
assertNotRedirect($message = ''): Nimmt einfach an, dass
keine Umleitung stattgefunden hat.
-
assertRedirectTo($url, $message = ''): Nimmt an, dass
eine Umleitung stattgefunden hat und dass der Wert des Ziel-Headers die
angegebene $url ist.
-
assertNotRedirectTo($url, $message = ''): Nimmt an, dass
eine Umleitung entweder NICHT stattgefunden hat oder dass der Wert des
Ziel-Headers NICHT die angegebene $url ist.
-
assertRedirectRegex($pattern, $message = ''): Nimmt an,
dass eine Umleitung stattgefunden hat und dass der Wert des Ziel-Headers dem
durch $pattern angegebenen regulären Ausdruck entspricht.
-
assertNotRedirectRegex($pattern, $message = ''): Nimmt
an, dass eine Umleitung entweder NICHT stattgefunden hat oder dass der Wert des
Ziel-Headers NICHT dem durch $pattern angegebenen regulären
Ausdruck entspricht.
Anfragezusicherungen
Es ist oft sinnvoll gegen die letzte Aktion, den Controller und das Modul zu prüfen;
zusätzlich ist es möglich die genommene Route die prüfen. Die folgenden Zusicherungen
können in diesen Fällen helfen:
-
assertModule($module, $message = ''): Nimmt an, dass das
angegebene Modul in der letzten Dispatch-Aktion verwendet wurde.
-
assertController($controller, $message = ''): Nimmt an,
dass der angegebene Controller in der letzten ausgeführten Aktion ausgewählt
wurde.
-
assertAction($action, $message = ''): Nimmt an, dass die
angegebene Aktion zuletzt ausgeführt wurde.
-
assertRoute($route, $message = ''): Nimmt an, dass die
angegebene benannte Route dem Router entsprochen hat.
Jede hat auch eine 'Not'-Variante für negative Zusicherungen.
Beispiele
Zu wissen, wie man die eigene Infrastruktur für Tests einstellt und wie Zusicherungen zu
erstellen sind, ist nur die halbe Miete; jetzt ist es Zeit, sich einige Testszenarien
anzuschauen und herauszufinden, wie diese wirksam eingesetzt werden können.
Example #2 Den UserController testen
Betrachten wir eine Standardaufgabe für eine Webseite: Authentifizierung und Registrierung
von Benutzern. In unserem Beispiel definieren wir einen UserController, um das zu
behandeln und haben die folgenden Anforderungen:
-
Wenn ein Benutzer nicht authentifiziert ist, wird er immer zur Login-Seite des
Controllers umgeleitet, unabhängig von der angeforderten Aktion.
-
Die Login-Formularseite wird sowohl das Login-Formular als auch das
Registrationsformular anzeigen.
-
Die Angabe von ungültigen Anmeldedaten soll zur Anzeige des Login-Formulars
führen.
-
Das Ansehen der Anmeldedaten soll zu einer Umleitung zur Profilseite des
Benutzers führen.
-
Die Profilseite soll angepasst werden, um den Benutzernamen des Benutzers
anzuzeigen.
-
Authentifizierte Benutzer, welche die Loginseite besuchen, sollen zu ihrer
Profilseite umgeleitet werden.
-
Bei der Abmeldung soll ein Benutzer zur Loginseite umgeleitet werden.
-
Mit ungültigen Daten soll die Registrierung fehlschlagen.
Wir können und sollten zusätzliche Tests definieren, aber diese reichen vorerst aus.
Für unsere Anwendung definieren wir ein Plugin, 'Initialisieren' es, damit es bei
routeStartup() läuft. Das erlaubt es uns, das Bootstrapping in
einem OOP-Interface zu kapseln, was auch einen einfachen Weg bietet, um ein Callback zu
ermöglichen. Schauen wir uns erstmals die Grundlagen dieser Klasse an:
class Bugapp_Plugin_Initialize extends Zend_Controller_Plugin_Abstract
{
/**
* @var Zend_Config
*/
/**
* @var string Aktuelle Umgebung
*/
protected $_env;
/**
* @var Zend_Controller_Front
*/
protected $_front;
/**
* @var string Pfad zum Root der Anwendung
*/
protected $_root;
/**
* Constructor
*
* Umgebung, Root Pfad und Konfiguration initialisieren
*
* @param string $env
* @param string|null $root
* @return void
*/
public function __construct($env, $root = null)
{
$this->_setEnv($env);
if (null === $root) {
}
$this->_root = $root;
$this->initPhpConfig();
$this->_front = Zend_Controller_Front::getInstance();
}
/**
* Route beginnen
*
* @return void
*/
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$this->initDb();
$this->initHelpers();
$this->initView();
$this->initPlugins();
$this->initRoutes();
$this->initControllers();
}
// Die Definition von Methoden würde hier folgen...
}
Das erlaubt es uns einen Bootstrap-Callback wie folgt zu erstellen:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
public function appBootstrap()
{
$controller = $this->getFrontController();
$controller->registerPlugin(
new Bugapp_Plugin_Initialize('development')
);
}
public function setUp()
{
$this-> bootstrap = array($this, 'appBootstrap');
parent::setUp();
}
// ...
}
Sobald das fertig ist, können wir unsere Tests schreiben. Was ist jedoch mit den
Tests, die erfordern, dass der Benutzer angemeldet ist? Die einfache Lösung besteht darin,
dass unsere Anwendungslogik das macht... und ein bisschen trickst, indem die Methoden
resetRequest() und resetResponse()
verwendet werden, die es uns erlauben eine andere Anfrage abzusetzen.
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
// ...
public function loginUser($user, $password)
{
$this->request->setMethod('POST')
'username' => $user,
'password' => $password,
));
$this->dispatch('/user/login');
$this->assertRedirectTo('/user/view');
$this->resetRequest()
->resetResponse();
$this-> request-> setPost(array());
// ...
}
// ...
}
Jetzt schreiben wir Tests:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
// ...
public function testCallWithoutActionShouldPullFromIndexAction()
{
$this->dispatch('/user');
$this->assertController('user');
$this->assertAction('index');
}
public function testLoginFormShouldContainLoginAndRegistrationForms()
{
$this->dispatch('/user');
$this->assertQueryCount('form', 2);
}
public function testInvalidCredentialsShouldResultInRedisplayOfLoginForm()
{
$request = $this->getRequest();
$request->setMethod('POST')
'username' => 'bogus',
'password' => 'reallyReallyBogus',
));
$this->dispatch('/user/login');
$this->assertNotRedirect();
$this->assertQuery('form');
}
public function testValidLoginShouldRedirectToProfilePage()
{
$this->loginUser('foobar', 'foobar');
}
public function testAuthenticatedUserShouldHaveCustomizedProfilePage()
{
$this->loginUser('foobar', 'foobar');
$this->request->setMethod('GET');
$this->dispatch('/user/view');
$this->assertNotRedirect();
$this->assertQueryContentContains('h2', 'foobar');
}
public function
testAuthenticatedUsersShouldBeRedirectedToProfileWhenVisitingLogin()
{
$this->loginUser('foobar', 'foobar');
$this->request->setMethod('GET');
$this->dispatch('/user');
$this->assertRedirectTo('/user/view');
}
public function testUserShouldRedirectToLoginPageOnLogout()
{
$this->loginUser('foobar', 'foobar');
$this->request->setMethod('GET');
$this->dispatch('/user/logout');
$this->assertRedirectTo('/user');
}
public function testRegistrationShouldFailWithInvalidData()
{
'username' => 'This will not work',
'email' => 'this is an invalid email',
'password' => 'Th1s!s!nv@l1d',
'passwordVerification' => 'wrong!',
);
$request = $this->getRequest();
$request->setMethod('POST')
->setPost($data);
$this->dispatch('/user/register');
$this->assertNotRedirect();
$this->assertQuery('form .errors');
}
}
Es ist zu beachten, dass die Tests knapp sind und größtenteils nicht den
aktuellen Inhalt suchen. Stattdessen suchen sie nach Teilen in der Anfrage --
Anfrage Codes und Header sowie DOM-Knoten. Das erlaubt es schnell zu prüfen, dass die
Strukturen wie erwartet sind -- und verhindern, dass die Tests jedesmal scheitern,
wenn der Site neue Inhalte hinzugefügt werden.
Es ist auch zu beachten, dass wir die Struktur des Dokuments in unseren Tests verwenden.
Zum Beispiel suchen wir im letzten Test nach einer Form, die einen Knoten der Klasse
"errors" hat; das erlaubt es uns lediglich auf das Vorhandensein von
Form-Prüfungsfehlern zu testen und uns keine Sorgen darüber zu machen, warum spezielle
Fehler überhaupt geworfen werden.
Diese Anwendung könnte eine Datenbank verwenden. Wenn dem so ist,
muss man wahrscheinlich einige Grundlagen ändern um sicherzustellen, dass die Datenbank am
Anfang jedes Tests in einer unverfälschten, testbaren Konfiguration ist. PHPUnit bietet
bereits Funktionalität um das sicherzustellen; » Lesen Sie darüber in
der PHPUnit-Dokumentation nach. Wir empfehlen eine separate Datenbank für das
Testen zu verwenden statt der Produktionsdatenbank und entweder eine SQLite-Datei oder
eine Datenbank im Speicher zu verwenden, da beide Optionen sehr performant sind, keinen
separaten Server benötigen und die meisten SQL-Syntax verwenden
können.
|
|