
Wie wir uns mit Codeception und Drupal angefreundet haben
Wir machen viel Drupal-Entwicklung. Wir beschäftigen uns auch viel mit automatisierten Tests. Deshalb haben wir beschlossen, die Standardfunktionalität von Codeception mit einigen neuen Modulen für Drupal zu ergänzen. Dies hilft uns enorm in unserer täglichen Arbeit.
Wie in unserem vorherigen Artikel werden alle unten aufgeführten Beispiele auf einem Projekt basieren, das auf docker-console basiert, weshalb wir allen empfehlen, zuerst die vorherigen Artikel zu lesen, wenn Sie dies noch nicht getan haben. Wenn Sie bereits Ihr Codeception-Projekt haben und es nur leicht modifizieren möchten, damit es besser mit Drupal funktioniert, ist dieser Artikel ebenfalls für Sie geeignet.
Als wir das erste Mal versucht haben, die Funktionalität unserer Tests zu erweitern, hatten wir einige Anforderungen, die bestehende Module nicht erfüllten, weshalb die meisten der unten aufgeführten Lösungen von uns erstellt wurden. Sie basieren alle auf anderen, zuvor verfügbaren Lösungen, aber wir hoffen, dass Ihnen die Art und Weise gefällt, wie Droptica sie erweitert und zu einem kohärenten Ganzen gemacht hat, das im Handumdrehen in Ihrer Codeception-Projektkonfiguration verfügbar ist.
codeception-drupal-bootstrap
Das erste Modul, das in diesem Artikel vorgestellt wird, ist codeception-drupal-bootstrap, welches unter https://github.com/droptica/codeception-drupal-bootstrap gefunden werden kann
Dies ist ein Fork eines Moduls: https://github.com/Chapabu/codeception-module-drupal (Es wurde von uns modifiziert, da es ursprünglich nicht möglich war, es in mehreren Suiten gleichzeitig zu verwenden, und außerdem keine Version für Drupal 8 existierte). Es ermöglicht die Nutzung von Drupal-Funktionen in Tests und anderen Codeception-Modulen.
Konfiguration
Um dieses Modul verwenden zu können, müssen Sie es in einer yaml-Datei für eine gegebene Suite konfigurieren, z.B. unit.suite.yml.
Aktivierung in der Test-Suite-Konfiguration für Drupal 7.
- \Codeception\Module\Drupal7\Drupal7:
root: '/app/app'
relative: no
Freischaltung der Konfiguration für Drupal 8:
- \Codeception\Module\Drupal8\Drupal8:
root: '/app/app/'
env: 'prod'
relative: no
site_dir: 'default'
Beispiel
Für jeden, der mit Drupal arbeitet, ist der Nutzen offensichtlich. In einem kürzlich erschienenen Artikel haben wir Ihnen ein Beispiel gezeigt, wie Sie überprüfen können, ob ein bestimmtes Modul mithilfe von Drupal-Befehlen aktiviert ist. In diesem Blog-Beitrag werden wir Ihnen einen weiteren hilfreichen Test vorstellen, um zu überprüfen, ob Funktionen Ihrer Website nicht überschrieben werden. Wenn Sie möchten, dass dieses Beispiel mit unserem Projekt funktioniert, müssen Sie das Features-Modul zu Ihrem Projekt hinzufügen und einige Features exportieren. Sie können auch Dateien aus dem Codeception-Drupal-Branch abrufen, wo wir das bereits für Sie getan haben.
<?php
class ExampleUnitTest extends \Codeception\Test\Unit
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
/** TESTS */
public function testFeaturesDefault() {
module_load_include('inc', 'features', 'features.export');
// Lade Informationen zum Feature.
$features[] = 'test';
$features_states = features_get_component_states($features, FALSE, TRUE);
foreach ($features_states as $feature_name => $feature_state) {
$overridden_features = array_filter($feature_state, function($item) {
return $item != FEATURES_DEFAULT;
});
$this->assertEquals(TRUE, empty($overridden_features), 'Feature ' . $feature_name . ' is overridden.');
}
}
}
codeception-drupal-users
Ein weiteres Modul, das in diesem Artikel vorgestellt wird, ist codeception-drupal-users, das bei https://github.com/droptica/codeception-drupal-users zu finden ist. Dies ist ein modifiziertes drupal-user-registry Modul – https://github.com/ixis/codeception-module-drupal-user-registry, das für die automatische Erstellung von Testbenutzern zur Ausführungszeit der Testsuite verwendet wird. Mit dem Modul können Sie schnell Testbenutzer mit bestimmten Rollen erstellen und verwenden. Standardmäßig werden alle Testbenutzer nach Abschluss aller Tests einer gegebenen Suite entfernt (es sei denn, es ist anders konfiguriert).
Das ursprüngliche Modul nutzt drush zur Erstellung von Benutzern. Mit dieser Methode war es nicht möglich, benutzerdefinierte Profilfelder auszufüllen. Anstelle von drush verwendet unser Modul dafür Drupal-Funktionen. Dank dessen ist es möglich, sowohl Standardbenutzerdetails als auch benutzerdefinierte Profilfelder auszufüllen.
Konfiguration
Die Konfiguration ist einfach und erfolgt vollständig in einer Konfigurationsdatei einer gegebenen Suite. Es ist jedoch notwendig, einige Dinge zu beachten. Zunächst einmal müssen Sie, damit dieses Modul funktioniert, das codeception-drupal-bootstrap Modul in einer gegebenen Suite aktivieren. Zusätzlich sollte das Entity API (https://www.drupal.org/project/entity) Modul ebenfalls im Projekt aktiviert sein.
Beispiele
Es ist immer am besten, Konfigurationen anhand eines Beispiels zu erläutern, weshalb wir zwei zusätzliche Felder und drei neue Rollen für Benutzer hinzugefügt haben. (Wenn Sie nicht wissen, wie man das in Ihrem Projekt macht, können Sie die Änderungen aus dem docker-drupal-Branch übernehmen). Nach Aktivierung des Moduls müssen wir angeben, welche Arten von Benutzern wir erstellen möchten. Um dies zu tun, müssen wir zuerst die Rollen unserer Benutzer deklarieren (das können Sie auf die Weise tun, wie es im unten dargestellten Beispiel ist, oder benutzerdefinierte Rollen deklarieren, bei denen der Benutzer mehrere im System definierte Rollen hat). Nach der Beschreibung der Rollen im Projekt spezifizieren wir auch die Daten, die zum Ausfüllen unserer neuen Felder verwendet werden (ich könnte sie für jeden Benutzer separat angeben). Danach können wir damit fortfahren, die genauen Benutzer zu spezifizieren, die wir möchten, dass codeception vor der Ausführung unserer Tests erstellt. Am Ende sollten wir einen „true“-Wert in „create“ haben, wenn wir möchten, dass unsere Benutzer vor der Ausführung einer gegebenen Suite erstellt werden. Gleiches gilt für „delete“ – das löscht unsere Benutzer nach der Ausführung einer Testsuite. In meinem Fall werden die Benutzer nicht gelöscht, um im System überprüfen zu können, ob sie wirklich erstellt wurden. Wenn wir den Test zweimal ausführen, werden die neuen Benutzer nicht dupliziert, wir erhalten eine Fehlermeldung, dass der Benutzer bereits im System existiert.
- ManageUsers:
defaultPass: "123"
#Verfügbare Rollen:
#1 anonymer Benutzer
#2 authentifizierter Benutzer
#3 Administrator
#4 Redakteur
#5 Benutzer
#6 niemand
roles_admin: &roles_admin
2: "authentifizierter Benutzer"
3: Administrator
roles_editor: &roles_editor
2: "authentifizierter Benutzer"
4: Redakteur
roles_user: &roles_user
2: "authentifizierter Benutzer"
5: Benutzer
roles_nodoby: &roles_nodoby
2: "authentifizierter Benutzer"
6: niemand
custom_fields: &custom_fields
field_inne_pole: 'Vorname'
field_custom_field: 'key1'
users:
admin_user:
name: admin_user
email: [email protected]
roles: *roles_admin
custom_fields:
<<: *custom_fields
editor_user:
name: editor_user
email: [email protected]
roles: *roles_editor
custom_fields:
field_inne_pole: 'Vorname2'
field_custom_field: 'key2'
user_user:
name: user_user
email: [email protected]
roles: *roles_user
custom_fields:
<<: *custom_fields
nodoby_user:
name: nodoby_user
email: [email protected]
roles: *roles_nodoby
custom_fields:
<<: *custom_fields
create: true # Ob alle definierten Testbenutzer zu Beginn der Suite erstellt werden sollen.
delete: false # Ob alle definierten Testbenutzer am Ende der Suite gelöscht werden sollen.
Für Drupal 8 sieht die Konfiguration des Moduls fast identisch aus. Der einzige Unterschied besteht darin, das Modul in der Konfiguration mithilfe von:
- \Codeception\Module\Drupal8\ManageUsers:
anstelle von ManageUsers zu aktivieren.
Natürlich können Sie die Funktionen dieses Moduls beim Schreiben der Testfälle verwenden. Zu den nützlichsten gehören diejenigen, die es uns ermöglichen, auf einen Testbenutzer oder eine Gruppe von Benutzern zu verweisen:
- getAllTestUsers()
- getTestUsersByRoles($roles = array(), $return_one_user = FALSE)
- getTestUserByName($username)
codeception-drupal-content-types
Ein weiteres unserer Drupal-Module ist codeception-drupal-content-types, das unter https://github.com/droptica/codeception-drupal-content-types zu finden ist. Es basiert auf: https://github.com/ixis/codeception-drupal-content-types und wird zum Erstellen und Entfernen von Testknoten verwendet.
Konfiguration
Um zu aktivieren:
- DrupalContentTypeRegistry:
contentTypesAutoDump: true
contentTypesAutoDumpFile: "contentTypes.yml"
contentTypesFile: "contentTypes.yml"
customFieldsFile: "contentTypesOverrides.yml"
Nach diesem Schritt sollte die Ausführung der Tests die Datei contentTypes.yml generieren, die die Struktur der im Projekt verfügbaren Knoten auflistet. Ein Beispiel für eine solche Datei ist im Bild unten zu sehen.
Wenn eine der Inhaltstypen Felder wie Feldsammlung oder andere enthält, die verschachtelte Felder (z.B. Standort) umfassen, wird die Datei contentTypes.yml nur die Hauptfelder enthalten, ohne die verschachtelten. Um die verschachtelten Felder zu füllen, wie in einer Feldsammlung, müssen Sie sie in der Datei contentTypesOverrides.yml aufnehmen. Alle, die das Projekt mit Docker-Console-Unit-Tests initiiert oder den Code aus unserem Beispiel-Repository zusammengeführt haben, sollten diese Datei bereits in ihren Projekten haben. Sie sollte Tipps enthalten, wie Sie die gegebene Konfiguration überschreiben und wie die unten dargestellte aussehen.
Beispiel
In unserem Beispiel zeigen wir Ihnen, wie Sie mit diesem Modul einen Knoten vom Typ Artikel erstellen.
class NewNodeTestCest
{
/**
* @var string
* article_title
*/
private $article_title;
/**
* @var string
* article_body
*/
private $article_body;
/**
* @var string
* article_tags
*/
private $article_tags;
function __construct() {
$this->article_title = 'Testartikel';
$this->article_body = 'Testartikelinhalt';
$this->article_tags = 'Testartikel Etikett';
}
public function _before(AcceptanceTester $I) {
}
public function _after(AcceptanceTester $I) {
}
/** TESTS */
/**
* @param \AcceptanceTester $I
*
*/
public function newArticle(AcceptanceTester $I, UserSteps $U) {
$I->wantTo('Testen - Ich kann mich als Admin einloggen und einen Artikel hinzufügen und löschen');
$I->amOnPage('/');
$user = $I->getTestUserByName('admin_user');
$U->login($user->name, $user->pass);
$fields_values = array(
'title' => $this->article_title,
'body' => $this->article_body,
'field_tags' => $this->article_tags
);
$I->createNode($I, 'article', $fields_values, NULL, FALSE);
$nid = $I->grabLastCreatedNid($I);
$I->deleteNodeFromStorage($nid);
$I->amOnPage('/user/logout');
}
}
codeception-drupal-content-types + NodeSteps
Um unsere Arbeit mit dem Modul noch einfacher zu gestalten, haben wir einige zusätzliche unterstützende Funktionen hinzugefügt, die es uns ermöglichen, festzulegen, welchen Benutzer wir verwenden möchten, um einen bestimmten Knoten hinzuzufügen oder zu entfernen. Die NodeSteps-Datei enthält Funktionen, die uns als gegebener Benutzer anmelden, bevor wir einen Knoten hinzufügen/entfernen. Ein Beispiel für die Verwendung dieser Funktionen finden Sie weiter unten, hier fügen wir einen „page“-Knoten als admin_user hinzu.
<?php
use Step\Acceptance\UserSteps;
use Step\Acceptance\NodeSteps;
class NewNodeAsUserTestCest
{
/**
* @var string
* page_title
*/
private $page_title;
/**
* @var string
* page_body
*/
private $page_body;
function __construct() {
$this->page_title = 'Testseite';
$this->page_body = 'Testseiteninhalt';
}
public function _before(AcceptanceTester $I) {
}
public function _after(AcceptanceTester $I) {
}
/** TESTS */
/**
* @param \AcceptanceTester $I
*
*/
public function newPage(AcceptanceTester $I, UserSteps $U, NodeSteps $N) {
$I->wantTo('Testen - Ich kann als Admin eine Seite hinzufügen und löschen');
$I->amOnPage('/');
$fields_values = array(
'title' => $this->page_title,
'body' => $this->page_body
);
$nid = $N->createNewNodeAsUser('admin_user', 'article', $fields_values);
$N->deleteNodeAsUser('admin_user', $nid);
}
}
codeception-drupal-storage
Das letzte Modul, das im heutigen Artikel vorgestellt wird, ist codeception-drupal-storage, das unter https://github.com/droptica/codeception-drupal-storage zu finden ist
Es wird verwendet, um Variablen und die von uns erstellten Testknoten global in der gesamten Testsuite zu speichern, bis wir die Ausführung der Tests einer gegebenen Suite abgeschlossen haben.
In diesem Modul können Sie die folgenden Methoden nutzen:
- setVariableToStorage($name, $value)
- getVariablesFromStorage($names = array())
- getVariableFromStorage($name)
- deleteVariableFromStorage($name)
- appendNodeToStorage($nid)
- getAllNodesFromStorage()
- getNodeFromStorage($nid)
- deleteNodeFromStorage($nid)
Konfiguration
Das Modul erfordert keine komplizierte Konfiguration, es genügt, es zu aktivieren, indem Sie die folgende Zeile zur Konfigurationsdatei einer gegebenen Suite hinzufügen.
- SuiteVariablesStorage
Beispiel
Wie in jedem Fall ist es immer am besten zu sehen, was das Modul mit einem Beispiel machen kann. In unserem Beispiel, das unten dargestellt ist, haben wir das Erstellen eines Knotens, das Überprüfen, ob er den richtigen Inhalt hat, und das Entfernen desselben in drei separate Tests aufgeteilt, was es uns ermöglicht hat, zu zeigen, wie wir einen bestimmten Wert von einem Test zum anderen verschieben können. Natürlich müssen die Tests nicht in einer einzelnen Datei sein; es ist jedoch entscheidend, dass sie alle zu einer einzelnen Suite gehören, denn nachdem die Suite ausgeführt wurde, werden alle während der Tests erstellten Werte entfernt. (Zusätzlich können Sie einen bestimmten Wert jederzeit mit der entsprechenden Methode entfernen.)
<?php
use Step\Acceptance\UserSteps;
use Step\Acceptance\NodeSteps;
class VariablesStorageTestCest
{
/**
* @var string
* page_title
*/
private $page_title;
/**
* @var string
* page_body
*/
private $page_body;
function __construct() {
$this->page_title = 'Testseite';
$this->page_body = 'Testseiteninhalt';
}
public function _before(AcceptanceTester $I) {
}
public function _after(AcceptanceTester $I) {
}
/** TESTS */
/**
* @param \AcceptanceTester $I
*
*/
public function newPage(AcceptanceTester $I, UserSteps $U, NodeSteps $N) {
$I->wantTo('Testen - Ich kann mich als Admin einloggen und einen Artikel hinzufügen');
$I->amOnPage('/');
$fields_values = array(
'title' => $this->page_title,
'body' => $this->page_body
);
$nid = $N->createNewNodeAsUser('admin_user', 'article', $fields_values);
$I->setVariableToStorage('page_nid', $nid);
}
/**
* @param \AcceptanceTester $I
*
*/
public function seeTextOnPage(AcceptanceTester $I) {
$I->wantTo('Testen - Ich kann den Seitentitel und den Text auf der Testseite sehen');
$nid = $I-> getVariableFromStorage('page_nid');
$I->amOnPage('/node/'.$nid);
$I->canSee($this->page_title);
$I->canSee($this->page_body);
}
/**
* @param \AcceptanceTester $I
*
*/
public function deletePage(AcceptanceTester $I, UserSteps $U, NodeSteps $N) {
$I->wantTo('Testen - Ich kann die Testseite löschen');
$nid = $I-> getVariableFromStorage('page_nid');
$N->deleteNodeAsUser('admin_user', $nid);
}
}
Projektdaten
Sie können die in diesem Artikel beschriebenen Beispiele aus dem Projekt-Repository herunterladen und den Branch auf codeception-drupal wechseln.
Projekt-Repository:
https://github.com/DropticaExamples/docker-console-project-example
Datenbank-Dump:
https://www.dropbox.com/s/r0o3u9gjp3dccd4/database.sql.tar.gz?dl=0
Projektdaten:
https://www.dropbox.com/s/hl506wciwj60fds/files.tar.gz?dl=0
Hilfsfunktionen:
Neben der Hinzufügung von Modulen werden wir spezielle Funktionen zu jedem Projekt hinzufügen, die es uns ermöglichen, die Website besser zu testen. Wir haben diese Funktionen bereits demonstriert, als wir die NodeSteps zusammen mit dem codeception-drupal-content-types Modul vorgestellt haben. (Dies sind einige spezielle Klassen, mehr darüber erfahren Sie hier: http://codeception.com/docs/06-ReusingTestCode#StepObjects
Wir werden sie auch in einem unserer kommenden Artikel ausführlich besprechen.) Sie können auch Hilfsfunktionen in Dateien schreiben, die zu jeder Testsuite hinzugefügt wurden, zum Beispiel im „Acceptance“-Datei im _support/Helper oder erstellen eine neue Datei und schreiben die Hilfsfunktionen dort, genau wie in unserem Beispiel mit der DrupalHelper-Datei, die im gleichen Ordner gefunden wird. Unabhängig davon, welche Variante Sie wählen, sollten Sie daran denken, den Zugang zu diesen Funktionen in einer gegebenen Suite in einer yaml-Datei freizuschalten, wie im unten aufgeführten Beispiel.
Wenn Sie dies nicht tun, müssen Sie es in jeder Datei importieren, in der Sie eine bestimmte Funktion verwenden möchten, indem Sie z.B.
use Step\Acceptance\UserSteps;
use Step\Acceptance\NodeSteps;
Fazit
Wir hoffen, dass Ihnen unsere kleinen Verbesserungen für Drupal gefallen. Wenn Sie eine Lösung verwenden, die für Drupal gedacht ist und wir darüber noch nichts geschrieben haben, lassen Sie es uns wissen – wir werden unsere Konfiguration gerne mit neuen und coolen Modulen erweitern. Wenn Sie gerade Ihre Abenteuer mit Codeception beginnen, ermutigen wir Sie, zu experimentieren und so viele Tests wie möglich selbst zu schreiben, denn wie Sie wahrscheinlich bereits wissen, „Übung macht den Meister“. Zusätzlich ermutigen wir alle, unseren Blog weiterhin zu besuchen – Sie können sicher sein, dass wir in Zukunft mehr über dieses Tool schreiben werden.