N'ayant pas trouvé d'exemple concret unique d'une implémentation de Gherkin avec un modèle de conception d'
objet de page pour
Codeception sur
Internet , je pensais qu'il ne serait pas
déplacé de parler à Internet de notre propre implémentation de ce modèle.
Cet article est destiné davantage à ceux qui connaissent déjà un peu Codeception ou des cadres similaires, mais ne savent pas encore comment utiliser Test Object pour rendre les tests plus lisibles, simplifier leur prise en charge et réduire la quantité de code supplémentaire. Néanmoins, j'ai essayé d'expliquer pas à pas tous les points principaux de l'assemblage du projet d'automatisation à partir de zéro.
Le modèle d'objet de page vous permet d'encapsuler le travail avec des éléments de page, ce qui vous permet à son tour de réduire la quantité de code et de simplifier sa prise en charge. Toutes les modifications de l'interface utilisateur sont facilement et rapidement mises en œuvre - il suffit de mettre à jour la classe d'objet de page qui décrit cette page. Un autre avantage important de cette approche architecturale est qu'elle vous permet de ne pas encombrer le script de test HTML avec des détails, ce qui le rend plus compréhensible et simple à comprendre.
Voici à quoi ressemble le test sans utiliser l'objet de page

Utilisation de l'objet de page

Je ne m'attarderai pas sur l'installation de l'environnement de base, je donnerai mes données initiales:
- Castor bionique Ubuntu
- PHP 7.1.19-1
- Composer - gestionnaire de gestion des dépendances pour PHP, installé dans le monde entier
- PhpStorm - environnement de développement
Pour exécuter les tests, nous avons également besoin:
Développer Codeception
Procédez à l'installation de Codeception:
Nous ouvrons dans le terminal le répertoire dont nous avons besoin, où nous allons collecter le projet, ou créer un répertoire pour le projet et y aller:
mkdir ProjectTutorial cd ProjectTutorial
Installez le framework Codeception et ses dépendances:
composer require codeception/codeception --dev

Le fichier d'installation des dépendances composer.json dans le projet ressemblera à ceci:
{ "require": { "php": ">=5.6.0 <8.0", "facebook/webdriver": ">=1.1.3 <2.0", "behat/gherkin": "^4.4.0", "codeception/phpunit-wrapper": "^6.0.9|^7.0.6" }, "require-dev": { "codeception/codeception": "^2.5", "codeception/base": "^2.5" } }
Développez le projet:
php vendor/bin/codecept bootstrap

