German (Deutsch) translation by Wei Zhang (you can also view the original English article)



Wenn Sie fragen: "Was ist Yii?" Sehen Sie sich mein früheres Tutorial, Einführung in das Yii-Framework, an, das die Vorteile von Yii beschreibt und einen Überblick darüber enthält, was in Yii 2.0, veröffentlicht im Oktober 2014, neu ist.
In dieser Programming With Yii2-Serie leite ich die Leser mit dem Yii2 Framework für PHP. In diesem Tutorial erkläre ich das automatisierte Testen mithilfe von Codeception, das in das Yii2-Entwicklungsframework integriert ist.
Zugegeben, meine Erfahrung beim Schreiben von Tests mit meinem Code ist knapp. Ich war oft Teil von Einzelprojekten oder kleinen Projekten mit begrenzten Ressourcen. Während meiner Zeit bei Microsoft hatten wir verschiedene Testteams, die das taten. Aber ehrlich gesagt, das ist wahrscheinlich auch für dich typisch, oder? Programmierer schreiben gerne, sie schreiben keine Tests - zumindest Programmierer der alten Schule nicht.
Codeception ist eine innovative Bibliothek, die buchstäblich das Schreiben von Tests zum Kinderspiel macht. Und ich würde sagen, dass sie zu einem vernünftigen Grad erfolgreich waren. Als ich meinen Zeh in das Wasser von "Lake Codeception" tauchte, war es meistens einfach und lustig. Als ich jedoch tiefer ging, stieß ich auf Konfigurationsprobleme mit Yii und den spezifischen Modulen, die in dieser Serie verwendet wurden. Es gab definitiv Herausforderungen. Insgesamt bin ich beeindruckt und sehe den Vorteil, mehr zu lernen.
Einfach gesagt, Codeception und seine Integration mit Yii lassen mich mehr Tests schreiben, eine Premiere für mich. Ich vermute, du wirst eine ähnliche Erfahrung machen.
Eine kleine Erinnerung, bevor wir anfangen, nehme ich an den Kommentarthreads unten teil. Ich bin besonders interessiert, wenn Sie zusätzliche Gedanken haben oder Themen für zukünftige Tutorials vorschlagen möchten. Wenn Sie eine Frage oder einen Themenvorschlag haben, bitte posten Sie unten. Sie können mich auch auf Twitter @reifman direkt erreichen.
Fertig machen
Codeception installieren
Um mich zu führen, habe ich Yii Testing Environment Setup Dokumentation verwendet. Ich begann mit einer globalen Installation von Codeception, damit ich sie aus jedem Projekt verwenden konnte.
$ composer global require "codeception/codeception=2.1.*" Changed current directory to /Users/Jeff/.composer ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing symfony/yaml (v3.1.1) Loading from cache ... codeception/codeception suggests installing symfony/phpunit-bridge (For phpunit-bridge support) Writing lock file Generating autoload files
Sie müssen auch codeception/specify
benötigen:
$ composer global require "codeception/specify=*" Changed current directory to /Users/Jeff/.composer ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) composer require "codeception/verify=*" - Installing codeception/specify (0.4.3) Downloading: 100% Writing lock file Generating autoload files
Und codeception/verify
:
$ composer require "codeception/verify=*" ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing codeception/verify (0.3.0) Downloading: 100% Writing lock file Generating autoload files
Als nächstes hilft es, einen Alias für codecept
unter Verwendung Ihres globalen Composer-Verzeichnisses einzurichten:
$ composer global status Changed current directory to /Users/Jeff/.composer No local changes
Dies setzt den Alias:
$ alias codecept="/Users/Jeff/.composer/vendor/bin/codecept"
Yii erfordert auch, dass Sie Faker installieren, der gefälschte Testdaten für Ihre Anwendung generiert:
$ composer require --dev yiisoft/yii2-faker:* ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files
Einrichten der Codeception mit Ihrer Anwendung
codecept bootstrap
initialisiert die Codeception für Ihre Yii-Anwendung und erstellt eine Vielzahl von Konfigurationsdateien zum Erstellen und Ausführen von Tests für Ihre Anwendung. Wir verwenden die Hello-Anwendung aus dieser Serie für dieses Tutorial. Sehen Sie sich den GitHub-Link auf dieser Seite an, um den Code zu erhalten.
$ codecept bootstrap Initializing Codeception in /Users/Jeff/Sites/hello File codeception.yml created <- global configuration tests/unit created <- unit tests tests/unit.suite.yml written <- unit tests suite configuration tests/functional created <- functional tests tests/functional.suite.yml written <- functional tests suite configuration tests/acceptance created <- acceptance tests tests/acceptance.suite.yml written <- acceptance tests suite configuration tests/_output was added to .gitignore --- tests/_bootstrap.php written <- global bootstrap file Building initial Tester classes Building Actor classes for suites: acceptance, functional, unit -> AcceptanceTesterActions.php generated successfully. 0 methods added \AcceptanceTester includes modules: PhpBrowser, \Helper\Acceptance AcceptanceTester.php created. -> FunctionalTesterActions.php generated successfully. 0 methods added \FunctionalTester includes modules: \Helper\Functional FunctionalTester.php created. -> UnitTesterActions.php generated successfully. 0 methods added \UnitTester includes modules: Asserts, \Helper\Unit UnitTester.php created. Bootstrap is done. Check out /Users/Jeff/Sites/hello/tests directory
Aus irgendeinem Grund endete ich auch mit doppelten Testverzeichnissen in Hallo / Tests; nur hello / tests / functional, hallo / tests / acceptance und hello / tests / unit wurden gelöscht. Alle Tests leben in hello/tests/codeception/*.
Die verschiedenen Arten von Tests
Die Codeception konzentriert sich auf drei Arten von Tests:
- Das Testen von Einheiten überprüft, ob bestimmte Einheiten funktionieren, z. B. ein umfassender Test aller Methoden Ihres Modells.
- Funktionstests verifizieren gängige Anwendungsszenarien so, als ob sie von einem Benutzer ausgeführt würden, aber mithilfe der Webbrowser-Emulation.
- Akzeptanztests sind identisch mit Funktionstests, führen die Tests jedoch über einen Webbrowser durch.
Und es unterstützt drei verschiedene Arten von Testformaten für Ihren Testcode:
- Cept: Es ist die einfachste Testdatei für ein einzelnes Szenario
- Cest: ein objektorientiertes Format zum Ausführen mehrerer Tests innerhalb einer einzigen Datei
- Test: Tests geschrieben auf PHPUnit, einem PHP-Testframework
Beginnen wir mit einem Beispiel für Akzeptanztests im ceptformat:
Abnahmeprüfung
Wir werden zuerst das Testbeispiel für die Begrüßung
von Codeception verwenden.
$ codecept generate:cept acceptance Welcome Test was created in /Users/Jeff/Sites/hello/tests/acceptance/WelcomeCept.php
Dies erzeugt tests/acceptance/WelcomeCept.php
, die wir unten bearbeiten werden.
Da Abnahmetests den Browser erfordern, müssen wir /tests/acceptance.suite.yml in unserem Projekt bearbeiten, um unsere Entwicklungs-URL http://localhost:8888/hello bereitzustellen:
# Codeception Test Suite Configuration # # Suite for acceptance tests. # Perform tests in browser using the WebDriver or PhpBrowser. # If you need both WebDriver and PHPBrowser tests - create a separate suite. class_name: AcceptanceTester modules: enabled: - PhpBrowser: url: http://localhost:8888/hello/ - \Helper\Acceptance
Jetzt können wir den ersten Test in tests/acceptance/WelcomeCept.php ändern. Ich schreibe einen Test, der die Titelseite lädt, um sicherzustellen, dass es wie erwartet funktioniert.
Codeception-Tests haben das Konzept eines Actors, in diesem Fall $I= new AcceptanceTester()
.
So beschreibt es Akteure in der Codeception-Dokumentation:
Wir haben einen UnitTester, der Funktionen ausführt und den Code testet. Wir haben auch einen FunctionalTester, einen qualifizierten Tester, der die Anwendung als Ganzes mit der Kenntnis seiner Interna testet. Und ein AcceptanceTester, ein Benutzer, der mit unserer Anwendung über eine von uns bereitgestellte Schnittstelle arbeitet.
Sie können Ihre Tests mit Code kommentieren, z. B. $I->wantTo('perform a certain test')
oder 'ensure that the frontpage works'.
In meinem Test möchte ich $I->see
Text für 'Congratulations!'
und 'Yii-powered'
:
<?php $I = new AcceptanceTester($scenario); $I->wantTo('ensure that frontpage works'); $I->amOnPage('/'); $I->see('Congratulations!'); $I->see('Yii-powered');
Hier ist die aktuelle Hallo-Startseite:



Lassen Sie uns als nächstes den Test ausführen, einfach codecept run
:
$ codecept run Codeception PHP Testing Framework v2.1.11 Powered by PHPUnit 5.3.5 by Sebastian Bergmann and contributors. Acceptance Tests (1) --------------------------------------------------------------------------------------- Ensure that frontpage works (WelcomeCept) Ok ------------------------------------------------------------------------------------------------------------ Functional Tests (0) ------------------------ --------------------------------------------- Unit Tests (0) ------------------------------ --------------------------------------------- Time: 554 ms, Memory: 10.25MB OK (1 test, 2 assertions)
Wie Sie sehen können, hat unser Test bestanden und der Code zur Überprüfung dieser Funktionalität war sehr gut lesbar und einfach.
Hinweise zu den Standardtests von Yii
Um weiter zu gehen, habe ich Yi's Standardtests benutzt. An diesem Punkt stieß ich auf eine Reihe von Konfigurationsproblemen - hauptsächlich aufgrund der Verwendung des benutzerdefinierten yii2-Benutzermoduls in dieser Serie. Andere waren auf kleine Bugs mit Yii zurückzuführen, auf die das Team schnell reagiert hat und fixieren, wenn GitHub gemeldet wurde. In einigen Fällen wurden Probleme in späteren Versionen des yii2-basic tree behoben.
Da ich den yii2-basic tree für diese Serie aktualisiert habe, musste ich auch einige Änderungen an den Standardtests vornehmen.
Hier ist ein Beispiel für die Ausgabe zum Ausführen der Standard-Akzeptanztests, nachdem ich einige kleinere Anpassungen vorgenommen hatte:
$ codecept run Codeception PHP Testing Framework v2.1.11 Powered by PHPUnit 5.3.5 by Sebastian Bergmann and contributors. Acceptance Tests (4) ------------------------------------------------------------------------------------------------- Ensure that about works (AboutCept) Ok Ensure that contact works (ContactCept) Ok Ensure that home page works (HomeCept) Ok Ensure that login works (LoginCept) Ok ----------------------------------------------------------------------------------------------------------------------
Funktionsprüfung
Um funktionsfähige Tests zu erhalten, musste ich eine Instanz des integrierten Servers von Yii ausführen. Ich wusste nichts über diese Komponente, bis Yi's Alex Markov es in unserem GitHub-Austausch erwähnte.
$ ./yii serve
Ich habe kleine Änderungen an den Funktionstests in / tests / codeception / functional vorgenommen, hauptsächlich um nach meinen spezifischen aktualisierten Textzeichenfolgen zu suchen, d. H. "Invalid login or password" anstelle von Yi's Standard. Hier ist ein Blick auf LoginCept.php:
<?php use tests\codeception\_pages\LoginPage; $I = new FunctionalTester($scenario); $I->wantTo('ensure that login works'); $loginPage = LoginPage::openBy($I); $I->see('Login'); $I->amGoingTo('try to login with empty credentials'); $loginPage->login('', ''); $I->expectTo('see validations errors'); $I->see('Login cannot be blank.'); $I->see('Password cannot be blank.'); $I->amGoingTo('try to login with wrong credentials'); $loginPage->login('admin', 'wrong'); $I->expectTo('see validations errors'); $I->see('Invalid login or password'); $I->amGoingTo('try to login with correct credentials'); $loginPage->login('admin', 'admin11'); $I->expectTo('see user info'); $I->see('Logout');
Grundsätzlich greift der Code auf das LoginForm
-Modell zu und testet seine verschiedenen Methoden mit Hilfe von Yii serve.
Hier ist der Testcode /tests/codeception_pages/LoginPage.php, den er nutzt (ich musste ihn auch ändern, um Änderungen an der Serie vorzunehmen):
class LoginPage extends BasePage { public $route = 'user/login'; /** * @param string $username * @param string $password */ public function login($username, $password) { $this->actor->fillField('input[name="login-form[login]"]', $username); $this->actor->fillField('input[name="login-form[password]"]', $password); $this->actor->click('button[type=submit]'); } }
Sie können sehen, dass wir den Actor mit fillFields
kodieren und auf die Schaltflächen für unsere aktualisierten Formularfelder klicken
.
Bei der Fehlerbehebung meiner Codeception-Integration mit Yii fand ich es hilfreich, diese Tests im ausführlichen Modus auszuführen:
$ codecept run -vvv
Hier ist die ausführliche Ausgabe der Funktionstests für die Anmeldung: Im MacOS-Terminal sind PASSED
und FAILED
rot oder pinkfarben und für Sichtbarkeit invertiert:
Functional Tests (4) ------------------------------------------------------------------------------------------------- Modules: Filesystem, Yii2 ... ---------------------------------------------------------------------------------------------------------------------- Ensure that login works (LoginCept) Scenario: * I am on page "/index-test.php/user/login" [Page] /index-test.php/user/login [Response] 200 [Request Cookies] [] [Response Headers] {"content-type":["text/html; charset=UTF-8"]} * I see "Login" * I am going to try to login with empty credentials * I fill field "input[name="login-form[login]"]","" * I fill field "input[name="login-form[password]"]","" * I click "button[type=submit]" [Uri] http://localhost/index-test.php/user/login [Method] POST [Parameters] {"_csrf":"VEpvcmk3bVgFH1Y9AVsmYWQQDEouTSggYXMFGStdKBEnCyQfBxo8Bw==","login-form[login]":"","login-form[password]":""} [Page] http://localhost/index-test.php/user/login [Response] 200 [Request Cookies] {"_csrf":"dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada:2:{i:0;s:5:"_csrf";i:1;s:32:"QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_";}"} [Response Headers] {"content-type":["text/html; charset=UTF-8"]} * I expect to see validations errors * I see "Login cannot be blank." * I see "Password cannot be blank." * I am going to try to login with wrong credentials * I fill field "input[name="login-form[login]"]","admin" * I fill field "input[name="login-form[password]"]","wrong" * I click "button[type=submit]" [Uri] http://localhost/index-test.php/user/login [Method] POST [Parameters] {"_csrf":"QjFBRl9hMjMTZHgJNw15CnJrIn4YG3dLdwgrLR0Ld3oxcAorMUxjbA==","login-form[login]":"admin","login-form[password]":"wrong"} [Page] http://localhost/index-test.php/user/login [Response] 200 [Request Cookies] {"_csrf":"dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada:2:{i:0;s:5:"_csrf";i:1;s:32:"QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_";}"} [Response Headers] {"content-type":["text/html; charset=UTF-8"]} * I expect to see validations errors * I see "Invalid login or password" * I am going to try to login with correct credentials * I fill field "input[name="login-form[login]"]","admin" * I fill field "input[name="login-form[password]"]","admin11" * I click "button[type=submit]" [Uri] http://localhost/index-test.php/user/login [Method] POST [Parameters] {"_csrf":"bG8uMXdPYk49Ohd.HyMpd1w1TQkwNSc2WVZEWjUlJwcfLmVcGWIzEQ==","login-form[login]":"admin","login-form[password]":"admin11"} [Headers] {"location":["http://localhost/index-test.php"],"content-type":["text/html; charset=UTF-8"]} [Page] http://localhost/index-test.php/user/login [Response] 302 [Request Cookies] {"_csrf":"dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada:2:{i:0;s:5:"_csrf";i:1;s:32:"QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_";}"} [Response Headers] {"location":["http://localhost/index-test.php"],"content-type":["text/html; charset=UTF-8"]} [Redirecting to] http://localhost/index-test.php [Page] http://localhost/index-test.php [Response] 200 [Request Cookies] {"_csrf":"dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada:2:{i:0;s:5:"_csrf";i:1;s:32:"QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_";}"} [Response Headers] {"content-type":["text/html; charset=UTF-8"]} * I expect to see user info * I see "Logout" PASSED
Insgesamt gibt es ein bisschen zu lernen, um mit der Codeception anzufangen und Ihre Tests richtig zu programmieren. Aber die Ergebnisse sind beeindruckend und hilfreich.
Komponententest
Grundsätzlich sind Komponententests ein programmatischer Test unserer Infrastruktur und Modelle. Im Idealfall würden wir Tests für jede Methode und jede Nutzungsvariante unserer Modelle schreiben.
Leider war ich nicht in der Lage, Unit-Tests in unserem Baum zu betreiben, entweder wegen kleiner Yii-Bugs, die noch nicht veröffentlicht wurden, oder wegen Konfigurationsproblemen zwischen Codeception und yii2-user, die wir in Programmieren mit Yii2: Integrating User Registration integriert haben.
Unit Tests (3) ---------------------------------------------------------------------------------------------------- Modules: ------------------------------------------------------------------------------------------------------------------- Trying to test login no user (tests\codeception\unit\models\LoginFormTest::testLoginNoUser)... <pre>PHP Fatal Error 'yii\base\ErrorException' with message 'Call to undefined function tests\codeception\unit\models\expect()'
In unserer Startup-Reihe, die yii2-user nicht verwendet, sondern die integrierte Benutzerintegration der Yii Advanced-Baumstruktur verwendet, werde ich noch einmal auf Unit-Tests eingehen.
Lassen Sie uns ein paar Beispiele aus dem Yii2-App-Basisbaum betrachten.
E-Mails des Kontaktformulars testen
Der Befehl hello/tests/codeception/unit/models/ContactFormTest.php testet das Senden einer E-Mail über die programmatische Verwendung von Modellen:
<?php namespace tests\codeception\unit\models; use Yii; use yii\codeception\TestCase; use Codeception\Specify; class ContactFormTest extends TestCase { use Specify; protected function setUp() { parent::setUp(); Yii::$app->mailer->fileTransportCallback = function ($mailer, $message) { return 'testing_message.eml'; }; } protected function tearDown() { unlink($this->getMessageFile()); parent::tearDown(); } public function testContact() { $model = $this->createMock('app\models\ContactForm', ['validate']); $model->expects($this->once())->method('validate')->will($this->returnValue(true)); $model->attributes = [ 'name' => 'Tester', 'email' => 'tester@example.com', 'subject' => 'very important letter subject', 'body' => 'body of current message', ]; $model->contact('admin@example.com'); $this->specify('email should be send', function () { expect('email file should exist', file_exists($this->getMessageFile()))->true(); }); $this->specify('message should contain correct data', function () use ($model) { $emailMessage = file_get_contents($this->getMessageFile()); expect('email should contain user name', $emailMessage)->contains($model->name); expect('email should contain sender email', $emailMessage)->contains($model->email); expect('email should contain subject', $emailMessage)->contains($model->subject); expect('email should contain body', $emailMessage)->contains($model->body); }); } private function getMessageFile() { return Yii::getAlias(Yii::$app->mailer->fileTransportPath) . '/testing_message.eml'; } }
Ich konnte diesen Test aufgrund eines kleinen Fehlers in Yii, der noch nicht aktualisiert wurde (oder zumindest konnte ich den aktualisierten Code nicht finden), nicht erfolgreich bestehen. Mein Drop der Yii-Codebase benannte ausgehende E-Mails mit Datumsstempeln und der obige Code suchte nach einem festen Dateinamen. So ist es immer gescheitert. Dennoch ist es nützlich zu sehen, wie programmatische Tests Modelle verwenden können, um eine Datei zu generieren und dann nach dieser Datei zu suchen und ihren Inhalt zu überprüfen, um zu überprüfen, ob der Code funktioniert.
Testen der Anmeldung
Schauen wir uns hello/tests/codeception/unit/models/LoginFormTest.php an. Wiederum machte es meine Verwendung des yii2-Benutzers zum Zeitpunkt des Schreibens dieses Tutorials übermäßig schwierig zu integrieren; Wir können jedoch den konzeptionellen Ansatz für Unit-Test-Benutzermodellfunktionen betrachten.
Hier ist testLoginCorrect()
, die prüft, ob die Anmeldung mit einem korrekten Passwort erfolgreich ist:
public function testLoginCorrect() { $model = new LoginForm([ 'username' => 'admin', 'password' => 'admin11', ]); $this->specify('user should be able to login with correct credentials', function () use ($model) { expect('model should login user', $model->login())->true(); expect('error message should not be set', $model->errors)->hasntKey('password'); expect('user should be logged in', Yii::$app->user->isGuest)->false(); }); }
Es verwendet das LoginForm
-Modell, um den Benutzer programmgesteuert einzuloggen. Anschließend sucht es programmgesteuert nach dem aktuellen Benutzer von Yii, der nun kein Gast mehr ist.
expect('user should be logged in', Yii::$app->user->isGuest)->false();
Was kommt als nächstes?
Ich hoffe, dass es euch Spaß gemacht hat, über Codeception und seine Integration mit Yii zu lernen, trotz einiger der Hindernisse, denen ich begegnet bin. Die Standardinstallation von yii2-basic sollte heute besser funktionieren.
Wenn Sie mehr darüber erfahren möchten, wann und was getestet werden soll und warum, empfehle ich, Yiis Testing Overview zu lesen. Es gibt sicherlich mehr über Codeception zu lernen und umfassendere Tests zu schreiben.
Achten Sie auf kommende Tutorials in unserer Programming With Yii2-Serie, während wir weiter in verschiedene Aspekte des Frameworks eintauchen. Wenn du wissen möchtest, wann das nächste Yii2-Tutorial eintrifft, folge mir @reifman auf Twitter oder schau auf meiner Instructor-Seite vorbei.
Vielleicht möchten Sie auch unsere Build Your Startup With PHP-Serie, die Yii2-Vorlage verwendet, wie wir eine reale Anwendung erstellen. In der Tat können Sie heute die Startanwendung Meeting Planner ausprobieren.
ähnliche Links
- Codeception
- Yii2 Developer Exchange, meine Yii2-Ressourcen-Site
- Yii2 Testumgebung einrichten