Programmation avec Yii2 Test automatisé avec codeception

Ce que vous allez créer

Si vous demandez, "Qu'est-ce que Yii?" consultez mon tutoriel précédent, Introduction au framework Yii, qui passe en revue les avantages de Yii et inclut un aperçu des nouveautés de Yii 2.0, publiées en octobre 2014.

Dans cette série de programmation avec Yii2, je guide les lecteurs dans l'utilisation du framework Yii2 pour PHP. Dans ce tutoriel, je vais explorer les tests automatisés à l'aide de Codeception, intégré au framework de développement Yii2..

Certes, mon expérience en rédaction de tests avec mon code est rare. J'ai souvent fait partie de projets en solo ou de petits projets avec des ressources limitées. Pendant mon temps chez Microsoft, nous avions plusieurs équipes de test qui ont fait cela. Mais franchement, cela est probablement typique de vous aussi, non? Les programmeurs aiment coder, ils n'écrivent pas de tests, du moins les programmeurs de la vieille école ne l'ont pas.

Codeception est une bibliothèque innovante qui vise littéralement à rendre les tests d’écriture faciles et amusants. Et, je dirais qu'ils ont réussi dans une mesure raisonnable. Quand j'ai plongé mon pied dans l'eau de "Lake Codeception", c'était surtout facile et amusant. Cependant, alors que je commençais à aller plus loin, j'ai rencontré des problèmes de configuration avec Yii et les modules spécifiques utilisés dans cette série. Il y avait certainement des défis. Mais dans l’ensemble, je suis impressionné et vois les avantages d’apprendre plus.

En résumé, Codeception et son intégration à Yii me donnent envie d'écrire plus de tests, une première pour moi. Je soupçonne que vous aurez une expérience similaire. 

Un petit rappel avant de commencer, je participe aux commentaires ci-dessous. Je suis particulièrement intéressé si vous avez des idées supplémentaires ou si vous souhaitez suggérer des sujets pour de futurs tutoriels. Si vous avez une question ou une suggestion de sujet, veuillez poster ci-dessous. Vous pouvez également me joindre directement sur Twitter @reifman.

Commencer

Installer Codeception

Pour me guider, j'ai utilisé la documentation de Yii Testing Environment Setup. J'ai commencé avec une installation globale de la réception de code afin de pouvoir l'utiliser depuis n'importe quel projet.

$ composer global require "codeception / codeception = 2.1. *" Changement du répertoire en cours en /Users/Jeff/.composer ./composer.json a été mis à jour. Chargement des référentiels de compositeur avec les informations sur le paquet. yaml (v3.1.1) Chargement depuis le cache… codeception / codeception suggère d'installer symfony / phpunit-bridge (pour la prise en charge de phpunit-bridge) Ecriture d'un fichier verrou Génération de fichiers à chargement automatique

Vous devez également exiger codeception / spécifier:

$ composer global require "codeception / spécifie = *" Changement du répertoire en cours en /Users/Jeff/.composer ./composer.json a été mis à jour Chargement des référentiels de compositeur avec les informations sur le paquet. = * "- Installation de codeception / spécifie (0.4.3) Téléchargement: 100% écriture d'un fichier verrou Génération de fichiers à chargement automatique

Et codeception / vérifier:

$ composer composer require "codeception / verify = *" ./composer.json a été mis à jour Chargement des référentiels Composer avec les informations de paquet Mise à jour des dépendances (y compris require-dev) - Installation de codeception / verify (0.3.0) Téléchargement: 100% Écrire un fichier de verrouillage Générer chargement automatique des fichiers

Ensuite, il est utile de créer un alias pour codecept en utilisant votre répertoire global composer:

Etat global de $ composer Changement du répertoire en cours en /Users/Jeff/.composer Aucun changement local 

Cela définit l'alias:

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

Yii nécessite également l’installation de Faker, qui génère de fausses données de test pour votre application:

