Programmazione con Yii2 test automatici con codeception

Cosa starai creando

Se stai chiedendo "Cos'è Yii?" guarda il mio tutorial precedente, Introduzione al framework Yii, che rivede i vantaggi di Yii e include una panoramica delle novità in Yii 2.0, rilasciata nell'ottobre 2014.

In questa serie di programmazione con Yii2, guido i lettori all'uso di Yii2 Framework per PHP. In questo tutorial, esplorerò i test automatici usando Codeception, che è integrato con il framework di sviluppo Yii2.

Certo, la mia esperienza di scrittura dei test con il mio codice è scarsa. Ho spesso partecipato a progetti singoli o piccoli con risorse limitate. Durante la mia permanenza in Microsoft, abbiamo avuto team di test distinti che lo hanno fatto. Ma francamente, questo è probabilmente tipico anche di te, giusto? Ai programmatori piace programmare, non scrivono test, almeno i programmatori della vecchia scuola no.

Codeception è una libreria innovativa che mira letteralmente a rendere i test di scrittura semplici e divertenti. E, direi che ci sono riusciti in misura ragionevole. Mentre immergevo l'alluce nell'acqua di "Lake Codeception", era per lo più facile e divertente. Tuttavia, quando ho iniziato ad approfondire, ho riscontrato problemi di configurazione con Yii e i moduli specifici utilizzati in questa serie. C'erano sicuramente delle sfide. Nel complesso, tuttavia, sono impressionato e vedo il vantaggio di imparare di più.

In parole povere, Codeception e la sua integrazione con Yii mi fanno venir voglia di scrivere più test, una prima volta per me. Sospetto che tu abbia un'esperienza simile. 

Un piccolo promemoria prima di iniziare, parteciperò alle discussioni dei commenti qui sotto. Sono particolarmente interessato se hai ulteriori pensieri o vuoi suggerire argomenti per futuri tutorial. Se hai una domanda o un suggerimento sull'argomento, per favore pubblica qui sotto. Puoi anche raggiungermi su Twitter direttamente @reifman.

Iniziare

Installare Codeception

Per guidarmi, ho usato la documentazione di installazione di Testing Environment di Yii. Ho iniziato con un'installazione globale di codeception in modo da poterla utilizzare da qualsiasi progetto.

$ compositore globale richiede "codeception / codeception = 2.1. *" La directory corrente modificata in /Users/Jeff/.composer ./composer.json è stata aggiornata Caricamento dei repository di composer con informazioni sul pacchetto Aggiornamento delle dipendenze (incluso require-dev) - Installazione di symfony / yaml (v3.1.1) Caricamento dalla cache ... codeception / codeception suggerisce l'installazione di symfony / phpunit-bridge (per il supporto di phpunit-bridge) Scrittura del file di blocco Generazione dei file di caricamento automatico

È inoltre necessario richiedere codeception / specificare:

$ compositore globale richiede "codeception / specificare = *" La directory corrente modificata in /Users/Jeff/.composer ./composer.json è stata aggiornata Caricamento dei repository di compositore con informazioni sul pacchetto L'aggiornamento delle dipendenze (incluso require-dev) compositore richiede "codeception / verify = * "- Installazione codeception / specifica (0.4.3) Download: 100% Scrittura file di blocco Generazione di file autoload

codeception / verificare:

$ compositore richiede "codeception / verify = *" ./composer.json è stato aggiornato Caricamento dei repository di composer con informazioni sul pacchetto Aggiornamento delle dipendenze (incluso require-dev) - Installazione di codeception / verify (0.3.0) Download: 100% Scrittura del file di blocco Generazione caricamento automatico dei file

Successivamente, aiuta a impostare un alias per codecept utilizzando la directory del compositore globale:

$ global status del compositore Cambiato la directory corrente in /Users/Jeff/.composer Nessuna modifica locale 

Questo imposta l'alias:

