Sviluppo basato su test con Laravel e Doctrine

Come sviluppatore PHP, puoi usare la tecnica Test-Driven Development (TDD) per sviluppare il tuo software scrivendo dei test. In genere, TDD divide ogni attività dello sviluppo in singole unità. Viene quindi scritto un test per garantire che l'unità si comporti come previsto.

Ogni progetto che utilizza Test-Driven Development segue ripetutamente tre semplici passaggi:

  • Scrivi un test per il prossimo bit di funzionalità che desideri aggiungere.
  • Scrivi il codice funzionale fino alla fine del test.
  • Refactor sia nuovo che vecchio codice per renderlo ben strutturato.

Continuare a pedalare attraverso questi tre passaggi, un test alla volta, aumentando la funzionalità del sistema. I test ti aiuteranno nel refactoring, che ti permetterà di migliorare il tuo design nel tempo e renderà più evidenti alcuni problemi di progettazione.

Vengono chiamati i test che contengono piccoli singoli componenti test unitari. Mentre i test unitari possono essere eseguiti in modo indipendente, se si testano alcuni componenti quando sono integrati con altri componenti, lo si sta facendo test d'integrazione. Il terzo tipo di test è matrici di prova. Gli stub di test consentono di testare il codice senza dover effettuare chiamate reali a un database.

Perché funziona TDD

Oggigiorno, dato che puoi usare la moderna sintassi IDE di PHP, il feedback non è un grosso problema. Uno degli aspetti importanti del tuo sviluppo è fare in modo che il codice faccia ciò che ti aspetti che faccia. Poiché il software è complicato (componenti diversi integrati tra loro), sarebbe difficile per tutte le nostre aspettative diventare realtà. Soprattutto alla fine del progetto, a causa del tuo sviluppo, il progetto diventerà più complesso e quindi più difficile da eseguire il debug e testare.

TDD verifica che il codice faccia ciò che ti aspetti che faccia. Se qualcosa va storto, ci sono solo poche righe di codice da ricontrollare. Gli errori sono facili da trovare e risolvere. In TDD, il test si concentra sul comportamento, non sull'implementazione. TDD fornisce un codice comprovato che è stato testato, progettato e codificato.

PHPUnit e Laravel

PHPUnit è lo standard di fatto per il test delle unità PHP. È essenzialmente un framework per scrivere test e fornire gli strumenti necessari per eseguire test e analizzare i risultati. PHPUnit deriva la sua struttura e funzionalità dalla SUnit di Kent Beck.

Esistono diverse asserzioni che possono aiutarti a verificare i risultati di tutti i tipi di chiamate nelle tue applicazioni. A volte devi essere un po 'più creativo per testare una funzionalità più complessa, ma le asserzioni fornite da PHPUnit coprono la maggior parte dei casi che vorresti testare. Ecco un elenco di alcuni dei più comuni che utilizzerai nei tuoi test:

  • assertTrue: Controlla l'input per verificare che sia uguale a true.
  • AssertFalse: Controlla l'input per verificare che sia uguale al valore falso.
  • assertEquals: Controlla il risultato rispetto a un altro input per una corrispondenza.
  • AssertArrayHasKey (): Segnala un errore se l'array non ha la chiave.
  • AssertGreaterThan: Controlla il risultato per vedere se è più grande di un valore.
  • AssertContains: Verifica che l'input contenga un determinato valore.
  • AssertType: Verifica che una variabile sia di un certo tipo.
  • AssertNull: Verifica che una variabile sia nullo.
  • AssertFileExists: Verifica che esista un file.
  • AssertRegExp: Controlla l'input rispetto a un'espressione regolare.

Per impostazione predefinita, PHPUnit 4.0 è installato in Laravel ed è possibile eseguire il seguente comando per aggiornarlo:

bash compositore globale richiede "phpunit / phpunit = 5.0. *"

Il phpunit.xml il file nella directory principale di Laravel ti permetterà di fare alcune configurazioni. In questo caso, se desideri sovrascrivere la configurazione predefinita puoi modificare il file:

"xml

./ test / app /

"