$ composer require --dev yiisoft / yii2-faker: * ./composer.json a été mis à jour Chargement des référentiels de compositeur avec les informations de paquet Mise à jour des dépendances (y compris require-dev) Rien à installer ou à mettre à jour Génération de fichiers à chargement automatique

Configuration de la réception de code avec votre application

Codecept bootstrapinitialise la réception de code pour votre application Yii, en créant une variété de fichiers de configuration pour la construction et l'exécution de tests sur votre application. Nous utilisons l'application Hello de cette série pour ce tutoriel. Voir le lien GitHub sur cette page pour obtenir le code.

$ codecept bootstrap Initialisation du codeception dans / Utilisateurs / Jeff / Sites / hello Fichier codeception.yml créé <- 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 généré avec succès. 0 méthodes ajoutées \ AcceptanceTester inclut les modules: PhpBrowser, \ Helper \ Acceptance AcceptanceTester.php créé. -> FunctionalTesterActions.php généré avec succès. 0 méthodes ajoutées \ FunctionalTester inclut les modules: \ Helper \ Functional FunctionalTester.php créé. -> UnitTesterActions.php généré avec succès. 0 méthodes ajoutées \ UnitTester inclut les modules: Asserts, \ Helper \ Unit UnitTester.php créé. Bootstrap est fait. Répertoire / Utilisateurs / Jeff / Sites / hello / tests

Pour une raison quelconque, je me suis également retrouvé avec des répertoires de test en double dans hello / tests; il suffit de supprimer hello / tests / fonctionnel, hello / tests / acceptation et hello / tests / unit pour régler le problème. Tous les tests vivent dans hello / tests / codeception / *.

Les différents types d'essais

Codeception se concentre sur trois types de tests:

  1. Le test des unités vérifie que des unités spécifiques fonctionnent, comme un test exhaustif de toutes les méthodes de votre modèle..
  2. Les tests fonctionnels vérifient les scénarios d'application courants comme si un utilisateur les agissait, mais en utilisant l'émulation de navigateur Web..
  3. Les tests d'acceptation sont identiques aux tests fonctionnels, mais ils sont exécutés via un navigateur Web..

Et il prend en charge trois types de formats de test pour votre code de test:

  1. Cept: c'est le fichier de test de scénario unique le plus simple
  2. Cest: un format orienté objet pour l'exécution de plusieurs tests dans un seul fichier
  3. Test: tests écrits sur PHPUnit, un framework de test PHP

Commençons par un exemple de tests d'acceptation en utilisant format cept:

Test d'acceptation

Nous allons utiliser Codeception Bienvenueexemple de test en premier.

$ codecept gener: acceptation de cept Welcome Test a été créé dans /Users/Jeff/Sites/hello/tests/acceptance/WelcomeCept.php.

Cela génère tests / acceptation / WelcomeCept.php, que nous éditerons ci-dessous.

Comme les tests d'acceptation nécessitent le navigateur, nous devons éditer /tests/acceptance.suite.yml dans notre projet pour fournir notre URL de développement., http: // localhost: 8888 / hello:

# Codeception Test Suite Configuration # # Suite pour les tests d'acceptation. # Effectuer des tests dans un navigateur en utilisant WebDriver ou PhpBrowser. # Si vous avez besoin des tests WebDriver et PHPBrowser, créez une suite séparée. nom_classe: Modules AcceptanceTester: activés: - PhpBrowser: url: http: // localhost: 8888 / hello / - \ Helper \ Acceptance 

Nous sommes maintenant prêts à modifier le test initial dans le fichier tests / acceptation / WelcomeCept.php. J'écris un test qui charge la première page pour s'assurer qu'il fonctionne comme prévu. 

Les tests de réception ont la notion d'acteur, dans ce cas, $ I = new AcceptanceTester ().

Voici comment cela décrit les acteurs dans la documentation de Codeception:

Nous avons un UnitTester, qui exécute des fonctions et teste le code. Nous avons également un FunctionalTester, un testeur qualifié, qui teste l'application dans son ensemble, avec une connaissance de ses composants internes. Et un AcceptanceTester, un utilisateur qui travaille avec notre application via une interface que nous fournissons.