$ alias codecept = "/ Utenti / Jeff / .composer / vendor / bin / codecept"

Yii richiede anche l'installazione di Faker, che genera dati di test falsi per la tua applicazione:

$ compositore richiede --dev yiisoft / yii2-faker: * ./composer.json è stato aggiornato Caricamento dei repository di compositore con informazioni sui pacchetti Aggiornamento delle dipendenze (incluso require-dev) Niente da installare o aggiornare Generazione dei file di caricamento automatico

Impostare Codeception con la tua applicazione

Bootstrap codecettoinizializza la codeception per l'applicazione Yii, creando una varietà di file di configurazione per la creazione e l'esecuzione di test contro la tua applicazione. Stiamo utilizzando l'applicazione Hello di questa serie per questo tutorial. Vedi il link GitHub in questa pagina per ottenere il codice.

$ codecept bootstrap Inizializzazione Codeception in / Users / Jeff / Sites / hello File codeception.yml creato <- 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 generato con successo. 0 metodi aggiunti \ AcceptanceTester include moduli: PhpBrowser, \ Helper \ Acceptance AcceptanceTester.php creato. -> FunctionalTesterActions.php generato con successo. 0 metodi aggiunti \ FunctionalTester include moduli: \ Helper \ FunctionalTester.php creato. -> UnitTesterActions.php generato con successo. 0 metodi aggiunti \ UnitàTester include moduli: Asseriti, \ Helper \ Unità UnitTester.php creati. Bootstrap è fatto. Elenco utenti / utenti / Jeff / Sites / hello / tests

Per qualche ragione, ho anche finito con le directory di test duplicate in ciao / test; appena cancellando ciao / test / funzionale, ciao / test / accettazione e ciao / test / unità chiarito le cose. Tutti i test vivono in ciao / test / codeception / *.

I diversi tipi di test

La codeception è focalizzata su tre tipi di test:

  1. I test unitari verificano che unità specifiche stiano funzionando, come un test esaustivo di tutti i metodi del tuo modello.
  2. I test funzionali verificano scenari applicativi comuni come se un utente li stesse recitando, ma usando l'emulazione del browser web.
  3. Il test di accettazione è identico al test funzionale, ma in realtà esegue i test tramite un browser web.

E supporta tre diversi tipi di formati di test per il tuo codice di test:

  1. Cept: è il più semplice file di test dello scenario singolo
  2. Cest: un formato orientato agli oggetti per eseguire più test all'interno di un singolo file
  3. Test: test scritti su PHPUnit, un framework di test PHP

Iniziamo con un esempio di test di accettazione utilizzando formato sicuro:

Test di accettazione

Useremo la Codeception benvenutoprova prima l'esempio.

$ codecept genera: cept accettazione Welcome Test è stato creato in /Users/Jeff/Sites/hello/tests/acceptance/WelcomeCept.php

Questo genera Test / accettazione / WelcomeCept.php, che modificheremo qui sotto.

Poiché i test di accettazione richiedono il browser, dobbiamo modificare /tests/acceptance.suite.yml nel nostro progetto per fornire il nostro URL di sviluppo, http: // localhost: 8888 / ciao:

# Suite Suite # Codeception Test Suite per i test di accettazione. # Eseguire test nel browser utilizzando WebDriver o PhpBrowser. # Se sono necessari entrambi i test di WebDriver e PHPBrowser, creare una suite separata. class_name: moduli AcceptanceTester: abilitato: - PhpBrowser: url: http: // localhost: 8888 / hello / - \ Helper \ Acceptance 

Ora siamo pronti a modificare il test iniziale in test / accettazione / WelcomeCept.php. Sto scrivendo un test che carica la prima pagina per assicurarci che funzioni come previsto. 

I test di codeception hanno il concetto di attore, in questo caso, $ I = nuovo AcceptanceTester ().

Ecco come descrive gli attori nella documentazione di Codeception:

