Nikolas Martens hat am Wochenende auf der FrOSCon in seinem Vortrag „The Pyramid is a lie“ vorgestellt wie Tests richtig laufen sollten. Ich möchte nun hier nochmal die Erkenntnisse aus dem Talk darstellen. Die Slides von Nikolas findet man hier.
Wer kennt sie nicht – Die Pyramide. In beinahe jedem Testing-Worshop oder -Votrag kommt sie vor. Decke beinahe den ganzen Code mit vielen, günstige und schnellen Unit-Tests ab, jedoch nur wenige mit langsamen UI-Tests. Dazwischen käme eigentlich noch der Teil der Service-Tests, wird aber meistens vernachlässigt. Hält man sich die Vor- und Nachteile von Unit-Test und UI-Tests vor Augen so wird man schnell feststellen, dass diese beinahe komplementär sind. Der Nachteil des Einen ist der Vorteil des Anderen. Die genaue Abbildung von Akzeptanz-Kriterien in UI-Tests wird zum Nachteil, wenn man viele solcher Tests laufen lässt. Viele laufen lassen, kann man bei Unit-Tests, doch meist deckt man damit jeweils immer einen viel zu kleinen Teil ab. Diese Tests lassen sich so dann selten an das Business kommunizieren.
Wie Nikolas am Wochenende ging auch schon Everzet in seinem Blog-Post darauf ein, dass wir mit der gewohnten Pyramide meist den wichtigsten Teil der Applikation vergessen:
Domain Core – Service-Layer
Diese beinhaltet die eigentliche Business-Logik, bildet also auch das Domain-Model ab. Wir können zwar dessen Komponenten mit Unit-Test abdecken, doch die komplette Funktionalität lässt sich nur mit „etwas größeren“ Tests sicher stellen.
Bedenkt man noch, dass durch die featureweise Entwicklung viele Schnittmengen zwischen verschiedenen Features und den damit verbundenen Tests entstehen, führt das einen schnell zu dem Schluss: „Warum die Tests nicht im Service Layer beginnen?“. Dabei kann man die Tests dann gleich in einer business-verständlichen Form umsetzen – der sogenannten Ubiquitous Language.
Business Need: Edit users In order to have customer support an Admin want's to edit a user. Scenario: Edit user data on behalf of a customer Given a user with email "maximilian.berghoff@mayflower.de" When i change the username to "ElectricMaxxx" Then the user profile should display the username "ElectricMaxxx"
Das Szenario ist in der sogenannten Gherkin Notation geschrieben und wird hier mit Behat umgesetzt. Das heißt man schreibt für deren Ausführung ein Kontext-Objekt:
user = $this->repository->getUserByEmail($email); } /** * @Then i change the username to :username */ public function iChangeTheUserNameTo($userName) { $this->user->setUserName($userName); $this->repository->persist($this->user); } /** * @Then the user profile should display the username :userName */ public function theUserProfileShouldDisplayTheUsername($userName) { $userProfile = $this->repository->getUserByEmail($this->user->getEmail); $this->assertEquals($userProfile->getUserName, $userName); } }
Woher jetzt das Repository und die Asserts kommen sei mal dahin gestellt. Beispielsweise könnte das Repository hier einfach nur ein LocalCache oder ein Mock sein.
Was wäre wenn wir jetzt den selben Test für das UI-Testing benutzen würden? Dann würden wir einfach ein anderes Kontext-Objekt erstellen:
Kurze Unterbrechung
DAS IST DEIN ALLTAG?
Keine Sorge – Hilfe ist nah! Melde Dich unverbindlich bei uns und wir schauen uns gemeinsam an, ob und wie wir Dich unterstützen können.
Schreibe einen Kommentar