Vous trouverez plus d'informations sur l'installation du projet dans la
documentation officielle .
A ce stade, trois ensembles de tests sont créés dans notre projet. Par défaut, Codeception les divise en acceptation, fonction et unité. Pour ces ensembles, Codeception génère également trois fichiers yml. Nous y indiquons toutes les
configurations nécessaires, connectons les modules et les propriétés pour exécuter nos tests.
Cette leçon est construite sur l'exemple du test d'acceptation, je vais donc donner les paramètres dans Acceptance.suite.yml.
Ouvrez notre projet dans PHP Storm (ou un autre environnement de développement préféré) et accédez à
Acceptance.suite.yml (par défaut, il se trouve dans le dossier tests / acceptation.suite.yml).
Nous notons les dépendances minimales nécessaires et faisons toujours attention au formatage. Les modules sont séparés par un signe "-" et doivent être au même niveau, sinon des erreurs se répandront au démarrage du test.
Il s'avère:
actor: AcceptanceTester modules: enabled: - WebDriver: url: 'http://yandex.ru/' // , browser: 'chrome' - \Helper\Acceptance // gherkin: contexts: default: - AcceptanceTester
Et quelques travaux préparatoires supplémentaires:
Créez un répertoire séparé dans la racine du projet (j'ai lib).
Dans ce répertoire, créez le fichier exécutable run.sh, qui exécutera Selenium et Chrome Driver.
Nous mettons ici Selenium et Chrome Driver, et écrivons la commande run dans run.sh:
java -jar -Dwebdriver.chrome.driver=chromedriver_241 selenium-server-standalone-3.14.0.jar
A quoi cela ressemble dans le projet:

Nous revenons à la console et modifions les droits d'accès:
chmod +x ./run.sh
(remarque. Les noms des pilotes se trouvant dans le répertoire doivent correspondre exactement à ceux spécifiés dans la commande de démarrage).Vous pouvez démarrer Selenium et Webdriver dès maintenant pour ne pas y revenir. Pour ce faire, ouvrez un nouvel onglet de terminal, accédez au répertoire où se trouve le fichier run.sh et écrivez la commande de lancement:
~/AutomationProjects/ProjectTutorial/lib$ ./run.sh
Assurez-vous que le serveur fonctionne:

Nous le laissons en état de marche. Sur ce travail préparatoire est terminé.
Écrire un script de test
Nous procédons à la création d'un fichier de fonctionnalités pour notre scénario de test. Pour ce faire, une commande spéciale est fournie dans Codeception, exécutez-la dans la console:
cept g:feature acceptance check
(notez «check» - le nom de mon test)Nous voyons le nouveau fichier check.feature dans le dossier d'acceptation.

Nous n'avons pas besoin du contenu par défaut, nous le supprimons immédiatement et écrivons notre test.
Pour que le collectionneur reconnaisse l'alphabet cyrillique, n'oubliez pas de démarrer le script avec #language: ru.
Nous écrivons un court script en russe. Je vous rappelle que chaque phrase doit commencer par les mots clés: "Quand", "Alors", "Et", le symbole "*", etc.
Pour mon exemple, j'ai pris le site Web Yandex, vous pouvez en prendre n'importe quel.

Pour voir quelles sont les étapes du test, nous exécutons notre script dans le terminal:
cept dry-run acceptance check.feature

Les étapes du script sont affichées dans la console, mais leur implémentation n'est pas encore disponible.
Ensuite, nous exécutons une commande qui générera automatiquement des modèles pour implémenter nos méthodes:
cept gherkin:snippets acceptance

Tous les noms du script qui étaient entre guillemets sont remplacés par des variables: arg.
Nous les copions depuis le terminal et les collons dans le fichier
AcceptanceTester.php , où se trouvent les méthodes de travail avec les éléments de page.

Renommez les méthodes en méthodes lisibles, reflétant leur essence (facultatif), et écrivez leur implémentation.

Tout est simple, mais encore plus simple si vous travaillez dans un environnement de développement intelligent, tel que Storm, qui lui-même demandera les commandes nécessaires depuis la bibliothèque:

Nous supprimons l'excédent et écrivons les méthodes:
public function step_beingOnMainPage($page) { $this->amOnPage('/'); } public function step_seeElement($element) { this->seeElement($element); } public function step_clickOnButton($button) { $this->click($button); } public function step_fillField($field, $text) { $this->fillField($field, $text); }
Voyons ce qui s'est passé. Nous lançons une équipe qui nous montrera quelles méthodes (étape) nous avons maintenant une implémentation.
cept gherkin:steps acceptance

Succès!
Mais les étapes du fichier de fonctionnalités ne sont toujours pas reconnues comme des méthodes.

Pour que Storm comprenne ce qu'il faut faire des étapes, nous allons faire un tour avec l'implémentation de l'interface Context à partir de l'espace de noms Gherkin Context.
namespace Behat\Behat\Context { interface Context {} }
Enveloppez notre classe AcceptanceTester dans un espace de noms et héritez du contexte
implements \Behat\Behat\Context\Context

Maintenant, toutes les étapes du fichier de fonctionnalités sont liées à leur implémentation:

Pour que Webdriver comprenne sur quoi cliquer et où chercher, vous devez remplacer les noms lisibles des éléments et des adresses de page par les localisateurs et URL correspondants, qui tomberont dans les méthodes comme arguments.
Ensuite, nous obtenons un test du formulaire:

Et vous pouvez exécuter:
cept run acceptance

Réussi
env. Si le chargement des éléments de page prend du temps, vous pouvez ajouter l'attente à la méthode souhaitée:
$this->waitForElementVisible($element);
Nous revenons à notre scénario de test. Nous sommes fâchés que la lisibilité totale du test soit perdue du fait qu'au lieu des noms clairs des éléments et des pages, nous voyons des éléments HTML et des URL.
Si nous voulons résoudre ce problème, il est temps de passer à la mise en œuvre du modèle d'objet de page.
Aller à l'objet de page
Dans le répertoire _support, créez le répertoire Page, où nous mettrons nos pages de classe:
php vendor/bin/codecept generate:pageobject MainPage
Le premier objet Page est la page principale de Yandex, appelons-le MainPage, nous appellerons la classe de la même manière:

Ici, nous déclarons des champs et des méthodes statiques afin qu'ils puissent être appelés sans créer d'objet.
Puisque dans les configurations d'Acceptance.suite.yml nous avons déjà spécifié l'url de la page de démarrage:
yandex.ru , pour la page principale il suffira de préciser
public static $URL = '/';
Vient ensuite un tableau d'éléments de page. Nous décrivons des localisateurs pour plusieurs éléments et leur donnons des noms clairs et uniques.
Vous devez maintenant ajouter la méthode getElement, qui renverra le localisateur par le nom de l'élément du tableau.
En conséquence, nous avons:
<?php //location: tests/_support/Page/MainPage.php namespace Page; /** */ class MainPage { public static $URL = '/'; public static $elements = array( ' ' => "//*[@id='wd-wrapper-_afisha']", ' ' => "//*[@data-statlog='afisha.title.link']", ' ' => "//*[@class='weather__icon weather__icon_ovc']|//*[@class='weather__icon weather__icon_skc_d']", ); public static function getElement($name){ return self::$elements[$name]; } }
Ajoutez quelques classes de pages:
/ ** Affiche * /

/ ** Poster - Résultats de recherche * /

Nous revenons à la classe
AcceptanceTester.php , où nous avons écrit nos méthodes.
Créons-y un tableau de classes PageObject, où nous allons assigner les noms aux pages et indiquer leurs noms de classe dans l'espace de noms:
private $pages = array( " " => "\Page\MainPage", "" => "\Page\AfishaPage", " - " => "\Page\AfishaResult" );
Chaque nouveau PageObject est également ajouté à ce tableau.
Ensuite, nous devons créer le champ currentPage, qui stockera le lien vers le PageObject de la page actuelle:
private $currentPage;
Maintenant, nous allons écrire une méthode, lorsqu'elle est appelée, nous pouvons obtenir currentPage et initialiser la classe PageObject dont nous avons besoin.
Il est logique de faire une étape comme celle-ci en utilisant la méthode "Lorsque l'utilisateur accède à la page" Nom de la page ". Ensuite, le moyen le plus simple d'initialiser la classe PageObject, sans vérifications, ressemblerait à ceci:
/** * @When :page */ public function step_beingOn($page) { // pageObject $this->currentPage = $this->pages[$page]; }
Maintenant, nous écrivons la méthode getPageElement, qui nous permettra d'obtenir l'élément, ou plutôt son localisateur depuis la page courante:
private function getPageElement($elementName) { // $curPage = $this->currentPage; return $curPage::getElement($elementName); }

Pour les méthodes déjà implémentées, il est nécessaire de remplacer les arguments que nous avons reçus directement du texte d'entité au début par des éléments de PageObject, c'est-à-dire:
$arg
prendra la forme
getPageElement($arg))
Ensuite, nos méthodes prendront la forme:
/** * @When :page */ public function step_beingOnMainPage($page) { // pageObject $this->currentPage = $this->pages[$page]; $curPage = $this->currentPage; $this->amOnPage($curPage::$URL); } /** * @Then :element */ public function step_seeElement($element) { $this->waitForElementVisible($this->getPageElement($element)); $this->seeElement($this->getPageElement($element)); } /** * @Then :button */ public function step_clickOnButton($button) { $this->click($this->getPageElement($button)); } /** * @Then :field :text */ public function step_fillField($field, $text) { $this->fillField($this->getPageElement($field), $text); } /** * @Then :field */ public function step_deleteText($field) { $this->clearField($this->getPageElement($field)); }
Ajout d'une autre méthode pour afficher les résultats de la recherche en appuyant sur Entrée:
public function step_keyboardButton() { $this->pressKey('//input',WebDriverKeys::ENTER); }
La dernière étape est lorsque toutes les méthodes et PageObjects nécessaires sont décrits, vous devez refactoriser le test lui-même. Ajoutez les étapes qui initialiseront PageObject lors du passage à une nouvelle page. Nous avons cet «* utilisateur est allé à la page: page».
Pour plus de clarté, j'ajouterai quelques étapes supplémentaires. Le résultat est ce test:
#language: ru : : . . . " " " " " " " " "" " " " " ENTER " - " " " " " " " "" ENTER
Un tel scénario de test est compréhensible et lisible pour tout étranger.
Lancez!
Pour afficher un résultat d'exécution plus détaillé, vous pouvez utiliser la commande
cept run acceptance --debug
Nous regardons le résultat:

Ainsi, l'utilisation du modèle d'objet de page vous permet de séparer tous les éléments de page des scripts de test et de les stocker dans un répertoire distinct.
Le projet lui-même peut être trouvé sur
https://github.com/Remneva/ProjectTutorialEn tant qu'ingénieur en automatisation débutant, je vous serais reconnaissant de partager vos idées et, peut-être, de me dire comment transformer et simplifier de manière plus logique la structure du projet.