Abbiamo un UnitTester, che esegue funzioni e testa il codice. Abbiamo anche un FunctionalTester, un tester qualificato, che testa l'applicazione nel suo insieme, con la conoscenza dei suoi interni. E un AcceptanceTester, un utente che lavora con la nostra applicazione attraverso un'interfaccia che forniamo.

Puoi commentare i tuoi test con il codice, come ad esempio $ I-> wantTo ('esegue un determinato test')'assicurati che la prima pagina funzioni'.

Nel mio test, voglio vedere $ I-> vedi testo per 'Congratulazioni!' e 'Yu-powered':

wantTo ('assicurati che frontpage funzioni'); $ I-> amOnPage ( '/'); $ I-> vedi ( 'Congratulazioni!'); $ I-> vedi ( 'Yu-alimentato'); 

Ecco la home page attuale di Hello:

Quindi, eseguiamo il test, semplicemente run codecept:

$ codecept eseguito Codeception PHP Testing Framework v2.1.11 Realizzato da PHPUnit 5.3.5 di Sebastian Bergmann e collaboratori. Test di accettazione (1) --------------------------------------------- ------------------------------------------ Assicurarsi che la prima pagina funzioni (WelcomeCept) Ok -------------------------------------------------- -------------------------------------------------- -------- Test funzionali (0) ------------------------ ------------- -------------------------------- Test unitari (0) ------------- ----------------- --------------------------------- ------------ Tempo: 554 ms, Memoria: 10.25 MB OK (1 test, 2 asserzioni)

Come puoi vedere, il nostro test è stato superato e il codice per verificare questa funzionalità era abbastanza leggibile e semplice.

Note sui test predefiniti di Yii

Per andare oltre, ho iniziato a utilizzare i test predefiniti di Yii. A questo punto, mi sono imbattuto in un numero di problemi di configurazione, soprattutto a causa del mio uso del modulo utente yii2 personalizzato in questa serie. Altri erano dovuti a piccoli bug con Yii, a cui il suo team ha risposto e aggiustato rapidamente quando segnalato su GitHub; in alcuni casi, i problemi erano stati risolti nelle versioni successive dell'albero yii2-base.

Inoltre, poiché avevo aggiornato l'albero base yii2 per questa serie, ho dovuto apportare piccole modifiche ad alcuni dei test predefiniti.

Ecco un esempio dell'output per l'esecuzione dei test di accettazione predefiniti una volta apportati alcuni aggiustamenti minori:

$ codecept eseguito Codeception PHP Testing Framework v2.1.11 Realizzato da PHPUnit 5.3.5 di Sebastian Bergmann e collaboratori. Test di accettazione (4) --------------------------------------------- -------------------------------------------------- - Assicurati che funzioni (AboutCept) Ok Assicurati che il contatto funzioni (ContactCept) Ok Assicurati che la home page funzioni (HomeCept) Ok Assicurati che il login funzioni (LoginCept) Ok ----------------------------------------------------------------------------------------------------------------------

Test funzionali

Per far funzionare i test funzionali, avevo bisogno di eseguire un'istanza del server integrato di Yii. Non sapevo di questo componente fino a quando Alex Makarov di Yii non ne ha parlato nella nostra piattaforma GitHub.

$ ./yii serve

Ho apportato piccole modifiche ai test funzionali in / tests / codeception / functional, principalmente per cercare le mie stringhe di testo aggiornate specifiche, ad esempio "Login o password non validi" al posto di default di Yii. Ecco uno sguardo a LoginCept.php:

wantTo ('assicurati che il login funzioni'); $ loginPage = LoginPage :: openBy ($ I); $ I-> vedi ( 'Login'); $ I-> amGoingTo ('prova ad accedere con credenziali vuote'); $ LoginPage-> login ( ""); $ I-> expectTo ('vedi errori di validazione'); $ I-> vedere ('Login non può essere vuoto.'); $ I-> vedere ('Password non può essere vuota.'); $ I-> amGoingTo ('prova ad accedere con credenziali sbagliate'); $ loginPage-> login ('admin', 'wrong'); $ I-> expectTo ('vedi errori di validazione'); $ I-> vedere ('Login o password non validi'); $ I-> amGoingTo ('prova ad accedere con le credenziali corrette'); $ loginPage-> login ('admin', 'admin11'); $ I-> expectTo ('vedi informazioni utente'); $ I-> vedi ( 'Logout');