Vous pouvez commenter vos tests avec du code, tel que $ I-> wantTo ('effectuer un certain test')ou "s'assurer que la page d'accueil fonctionne".

Dans mon test, je veux voir $ I-> voir texte pour 'Toutes nos félicitations!' et 'Alimenté par Yii':

wantTo ('s'assurer que Frontpage fonctionne'); $ I-> amOnPage ('/'); $ I-> voir ('Félicitations!'); $ I-> voir ('alimenté par Yii'); 

Voici la page d'accueil actuelle de Hello:

Ensuite, exécutons le test, simplement codecept run:

$ codecept run Codeception PHP Testing Framework v2.1.11 Développé par PHPUnit 5.3.5 par Sebastian Bergmann et ses contributeurs. Tests d'acceptation (1) --------------------------------------------- ------------------------------------------ Assurez-vous que Frontpage fonctionne (WelcomeCept) Ok -------------------------------------------------- -------------------------------------------------- -------- Tests fonctionnels (0) ------------------------ ------------- -------------------------------- Tests unitaires (0) ------------- ----------------- --------------------------------- ------------ Temps: 554 ms, mémoire: 10,25 Mo OK (1 test, 2 assertions)

Comme vous pouvez le constater, notre test a réussi et le code permettant de vérifier cette fonctionnalité était assez lisible et simple..

Notes sur les tests par défaut de Yii

Pour aller plus loin, j'ai commencé à utiliser les tests par défaut de Yii. À ce stade, j'ai rencontré un certain nombre de problèmes de configuration, principalement à cause de mon utilisation du module personnalisé yii2-user de cette série. D'autres étaient dus à de petits bugs avec Yii, que son équipe a rapidement réagi et corrigé lorsqu'il a été rapporté sur GitHub; dans certains cas, les problèmes avaient été résolus dans les versions ultérieures de l'arborescence yii2-basic.

De plus, comme j'avais mis à jour l'arborescence yii2-basic pour cette série, je devais apporter de petites modifications à certains tests par défaut..

Voici un exemple de résultat pour l'exécution des tests d'acceptation par défaut une fois que j'avais apporté quelques modifications mineures:

$ codecept run Codeception PHP Testing Framework v2.1.11 Développé par PHPUnit 5.3.5 par Sebastian Bergmann et ses contributeurs. Tests d'acceptation (4) --------------------------------------------- -------------------------------------------------- - Assurez-vous que ça fonctionne (AboutCept) Ok Assurez-vous que le contact fonctionne (ContactCept) Ok Assurez-vous que la page d'accueil fonctionne (HomeCept) Ok Assurez-vous que la connexion fonctionne (LoginCept) Ok ----------------------------------------------------------------------------------------------------------------------

Test fonctionel

Pour que les tests fonctionnels fonctionnent, je devais exécuter une instance du serveur intégré de Yii. Je n'avais pas entendu parler de ce composant jusqu'à ce qu'Alex Makarov de Yii en parle dans notre échange GitHub.

$ ./yii servir

J'ai apporté de petites modifications aux tests fonctionnels dans / tests / codeception / functional, principalement pour rechercher mes chaînes de texte mises à jour spécifiques, c'est-à-dire "Identifiant ou mot de passe invalide" à la place de la valeur par défaut de Yii. Voici un aperçu de LoginCept.php:

wantTo ('s'assure que la connexion fonctionne'); $ loginPage = LoginPage :: openBy ($ I); $ I-> voir ('Login'); $ I-> amGoingTo ('essayez de vous connecter avec des identifiants vides'); $ loginPage-> login (","); $ I-> expectTo ('voir les erreurs de validation'); $ I-> see ('Login ne peut pas être vide.'); $ I-> see ('Le mot de passe ne peut pas être vide.'); $ I-> amGoingTo ('essayez de vous connecter avec de mauvaises identifiants'); $ loginPage-> login ('admin', 'faux'); $ I-> expectTo ('voir les erreurs de validation'); $ I-> see ('Identifiant ou mot de passe invalide'); $ I-> amGoingTo ('essayez de vous connecter avec les informations d'identification correctes'); $ loginPage-> login ('admin', 'admin11'); $ I-> expectTo ('voir les informations de l'utilisateur'); $ I-> voir ('Logout');

Fondamentalement, le code accède à la Formulaire de connexion modéliser et tester ses différentes méthodes en utilisant Yii servir.

Voici le code de test /tests/codeception_pages/LoginPage.php dont il tire parti (je devais également le modifier pour les modifications apportées à la série):

class LoginPage étend BasePage public $ route = 'utilisateur / login'; / ** * chaîne @param $ username * @ chaîne @param mot_passe * / login de fonction publique ($ nom_utilisateur, $ mot_passe) $ this-> actor-> fillField ('input [name = "login-form [login]" ] ', $ nom d'utilisateur); $ this-> actor-> fillField ('input [name = "login-form [mot de passe]"]', $ mot de passe); $ this-> actor-> click ('button [type = submit]');  

Vous pouvez voir que nous codons l'acteur à champs de remplissageet Cliquez sur boutons pour nos champs de formulaire mis à jour. 

Lors du dépannage de l'intégration de Codeception avec Yii, j'ai trouvé utile d'exécuter ces tests en mode prolixe:

$ codecept run -vvv

Voici le résultat détaillé des tests fonctionnels de connexion dans le terminal MacOS, PASSÉ et ÉCHOUÉ sont de couleur rouge ou rose et inversés pour plus de visibilité:

Tests fonctionnels (4) --------------------------------------------- -------------------------------------------------- - Modules: Système de fichiers, Yii2… ---------------------------------------------- -------------------------------------------------- -------------------------- Assurez-vous que la connexion fonctionne (LoginCept) Scénario: * Je suis à la page "/index-test.php/user/ login "[Page] /index-test.php/user/login [Réponse] 200 [Demande de cookies] [] [En-têtes de réponse] " content-type ": [" text / html; charset = UTF-8 "] * Je vois "Login" * Je vais essayer de me connecter avec des identifiants vides * Je remplis le champ "input [name =" login-form [login] "," "* * Je remplis le champ" input [name = "login -form [mot de passe] "]", "" * je clique sur "bouton [type = submit]" [Uri] http: //localhost/index-test.php/user/login [Méthode] POST [Paramètres] "_csrf ":" VEpvcmk3bVgFH1Y9AVsmYWQQDEouTSggYXMFGStdKBEnCyQfBxo8Bw == "," formulaire de connexion [login] "," formulaire de connexion [mot de passe] ":" ""] [Page] http: //localhost/index-test.index.html. [Réponse] 200 [Demande de cookies] "_csrf": "dd395a9e5e3c08 cfb1615dae5fc7b5ba0a2025c003e430ba0139b300f4a917ada: 2: i: 0; s: 5: "_ csrf", i: 1; ; charset = UTF-8 "] * Je m'attends à voir des erreurs de validation * Je vois" Le nom de connexion ne peut pas être vide. "* Je vois" Le mot de passe ne peut pas être vide. "* Je vais essayer de me connecter avec de mauvaises informations d'identification * Je remplis le champ "input [nom =" login-formulaire [login] "]", "admin" * je remplis le champ "input [name =" login-formulaire [mot de passe] "]", "faux" * je clique sur le bouton [type = submit "" [Uri] http: //localhost/index-test.php/user/login [Méthode] POST [Paramètres] "_csrf": "QjFBRl9hMjMTZHgJNw15CnJrIn4YG3dLdwgrLR0LdxoxcAorMxbbAmour "," login-form [mot de passe] ":" faux " [Page] http: //localhost/index-test.php/user/login [Réponse] 200 [Demande de Cookies] " _csrf ":" dd395a9e5e3c08cfb1615dae5fc7b5b0ba00293029302930293029302930293029302929 » : i: 0; s: 5: "_ csrf"; i: 1; s: 32: "QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_"; " [En-têtes de réponse] " type de contenu ": [" text / html; charset = UTF-8 "] * Je m'attends à voir des erreurs de validation * Je vois" Identifiant ou mot de passe invalide "* Je vais essayer de me connecter avec les informations d'identification correctes * Je remplis le champ" input [name = "login-form [login ] "]", "admin" * Je remplis le champ "input [nom =" login-form [mot de passe] "]", "admin11" * je clique sur le bouton "[type = submit]" "[Uri] http: // localhost /index-test.php/user/login [Méthode] POST [Paramètres] "_csrf": "bG8uMXdPYk49Ohd.HyMpd1w1TQkwNT2WVZEWjUlJwcfLmVcGWIzEQ =", identifiez-vous comme par exemple: ":" admin11 " [en-têtes] " emplacement ": [" http: //localhost/index-test.php "]," type de contenu ": [" text / html; charset = UTF-8 "] [Page] http: //localhost/index-test.php/user/login [Réponse] 302 [Demande de cookies] " _csrf ":" dd3953013 "». : 5: "_ csrf"; i: 1; s: 32: "QU9OhlK90Zc8GzEx59jkBjEIsAKmn-Q_"; " [En-têtes de réponse] " location ": [" http: //localhost/index-test.php "]," content-type ": [" text / html; charset = UTF-8 "] [Rediriger vers] http: //localhost/index-test.php [Page] http: //localhost/index-test.php [Réponse] 200 [demander les cookies] " _csrf ": "dd395a9e5e3e8c8c8c8cfc7b5ba025c4b5ba025a4:": ";"; ";"; ";"; ";"; s: 32; html; charset = UTF-8 "] * Je m'attends à voir les informations utilisateur * Je vois" Déconnexion "PASSÉ 

Globalement, il y a un peu à apprendre à démarrer avec Codeception et à coder correctement vos tests. Mais les résultats sont impressionnants et utiles.

Tests unitaires

Fondamentalement, les tests unitaires sont des tests programmatiques de notre infrastructure et de nos modèles. Idéalement, nous rédigerions des tests pour chaque méthode et chaque variante d'utilisation de nos modèles..

Malheureusement, je n’ai pas pu faire fonctionner les tests unitaires dans notre arborescence à cause de petits bugs Yii qui n’ont pas encore été publiés ou de problèmes de configuration entre Codeception et yii2-user que nous avons intégrés à Comment programmer avec Yii2: Intégration de l’enregistrement utilisateur. 

Tests unitaires (3) --------------------------------------------- -------------------------------------------------- ----- Modules: ------------------------------------------- -------------------------------------------------- ---------------------- Essayer de tester la connexion sans utilisateur (tests \ codeception \ unité \ models \ LoginFormTest :: testLoginNoUser)… 
Erreur irrécupérable PHP 'yii \ base \ ErrorException' avec le message 'Appel à des tests de fonction non définis \ codeception \ unit \ models \ expect ()' 

J'aborderai à nouveau les tests unitaires dans notre série Startup qui n'utilise pas yii2-user mais utilise plutôt l'intégration utilisateur intégrée de l'arborescence Yii Advanced..

Regardons quelques exemples de l'arbre Yii2-app-basic.

Test des emails du formulaire de contact

Hello / tests / codeception / unit / models / ContactFormTest.php teste l'envoi d'un courrier électronique par le biais d'une utilisation programmatique de modèles:

mailer-> fileTransportCallback = function ($ mailer, $ message) return 'testing_message.eml'; ;  fonction protégée tearDown () unlink ($ this-> getMessageFile ()); parent :: tearDown ();  public function testContact () $ model = $ this-> createMock ('app \ models \ ContactForm', ['validate']); $ model-> attend ($ this-> once ()) -> méthode ('validate') -> will ($ this-> returnValue (true)); $ model-> attributs = ['name' => 'Testeur', 'email' => '[email protected]', 'sujet' => 'sujet de lettre très important', 'corps' => 'corps du courant message', ]; $ model-> contact ('[email protected] '); $ this-> spécifiez ('email devrait être envoyé', function () expect ('le fichier email devrait exister', file_exists ($ this-> getMessageFile ())) -> true ();); $ this-> spécifiez ('le message doit contenir les données correctes', function () use ($ model) $ emailMessage = file_get_contents ($ this-> getMessageFile ()); expect ('l'email doit contenir le nom d'utilisateur', $ emailMessage) -> contient ($ modèle-> nom); expect ("email doit contenir l'expéditeur", $ emailMessage) -> contient ($ modèle-> email); expect ("l'email doit contenir l'objet", $ emailMessage) -> contient ($ model-> subject); expect ('l'email doit contenir un corps', $ emailMessage) -> contient ($ model-> body););  fonction privée getMessageFile () return Yii :: getAlias ​​(Yii :: $ app-> mailer-> fileTransportPath). '/testing_message.eml';  

Je n'ai pas réussi à faire passer ce test à cause d'un petit bogue dans Yii qui n'a pas encore été mis à jour (ou au moins, je n'ai pas trouvé le code mis à jour). Ma chute de la base de code Yii nommait le courrier électronique sortant avec les horodatages et le code ci-dessus cherchait un nom de fichier fixe. Ainsi, cela a toujours échoué. Néanmoins, il est utile de voir comment les tests programmatiques peuvent utiliser des modèles pour générer un fichier, puis rechercher ce fichier et valider son contenu pour vérifier que le code fonctionne..

Test de connexion

Regardons hello / tests / codeception / unit / models / LoginFormTest.php. Encore une fois, mon utilisation de yii2-user a rendu l’intégration trop difficile au moment de la rédaction de ce tutoriel; Cependant, nous pouvons examiner l’approche conceptuelle des fonctions de modèle d’utilisateur des tests unitaires..

Voici testLoginCorrect (), qui cherche à voir si la connexion réussit avec un mot de passe correct:

fonction publique testLoginCorrect () $ model = new LoginForm (['username' => 'admin', 'password' => 'admin11',]); $ this-> spécifiez ('l'utilisateur devrait pouvoir se connecter avec les informations d'identification correctes', function () use ($ model) expect ('le modèle devrait se connecter comme utilisateur', $ model-> login ()) -> true (); expect ('le message d'erreur ne doit pas être défini', $ model-> errors) -> hasntKey ('password'); expect ('l'utilisateur doit être connecté', Yii :: $ app-> user-> isGuest) -> faux(); ); 

Il utilise le Formulaire de connexion modèle à connecter par programme à l'utilisateur, puis il recherche par programme si l'utilisateur actuel de Yii n'est plus un invité.

expect ('l'utilisateur doit être connecté', Yii :: $ app-> user-> isGuest) -> false ();

Et après?

J'espère que vous avez apprécié l'apprentissage de Codeception et de son intégration à Yii, en dépit des obstacles que j'ai rencontrés. L'installation par défaut de yii2-basic aujourd'hui devrait mieux fonctionner.

Si vous souhaitez en savoir plus sur le choix du moment et des raisons du test, je vous recommande de lire la vue d'ensemble des tests de Yii. Il y a certainement plus à apprendre sur Codeception et écrire des tests plus complets.

Surveillez les prochains tutoriels de notre série Programmation avec Yii2 pendant que nous continuons à plonger dans différents aspects du cadre. Si vous souhaitez savoir quand le prochain tutoriel Yii2 arrive, suivez-moi @reifman sur Twitter ou consultez ma page d'instructeur.. 

Vous voudrez peut-être aussi consulter notre série Construire votre démarrage avec PHP, qui utilise le modèle avancé de Yii2 pour créer une application réelle. En fait, vous pouvez essayer l'application de démarrage, Meeting Planner, aujourd'hui.

Liens connexes

  • Codeception
  • Yii2 Developer Exchange, mon site de ressources Yii2
  • Configuration de l'environnement de test Yii2