4

Ich hatte nur set up a test framework for a new web application und merkte, dass ich eine der großen Fragen verpasste: "Wie mache ich Tests unabhängig voneinander?"Wie man Testbefestigungen für End-zu-End-Tests verwaltet?

Vor Jahren habe ich einige komplizierte Ant-Scripts eingerichtet, um vollständige Zyklen zum Löschen aller Datenbanktabellen, zum erneuten Erstellen des Schemas, zum Hinzufügen von Testdaten, zum Starten der Anwendung, zum Ausführen eines Tests und zum Beenden der Anwendung durchzuführen. Das war ein Schmerz zu halten und beschränkt uns auf nächtliche Tests aufgrund der Zeit, die es dauerte, um die gesamte Suite zu laufen. Es war es immer noch wert, aber ich frage mich, ob es einen leichteren Weg gibt.

Gibt es Alternativen zu diesem Ansatz? Das Hauptkriterium ist, dass jeder Test von keinem anderen Test in der Suite beeinflusst wird, unabhängig davon, ob der Test fehlgeschlagen oder erfolgreich war.

Antwort

0

Sicher ... schauen Sie sich den kontinuierlichen Integrationstest mit CruiseControl an. Sie können das zusammen mit NAnt und NUnit verwenden, um Ihre Tests durchzuführen, Ihre Umgebung zu zerstören und einzurichten und eine ganze Reihe anderer Dinge. Und dies kann jedes Mal ausgeführt werden, wenn jemand seinen Code in Ihrem Code-Repository eincheckt. Es ist der einzige Weg, um Code zu machen!

+0

Ich benutze bereits Hudson, Maven, JWebUnit und andere Tools. Die End-to-End-Tests werden von jedem erfolgreichen Build des Hauptprojekts ausgelöst. Die interessante Frage ist jedoch, wie ich meine Umgebung einrichten und abreißen kann, wenn sie tatsächlich in der Datenbank gehostet wird und in der Webanwendung zwischengespeichert wird, während ich meine Tests in einem separaten Prozess durchführe. –

1

Für den Datensatz: was ich jetzt mache, ist eine spezielle Ressource in der Anwendung konfiguriert, die die gesamte Datenbank zurückgesetzt (löscht alle Inhalte, fügt Standardbenutzer). Diese Ressource ist nur dann an eine URL gebunden, wenn die Anwendung im "Testmodus" gestartet wird. Da unsere Anwendung (meistens) RESTful ist, kann das Hinzufügen neuer Objekte von außen trotzdem erfolgen. Die Basisklasse unserer Tests ruft die Ressource während der Einrichtung eines Testfalls auf.

Ich mag die Lösung nicht wirklich, da sie Änderungen in der zu testenden Anwendung erfordert und ein potenzielles Sicherheitsrisiko darstellt. Tatsächlich teste ich die Flagge mindestens dreimal, bevor etwas gelöscht wird und wenn die Flagge gesetzt ist, gibt es einen großen, roten, blinkenden Kopf rechts auf der Titelseite (gute Entschuldigung, das Blink-Tag zum ersten Mal in einem Jahrzehnt zu verwenden). Aber es ist immer noch ein bisschen beängstigend.

0

Die Anpassung der Datenbank für Tests kann die Dinge beschleunigen. Ofc. Dies hängt von dem verwendeten db-Typ ab ... Durch db-Integrationstests können Sie Ihre Transaktionen einfach zurücksetzen. Durch andere Integrationstests können Sie die Datenzugriffsebene einfach ausspionieren.

durch funktionelle Tests, die Sie keine andere Wahl haben, aber Ihr System mit der realen Datenbank zu testen ...

Ich experimentiere derzeit mit Event-Sourcing, die eine Menge, indem sie Vorrichtungen helfen kann. Die kürzeste Beschreibung dieser Technik: Sie benötigen DDD (und auch CQRS wird empfohlen), speichern Domänenereignisse in Ihrem Ereignisspeicher, und danach können Sie den aktuellen Status erstellen, indem Sie die zugehörigen Ereignisse aus dem Ereignisspeicher abrufen und sie in a wiederholen Sequenz. Sie können viele verschiedene Cache-Datenbanken oben auf diesem Ereignisspeicher erstellen, die nur den aktuellen Status einer Komponente Ihres Dienstes enthalten, nichts mehr ... Der Synchronisationsprozess wird von Klassen ausgeführt, die Projektionen genannt werden, und wird automatisch sync oder async genannt indem Sie ein Ereignis speichern. Also, um eine Befestigung zu machen, müssen Sie nur Domain-Ereignisse speichern ...

Zum Beispiel können Sie so etwas wie dies durch eine sehr einfache REST-API schreiben:

Herstellung Aufnahme:

event.storage.clear(); 
every.cache.clear(); 

var credentials = { 
    name: "infje", 
    password: "oéö9péüöáé9oilusw" 
}; 
var resourceId = "swegretz34ze4wed"; 
var userDataSet = [ 
    { 
     id: 1, 
     type: "UserCreate", 
     resource: resourceId, 
     identificationFactors: credentials, 
     nick: "inf3rno", 
     birthDate: "1333.03.03.", 
     hobbies: ["wall climbing"] 
    }, 
    { 
     id: 2, 
     type: "UserUpdate", 
     resource: resourceId, 
     hobbies: ["base jumping", "knitting"] 
    } 
]; 

event.storage.persistAll(userDataSet); 
auth.cache.sync(event.storage); //a relational database with the user credentials 
users.cache.sync(event.storage); //a nosql document database with the user profile 

Funktionstest:

var response = http.get("https://my.test.api/users", credentials); 
assert(response).toEqual({ 
    size: 1, 
    items: [ 
     { 
      id: resourceId, 
      nick: "inf3rno", 
      hobbies: ["base jumping", "knitting"], 
      birthDate: "1333.03.03." 
     } 
    ] 
}); 

Anmerkung: Dies ist nur ein Proof of concept-Code, so Details wie Passwort-Verschlüsselung, REST Hypermedia-Einschränkung, automa c Aufruf von Projektionsklassen, etc ... sind jetzt nicht relevant.

Ofc. Dies ist immer noch langsames Ereignis langsamer als Ihr ursprünglicher Ansatz, aber Sie können diesen Teil nicht ändern, wenn Sie die echte Datenbank testen möchten, und mit Event Sourcing ist es mühelos, Test-Fixtures zu machen, Daten zu migrieren, die Struktur der Cache-Datenbanken zu ändern neue Version, etc ... Also es ist definitiv einen Versuch wert ...