Fondamentalmente, il codice accede a LoginForm modella e testa i suoi vari metodi usando Yii serve.

Ecco il /tests/codeception_pages/LoginPage.php codice di test che sta facendo leva (ho anche dovuto modificarlo per le modifiche apportate alla serie):

class LoginPage estende BasePage public $ route = 'user / login'; / ** * @param stringa $ username * @param stringa $ password * / login funzione pubblica ($ username, $ password) $ this-> actor-> fillField ('input [nome = "login-form [login]" ] ', $ username); $ this-> actor-> fillField ('input [nome = "login-form [password]"]', $ password); $ This-> attore-> click ( 'tasto [type = submit]');  

Puoi vedere che stiamo codificando l'attore FillFieldsclic pulsanti per i nostri campi modulo aggiornati. 

Durante la risoluzione dei problemi con l'integrazione di Codeception con Yii, ho trovato utile eseguire questi test in modalità dettagliata:

$ codecept run -vvv

Ecco l'output dettagliato dei test di funzionalità di accesso: in MacOS Terminal, PASSATO e FALLITA sono codificati a colori rosso o rosa e invertiti per visibilità:

Test funzionali (4) --------------------------------------------- -------------------------------------------------- - Moduli: Filesystem, Yii2 ... ------------------------------------------ -------------------------------------------------- -------------------------- Assicurati che il login funzioni (LoginCept) Scenario: * I am on page "/index-test.php/user/ login "[Pagina] /index-test.php/user/login [Risposta] 200 [Richiedi cookie] [] [Intestazioni risposta] " tipo di contenuto ": [" testo / html; charset = UTF-8 "] * Vedo "Login" * Sto tentando di accedere con le credenziali vuote * I fill field "input [nome =" login-form [login] "]", "" * I fill field "input [nome =" login -form [password] "]", "" * clicco sul pulsante [tipo = invio] "[Uri] http: //localhost/index-test.php/user/login [Metodo] POST [Parametri] " _csrf ":" VEpvcmk3bVgFH1Y9AVsmYWQQDEouTSggYXMFGStdKBEnCyQfBxo8Bw == "," login-form [login] ":" "," login-form [password] ":" " [Pagina] http: //localhost/index-test.php/user/login [Risposta] 200 [Richiedi cookie] "_csrf": "dd395a9e5e3c08 cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada: 2: i: 0; s: 5: "_ csrf"; i: 1; s: 32: "QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_"; " [Intestazioni di risposta] " tipo di contenuto ": [" testo / html ; charset = UTF-8 "] * Mi aspetto di vedere errori di validazione * Vedo che" Login non può essere vuoto. "* Vedo che" La password non può essere vuota. "* Vado a provare ad accedere con credenziali errate * Compilo campo "input [nome =" login-form [login] "]", "admin" * I fill field "input [nome =" login-form [password] "]", "errato" * I clic "pulsante [tipo = invia] "[Uri] http: //localhost/index-test.php/user/login [Metodo] POST [Parametri] " _csrf ":" QjFBRl9hMjMTZHgJNw15CnJrIn4YG3dLdwgrLR0Ld3oxcAorMUxjbA == "," login-form [login] ":" admin "," login-form [password] ":" sbagliato " [Pagina] http: //localhost/index-test.php/user/login [Risposta] 200 [Richiedi cookie] " _csrf ":" dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada: 2 : i: 0; s: 5: "_ csrf"; i: 1; s: 32: "QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_"; " [Intestazioni di risposta] " tipo di contenuto ": [" testo / html; charset = UTF-8 "] * Mi aspetto di vedere errori di validazione * Vedo" Accesso o password non validi "* Vado a provare ad accedere con le credenziali corrette * Riempio campo" input [nome = "login-form [login ] "]", "admin" * I fill field "input [nome =" login-form [password] "]", "admin11" * I clic "pulsante [tipo = invio]" [Uri] http: // localhost /index-test.php/user/login [Metodo] POST [Parametri] "_csrf": "bG8uMXdPYk49Ohd.HyMpd1w1TQkwNSc2WVZEWjUlJwcfLmVcGWIzEQ ==", "login-form [login]": "admin", "login-form [password] ":" admin11 " [Intestazioni] " posizione ": [" http: //localhost/index-test.php "]," tipo di contenuto ": [" testo / html; charset = UTF-8 "] [Pagina] http: //localhost/index-test.php/user/login [Risposta] 302 [Richiedi cookie] " _csrf ":" dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada: 2: i: 0; s : 5: "_ csrf"; i: 1; s: 32: "QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_"; " [Intestazioni risposta] " posizione ": [" http: //localhost/index-test.php "]," Content-Type ": [" text / html; charset = UTF-8 "] [Reindirizzamento a] http: //localhost/index-test.php [Pagina] http: //localhost/index-test.php [Risposta] 200 [Richiedi cookie] " _csrf ": "dd395a9e5e3c08cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada: 2: i: 0; s: 5:" _ csrf "; i: 1; s: 32:" QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_ ";" [Intestazioni di risposta] "tipo di contenuto": ["testo / html; charset = UTF-8 "] * Mi aspetto di vedere le informazioni utente * Vedo" Logout "PASSATO 

