Bei der Arbeit geht es in einem meiner Projekte hauptsächlich darum, Daten, die von einem externen Kunden übermittelt wurden, in einer Datenbank zu speichern. Es ist eine Java-Unternehmensanwendung, die JPA verwendet, und der größte Teil unserer Logik dreht sich um CRUD-Operationen.
Die meisten unserer Fehler betreffen JPA auf die eine oder andere Weise.
- Beispiel 1: Wenn Sie zweimal auf die Schaltfläche Speichern klicken, versucht JPA möglicherweise, dieselbe Entität ein zweites Mal in die Datenbank einzufügen, was zu einer Verletzung des Primärschlüssels führt.
- Beispiel 2: Sie rufen eine Entität aus der Datenbank ab, bearbeiten sie und versuchen, ihre Daten zu aktualisieren. JPA versucht möglicherweise, eine neue Instanz zu erstellen, anstatt die alte zu aktualisieren.
Oft muss die Lösung eine JPA-Anmerkung hinzufügen / entfernen / ändern. Ein anderes Mal hat es mit dem Ändern der DAO-Logik zu tun.
Ich kann nicht herausfinden, wie ich mit Unit-Tests und TDD Vertrauen in unseren Code gewinnen kann. Ich bin mir nicht sicher, ob es daran liegt, dass Unit-Tests und TDD schlecht zusammenpassen, oder ob ich mich dem Problem falsch nähere.
Unit-Tests scheinen nicht zu passen, da ich diese Probleme nur zur Laufzeit feststellen kann und sie auf einem App-Server bereitstellen muss, um die Probleme zu reproduzieren. In der Regel muss die Datenbank einbezogen werden, die meiner Meinung nach außerhalb der Definition eines Komponententests liegt: Hierbei handelt es sich um Integrationstests.
TDD scheint schlecht zu passen, da die Rückkopplungsschleife von deploy + test so langsam ist, dass ich sehr unproduktiv bin. Die Rückkopplungsschleife von deploy + test dauert mehr als 3 Minuten. Dies gilt nur, wenn ich die Tests speziell für den Code durchführe, den ich schreibe. Das Ausführen aller Integrationstests dauert mehr als 30 Minuten.
Es gibt Code außerhalb dieser Form und ich teste ihn immer, wann immer ich kann. Aber die Mehrheit unserer Bugs und die größten Zeitverluste betreffen immer JPA oder die Datenbank.
Es gibt eine andere Frage, die ähnlich ist , aber wenn ich den Rat befolgen würde, würde ich den instabilsten Teil meines Codes (den JPA) packen und alles außer ihm testen. Im Zusammenhang mit meiner Frage würde ich in der gleichen schlechten Situation sein. Was ist der nächste Schritt nach dem Einwickeln der JPA? IMO ist diese Frage (vielleicht) ein Schritt, um meine Frage zu beantworten, aber keine Antwort darauf.
quelle
unit testing != TDD
)Antworten:
Eine Möglichkeit besteht darin, eine speicherinterne Testdatenbank wie H2 zu verwenden . Es ist in der Regel etwa 10-mal schneller als eine standardmäßige festplattenverwendende Datenbank und weist geringere Start- / Herunterfahrzeiten auf.
Ob dies hilft, hängt weitgehend davon ab, ob die JPA-Probleme, die Sie haben, allgemein genug sind, dass sie in einer anderen Datenbank immer noch fehlschlagen. Es macht nicht viel Sinn, Tests schneller durchzuführen, wenn der Großteil der Probleme übersehen wird.
Aber wenn Sie 10 Läufe mit H2 für jeden mit dem vollen System machen können, könnte es sich auszahlen.
quelle
Datenbanken können sehr einfach zu Unit-Tests werden - Sie benötigen gespeicherte Prozeduren und Transaktionen.
Dies ist, was Microsoft über das Testen von Datenbankeinheiten sagt . Sie können auch Komponententests für eine Datenbank ausführen, Ihre Tests in Java oder C # schreiben, indem Sie eine DB-Verbindung einrichten, eine Transaktion starten, alle Daten, die Sie für den Test verwenden möchten, in die DB schreiben, die Tests ausführen und dann ein Rollback durchführen. Keine Beschädigung der Datenbank, wenn Sie eine verwenden, für die Sie auch bereitgestellt haben, und Sie erhalten vollständig isolierte Tests.
Hoffe, dies kann Ihnen einen Einblick geben, wie Sie dies in Ihrem Rahmen tun können.
quelle
Andere Leute haben mit "Mock out your DB!" Geantwortet. - aber was nützt es, Ihre DB-Ebene zu verspotten, wenn Sie tatsächlich testen müssen, wie sie mit Ihrem Code interagiert?
Was Sie suchen, sind Integrationstests und / oder automatisierte UI-Tests. Sie haben erwähnt, dass das Problem auftritt, wenn:
Die einzige Möglichkeit, dies zu testen, besteht darin, einen automatisierten UI-Test zu schreiben, bei dem Sie zweimal auf die Schaltfläche klicken. Vielleicht sollten Sie Selen ausprobieren.
Sie werden wahrscheinlich auch einen Unit-Test-DB benötigen und für Ihre Tests darauf hinweisen. Ein Schmerz, den es zu bewahren gilt, aber willkommen bei TDD in der realen Welt.
quelle
In dem Beispiel, das Sie in Ihrer Frage angegeben haben, können Sie sich mit Unit Test / TDD nicht in die Situation begeben, dass Sie zweimal auf die Schaltfläche klicken, um auf einfache Weise einen Fehler zu verursachen. Was Sie jedoch testen können, ist, dass der Code, der beim Klicken auf die Schaltfläche aufgerufen wird, eine Ausnahme von der Persistenzschicht darstellt, die Sie entsprechend behandeln (indem Sie die Persistenzschicht verspotten oder eine speicherinterne Datenbank als verwenden) wurde in anderen Antworten vorgeschlagen) - entweder durch erneutes Werfen oder Anzeigen eines Fehlers oder was auch immer.
Sie haben Recht, dass TDD zusammenbrechen kann, wenn Sie Tests durchführen müssen, die nicht für einen Komponententest geeignet sind (z. B. Integrations- / Systemtests) Tot?" Debatten zwischen Kent Beck, Martin Fowler und David Heinemeier Hansson: http://martinfowler.com/articles/is-tdd-dead/
quelle