Come si vede nel codice sopra, ho aggiunto la configurazione del database di esempio (non utilizzato nell'articolo).

Cos'è Doctrine ORM?

Doctrine è un ORM che implementa il pattern del data mapping e consente di separare in modo pulito le regole di business dell'applicazione dal livello di persistenza del database. Per configurare Doctrine, è disponibile un bridge per consentire la corrispondenza con la configurazione esistente di Laravel 5. Per installare Doctrine 2 nel nostro progetto Laravel, eseguiamo il seguente comando:

il compositore di bash richiede laravel-doctrine / orm

Come al solito, il pacchetto dovrebbe essere aggiunto al app / config.php, come fornitore di servizi:

php LaravelDoctrine \ ORM \ DoctrineServiceProvider :: class,

Anche l'alias deve essere configurato:

php 'EntityManager' => LaravelDoctrine \ ORM \ Facades \ EntityManager :: class

Infine, pubblichiamo la configurazione del pacchetto con:

fornitore bash php artisan: pubblicare --tag = "config"

Come testare i repository di Doctrine

Prima di ogni altra cosa, dovresti sapere degli infissi. Le fixture vengono utilizzate per caricare un set di dati controllato in un database, di cui abbiamo bisogno per il test. Fortunatamente, Doctrine 2 ha una libreria che ti aiuta a scrivere i dispositivi per l'ORM di Doctrine.

Per installare il pacchetto di fixture nella nostra app Laravel, è necessario eseguire il seguente comando:

bash compositore richiede --dev doctrine / doctrine-fixtures-bundle

Creiamo il nostro appuntamento in test / Fixtures.php:

"php namespace Test; usa Doctrine \ Common \ Persistence \ ObjectManager; usa Doctrine \ Common \ DataFixtures \ FixtureInterface; usa app \ Entity \ Post;

class Fixtures implementa FixtureInterface / ** * Carica le fixture Post * @param ObjectManager $ manager * @return void * / public function load (Gestore $ ObjectManager) $ Post = new Post (['title' => 'hello world' , 'body' => 'this is body']); $ Manager-> persistere ($ Post); $ Manager-> flush ();

"

Come vedi, la tua classe di dispositivi dovrebbe implementare il FixtureInterface e dovrebbe avere il carico (gestore $ ObjectManager) metodo. I dispositivi Doctrine2 sono classi PHP in cui è possibile creare oggetti e persisterli nel database. Per caricare automaticamente i nostri dispositivi in ​​Laravel, dobbiamo modificarli composer.json nella nostra radice di Laravel:

json ... "autoload-dev": "classmap": ["tests / TestCase.php", "tests / Fixtures.php" // aggiunto qui], ...

Quindi esegui:

bash compositore dump-autoload

Creiamo il nostro file di test nella directory dei test DoctrineTest.php.

"php namespace Test; usa App; usa App \ Entity \ Post; usa Doctrine \ Common \ DataFixtures \ Executor \ ORMExecutor; usa Doctrine \ Common \ DataFixtures \ Purger \ ORMPurger; usa Doctrine \ Common \ DataFixtures \ Loader; usa App \ Repository \ PostRepo;

class doctrineTest estende TestCase private $ em; repository $ privato; $ loader privato; funzione pubblica setUp () parent :: setUp (); $ this-> em = App :: make ('Doctrine \ ORM \ EntityManagerInterface'); $ this-> repository = new PostRepo ($ this-> em); $ this-> executor = new ORMExecutor ($ this-> em, new ORMPurger); $ this-> loader = nuovo Loader; $ this-> loader-> addFixture (new Fixtures);

/ ** @test * / public function post () $ purger = new ORMPurger (); $ executor = new ORMExecutor ($ this-> em, $ purger); $ Executor-> execute ($ this-> loader-> getFixtures ()); $ user = $ this-> repository-> PostOfTitle ('hello world'); $ This-> em-> clear (); $ this-> assertInstanceOf ('App \ Entity \ Post', $ utente);  "

Nel impostare() metodo, istanziato il ORMExecutor e il caricatore. Carichiamo anche il infissi classe che abbiamo appena implementato.

Non dimenticare che il / ** @test * / l'annotazione è molto importante, e senza di essa la php restituirà a Nessun test trovato in classe errore.

Per iniziare i test nella root del progetto, esegui il comando:

bash sudo phpunit

Il risultato sarebbe:

"bash PHPUnit 4.6.6 di Sebastian Bergmann e collaboratori.

Configurazione letta da /var/www/html/laravel/phpunit.xml. Tempo: 17.06 secondi, Memoria: 16.00M OK (1 test, 1 asserzione) "

Se si desidera condividere oggetti tra le fixture, è possibile aggiungere facilmente un riferimento a quell'oggetto per nome e poi fare riferimento a esso per formare una relazione. Ecco un esempio:

"php namespace Test; usa Doctrine \ Common \ Persistence \ ObjectManager; usa Doctrine \ Common \ DataFixtures \ FixtureInterface; usa app \ Entity \ Post;

class PostFixtures implementa FixtureInterface / ** * Carica le fix User * * @param ObjectManager $ manager * @return void * / public function load (Gestore $ ObjectManager) $ postOne = new Post (['title' => 'hello' , 'body' => 'this is body']); $ postTwo = new Post (['title' => 'hello there', 'body' => 'questo è body two']); $ Manager-> persistere ($ Postone); $ Manager-> persistere ($ postTwo); $ Manager-> flush ();

 // memorizza il riferimento al ruolo di amministratore per la relazione utente con il ruolo $ this-> addReference ('new-post', $ postOne);  "

e il dispositivo di commento:

"php namespace Test; usa Doctrine \ Common \ Persistence \ ObjectManager; usa Doctrine \ Common \ DataFixtures \ FixtureInterface; usa app \ Entity \ Post;

class CommentFixtures implementa FixtureInterface / ** * Carica le fix User * * @param ObjectManager $ manager * @return void * / public function load (Gestore $ ObjectManager) $ comment = new Comment (['title' => 'hello' , 'email' => '[email protected]', 'text' => 'nice post']); $ Comment-> setPost ($ this-> getReference ( 'new-post')); // carica il riferimento memorizzato $ manager-> persist ($ commento); $ Manager-> flush (); // memorizza il riferimento al nuovo post per la relazione Comment per postare $ this-> addReference ('new-post', $ postOne); "

Con due metodi di getReference () e setReference (), è possibile condividere oggetti tra i dispositivi.

Se l'ordine degli infissi è importante per te, puoi ordinarli facilmente con getOrder metodo nei tuoi dispositivi come segue:

funzione pubblica php getOrder () return 5; // numero in quale ordine caricare i dispositivi

Si noti che l'ordine è rilevante per la classe Loader.

Una delle cose importanti dei dispositivi è la loro capacità di risolvere i problemi di dipendenza. L'unica cosa che devi aggiungere è un metodo nel tuo dispositivo come ho fatto di seguito:

php public function getDependencies () return array ('Test \ CommentFixtures'); // L'apparecchio delle classi di fixture dipende da

Conclusione

Questa è solo una descrizione di Test-Driven Development con Laravel 5 e PHPUnit. Quando si testano i repository, è inevitabile che si arrivi al database. In questo caso, gli infissi di Doctrine sono importanti.