Nel complesso, c'è un po 'da imparare a iniziare con Codeception e codificare correttamente i test. Ma i risultati sono impressionanti e utili.

Test unitario

Fondamentalmente, i test unitari sono test programmatici della nostra infrastruttura e dei nostri modelli. Idealmente, dovremmo scrivere test per ogni metodo e variazione di utilizzo dei nostri modelli.

Sfortunatamente, non sono riuscito a far funzionare i test unitari all'interno del nostro albero a causa di piccoli bug di Yii ancora da rilasciare o problemi di configurazione tra Codeception e yii2-user che abbiamo integrato in Come programmare con Yii2: Integrazione registrazione utente. 

Test unitari (3) --------------------------------------------- -------------------------------------------------- ----- Moduli: ------------------------------------------- -------------------------------------------------- ---------------------- Cercando di testare l'accesso senza utente (test \ codeception \ unit \ models \ LoginFormTest :: testLoginNoUser) ... 
Errore fatale PHP 'yii \ base \ ErrorException' con messaggio 'Chiama a test di funzione non definiti \ codeception \ unità \ models \ expect ()' 

Tratterò di nuovo il test delle unità nella nostra serie Startup che non usa yii2-user ma utilizza l'integrazione utente integrata nell'albero Yii Advanced.

Diamo un'occhiata ad un paio di esempi dall'albero Yii2-app-base.

Test delle email dei moduli di contatto

I test ciao / test / codeception / unit / models / ContactFormTest.php inviano un'email tramite l'uso programmatico dei modelli:

mailer-> fileTransportCallback = function ($ mailer, $ message) return 'testing_message.eml'; ;  funzione protetta tearDown () unlink ($ this-> getMessageFile ()); parent :: tearDown ();  public function testContact () $ model = $ this-> createMock ('app \ models \ ContactForm', ['validate']); $ Modello-> si aspetta ($ this-> una volta ()) -> Metodo ( 'validate') -> volontà ($ this-> returnValue (true)); $ model-> attributes = ['name' => 'Tester', 'email' => '[email protected]', 'subject' => 'soggetto lettera molto importante', 'body' => 'corpo corrente Messaggio', ]; $ Modello-> contatto ('[email protected] '); $ this-> specificare ('email dovrebbe essere send', function () expect ('il file email dovrebbe esistere', file_exists ($ this-> getMessageFile ())) -> true ();); $ this-> specifica ('il messaggio dovrebbe contenere dati corretti', function () usa ($ model) $ emailMessage = file_get_contents ($ this-> getMessageFile ()); aspettati ('email dovrebbe contenere il nome utente', $ emailMessage) -> contiene ($ model-> name); expect ('email dovrebbe contenere email del mittente', $ emailMessage) -> contains ($ model-> email); expect ('email dovrebbe contenere oggetto', $ emailMessage) -> contiene ($ model-> subject); expect ('email dovrebbe contenere body', $ emailMessage) -> contains ($ model-> body););  funzione privata getMessageFile () return Yii :: getAlias ​​(Yii :: $ app-> mailer-> fileTransportPath). '/Testing_message.eml';  

Non sono riuscito a far passare questo test a causa di un piccolo bug in Yii che non è stato ancora aggiornato (o almeno non ho trovato il codice aggiornato). La mia caduta della base di codice Yii stava denominando la posta elettronica in uscita con i timbri di data e il codice di cui sopra stava cercando un nome di file fisso. Quindi, ha sempre fallito. Tuttavia, è utile vedere come i test programmatici possono utilizzare i modelli per generare un file e quindi cercare quel file e convalidarne il contenuto per verificare che il codice funzioni.

Test di accesso

Diamo un'occhiata a ciao / test / codeception / unit / models / LoginFormTest.php. Ancora una volta, il mio uso di yii2-user ha reso eccessivamente difficile l'integrazione al momento della stesura di questo tutorial; tuttavia, possiamo esaminare l'approccio concettuale all'unità di test delle funzioni del modello utente.

Ecco testLoginCorrect (), che sembra vedere se l'accesso ha esito positivo con una password corretta:

funzione pubblica testLoginCorrect () $ model = new LoginForm (['username' => 'admin', 'password' => 'admin11',]); $ this-> specificare ('utente dovrebbe essere in grado di accedere con credenziali corrette', function () use ($ model) expect ('model dovrebbe login user', $ model-> login ()) -> true (); aspettati ('messaggio di errore non dovrebbe essere impostato', $ modello-> errori) -> hasntKey ('password'); aspettati ('utente deve essere loggato', Yii :: $ app-> utente-> isGuest) -> false ();); 

Usa il LoginForm modello per accedere in modo programmatico all'utente, quindi guarda a livello di codice per vedere se l'utente corrente di Yii non è più un ospite.

aspettati ('utente dovrebbe essere loggato', Yii :: $ app-> utente-> isGuest) -> false ();

Qual'è il prossimo?

Spero che ti sia piaciuto conoscere Codeception e la sua integrazione con Yii, nonostante alcuni dei blocchi stradali in cui mi sono imbattuto. L'installazione predefinita di yii2-basic oggi dovrebbe funzionare meglio.

Se vuoi saperne di più su come decidere quando e cosa testare e perché, ti consiglio di leggere la Panoramica dei test di Yii. C'è sicuramente altro da imparare su Codeception e scrivere test più completi.

Guarda le prossime esercitazioni nella nostra serie Programming With Yii2 mentre continuiamo a esplorare i diversi aspetti del framework. Se vuoi sapere quando arriverà il prossimo tutorial di Yii2, seguimi @reifman su Twitter o controlla la mia pagina di istruttore. 

Potresti anche voler dare un'occhiata alla nostra serie Building Your Startup with PHP, che utilizza il template avanzato di Yii2 mentre costruiamo un'applicazione reale. In effetti, puoi provare l'applicazione di avvio, Meeting Planner, oggi.

Link correlati

  • Codeception
  • Yii2 Developer Exchange, il mio sito di risorse Yii2
  • Yii2 Testing Environment Setup