Skip to content
Snippets Groups Projects
Commit 4e5ce9a3 authored by PIERRON Laurent's avatar PIERRON Laurent :man_in_tuxedo_tone1:
Browse files

adding correction for BDD.

parent 47328311
No related branches found
No related tags found
No related merge requests found
# Corrigé du TP BDD
## Installation des logiciels
Récupération du projet sur le dépôt :
```bash
git clone https://gitlab.univ-lorraine.fr/pierron9/pastebin
cd pastebin
```
Création de la branche d etravauil :
```bash
git branch pierron9
git switch pierron9
git status
git push --set-upstream origin pierron9
```
Mise en route et vérification du fonctionnement de l'application :
```bash
composer self-update
composer update
php -S lacalhost:8000
```
Installation de *codeception* :
```bash
composer remove phpunit/phpunit
composer require "codeception/codeception" --dev
composer update
php vendor/bin/codecept bootstrap
```
## Premiers tests avec `PhpBrowser`
Afin de visualiser les mêmes informations en **anglais** que ce que vous fournit le module `PhpBrowser` de navigation *headless* de *codeception* , je vous recommande d'utiliser un navigator comme `Firefox`, que vous configurerez pour afficher les pages en anglais.
Configuration du serveur pour les tests d'acceptation dans `tests/Acceptance.suite.yml` :
```yaml
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost:8000/
```
Création du premier test dans `tests/Acceptance/PremierCest.php`, attention par défaut la page est en anglais.
Si vous avez une erreur, vous pouvez consulter le contenu du fichier `HTML` dans `tests/_output`.
Voici un exemple de premier test, on contrôle la présence de la petite *maxime* en bas de page *Because ignorance is bliss* :
```php
<?php
namespace Tests\Acceptance;
use Tests\Support\AcceptanceTester;
class PremierCest
{
// tests
public function frontpageWorks(AcceptanceTester $I)
{
$I->amOnPage('/');
$I->see('Because ignorance is bliss');
}
}
```
## Tester une application avec JS côté client
Malheureusement le logiciel `PrivateBin` nécessite un navigateur capable d'interpréter le code `Javascript` embarqué.
Avec `codeception`, la solution passe par le module `WebDriver`, qu'il faut tout d'abord installer.
Ce module permettra d'utiliser l'un des navigateurs visuels suivants : `Chrome`, `Firefox`,
ou l'un des navigateurs *headless* suivants : `Selenium Headless`, `ChromeDriver`, `GeckoDriver`
Installation de `WebDriver` et de `Selenium` dans une nouvelle branche `git` nommée `<votre login>_sel` :
```bash
git branch -C <votre login>_sel
git push --set-upstream origin pierron9_sel
composer require --dev codeception/module-webdriver
npm install selenium-standalone -g
selenium-standalone install && selenium-standalone start
```
### Paramétrage de `Acceptance.suite.yml`
On va paramétrer nos tests pour utiliser `Google Chrome` en mode *headless* avec le français comme langue souhaitée.
Ce qui donne :
```yml
actor: AcceptanceTester
modules:
enabled:
- WebDriver:
url: 'http://localhost:8000/'
browser: chrome
capabilities:
chromeOptions:
args: ["--headless", "--disable-gpu", "--lang=fr-fr"]
```
### Réalisation de tests simples dans `FrenchBinCest.php`
On réalise quelques tests simples pour s'assurer que `PrivateBin` est bien lancé et que la première page
d'enregistrement d'un text fonctionne comme souhaitée :
```php
<?php
namespace Tests\Acceptance;
use Tests\Support\AcceptanceTester;
class FrenchBinCest
{
// tests
public function privatebin_is_running(AcceptanceTester $I)
{
$I->amOnPage('/');
$I->see('PrivateBin');
$I->see('1.5.1');
}
public function frontapge_is_in_french(AcceptanceTester $I)
{
$I->amOnPage('/');
$I->see('Vivons heureux, vivons cachés');
}
public function fr_javascript_is_setup(AcceptanceTester $I)
{
$I->amOnPage('/');
$I->dontSeeElement('#noscript');
$I->dontSee('JavaScript est requis pour faire fonctionner PrivateBin. Désolé pour cet inconvénient.', '#noscript');
}
public function preview_a_text_message_works(AcceptanceTester $I)
{
$msg = "Ceci n'est pas une pipe.";
$I->amOnPage('/');
//$I->waitForElement('#message', 5);
$I->fillField('#message', $msg);
//$I->waitForElement('#messagepreview', 5);
$I->click('#messagepreview');
$I->see($msg, '#prettyprint');
}
}
```
### Réalisation d'un test fonctionnel/acceptation complexe
On souhaite réaliser un test, qui met en oeuvre le petit scénario suivant :
1. création d'un document `pastebin`;
2. enregistrement du document ;
3. récupération de l'url du document ;
4. retour à la page principale de création de document ;
5. affichage du document enregistré.
Voici un exemple de programmation de ce scénario à ajouter à votre batterie de tests :
```php
public function create_and_read_a_text_message(AcceptanceTester $I)
{
// Message to paste in a document
$msg = "Ceci n'est pas une pipe.";
// 1. & 2. Create and send a paste
$I->amOnPage('/');
$I->fillField('#message', $msg);
$I->click(' Envoyer ');
// 3. View the send paste and get its url
$I->see('Votre paste est disponible');
$paste_url = $I->grabAttributeFrom('#pasteurl', 'href');
$I->click(['css' => 'img[alt="PrivateBin"][src="img/icon.svg"]']);
// 4. Go on main page to create a new paste
$I->dontSeeInCurrentUrl('?');
$I->see('Éditer');
// 5. Show the first created paste
$I->amOnUrl($paste_url);
$I->see('Ce document expirera');
$I->see($msg, '#prettyprint');
}
```
## Réalisation des tests comportementaux (BDD)
**BDD = BEHAVIOR DRIVEN DEVELOPMENT**
Les idées derrière le BDD peuvent être résumées en :
- décrire des fonctionnalités dans un scénario avec un texte formel
- utiliser des exemples pour rendre concrètes les sbstractions
- implémenter chaque étape d'un scénario pour la tester
- écrire le vrai code réalisant la fonctionnalité.'
En écrivant chaque fonctionnalité dans un format de Scénario d'Usage (User STory),
qui est **exécutable autmoatiqument** comme un test nous nous assurons que :
les décideurs, les développeurs et les commerciaux sont dans le même bateau.
Une histoire peut ressembler à cela :
```
We can try to write such simple story:
As a customer I want to buy several products
I put first product with $600 price to my cart
And then another one with $1000 price
When I go to checkout process
I should see that total number of products I want to buy is 2
Andmy order amount is $1600
```
Que l'on pourrait traduire dans un langage plus formel comme ceci :
```txt
Feature: checkout process
In order to buy products
As a customer
I want to be able to buy several products
Scenario:
Given I have product with $600 price in my cart
And I have product with $1000 price
When I go to checkout process
Then I should see that total number of products is 2
And my order amount is $1600
```
Certains pronoms, adverbes et verbes sont en fait des mots-clés qui vont se répéter d'un scénarion à l'autre.
Les auteurs du logiciel de BDD **Cucumber**(https://cucumber.io/) ont défini un langage appelé **Gherkin**(https://cucumber.io/docs/gherkin),
qui est composé de 11 mots-clés, que l'on peut traduire dans de nombreuses langues.
### Utilisation de `Gherkin` avec `codeception`
Les fonctionnalités en *langue naturelle* sont décrites dans des fichiers `feature` que `codeception` peut créer pour nous :
```bash
vendor/bin/codecept g:feature Acceptance create_paste
```
On voit que le fichier est créé dans le même dossier que les tests d'accepation (`Accepatnce`). Voici le contenu du ficheir `create_paste.faeture` :
```text
Feature: create_paste
In order to ...
As a ...
I need to ...
Scenario: try create_paste
```
On peut compléter notre scénario :
```yml
Feature: create_paste
In order to create a new shared paste
As an ordinary user
I need to enter a text and get an url to sahre
Scenario: register a text as a shared paste
Given I have the text "Ceci n'est pas une pipe."
When I go to frontpage of PrivateBin
Then I should enter my text in an input text area
And send my text to application
And get an url to share and retriev my text
```
Et maintenant on peut déjà le jouer :
```bash
vendor/bin/codecept dry-run Acceptance create_paste.feature
vendor/bin/codecept gherkin:snippets Acceptance create_paste.feature
```
La seconde ligne, nous donne les tests à ajouter dans le fichier `tests/Support/AcceptanceTester.php`, voici le programme généré :
```php
<?php
declare(strict_types=1);
namespace Tests\Support;
use Codeception\Attribute\Given;
use Codeception\Attribute\When;
use Codeception\Attribute\Then;
/**
* Inherited Methods
* @method void wantTo($text)
* @method void wantToTest($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause($vars = [])
*
* @SuppressWarnings(PHPMD)
*/
class AcceptanceTester extends \Codeception\Actor
{
use _generated\AcceptanceTesterActions;
/**
* Define custom actions here
*/
/**
* @Given I have the text :arg1
*/
public function iHaveTheText($arg1)
{
throw new \PHPUnit\Framework\IncompleteTestError("Step `I have the text :arg1` is not defined");
}
/**
* @When I go to frontpage of PrivateBin
*/
public function iGoToFrontpageOfPrivateBin()
{
throw new \PHPUnit\Framework\IncompleteTestError("Step `I go to frontpage of PrivateBin` is not defined");
}
/**
* @Then I should enter my text in an input text area
*/
public function iShouldEnterMyTextInAnInputTextArea()
{
throw new \PHPUnit\Framework\IncompleteTestError("Step `I should enter my text in an input text area` is not defined");
}
/**
* @Then send my text to application
*/
public function sendMyTextToApplication()
{
throw new \PHPUnit\Framework\IncompleteTestError("Step `send my text to application` is not defined");
}
/**
* @Then get an url to share and retrieve my text
*/
public function getAnUrlToShareAndRetrieveMyText()
{
throw new \PHPUnit\Framework\IncompleteTestError("Step `get an url to share and retrieve my text` is not defined");
}
}
```
On peut vérifier, que la liste des tests est reconnue avec la commande : `vendor/bin/codecept gherkin:steps Acceptance`
On peut aussi lancer un test à blanc, pour constater que tous les tests sont définis : `vendor/bin/codecept dry-run Acceptance create_paste.feature`
### Ajout du code des tests fonctionnelles
On crée le corps des différentes fonctions dans le ficheir `AcceptanceTester.php` :
```php
private $msg = "";
/**
* @Given I have the text :arg1
*/
public function iHaveTheText($arg1)
{
$this->msg = $arg1;
}
/**
* @When I go to frontpage of PrivateBin
*/
public function iGoToFrontpageOfPrivateBin()
{
$this->amOnPage('/');
$this->see('Vivons heureux, vivons cachés');
}
/**
* @Then I should enter my text in an input text area
*/
public function iShouldEnterMyTextInAnInputTextArea()
{
$this->fillField('#message', $this->msg);;
}
/**
* @Then send my text to application
*/
public function sendMyTextToApplication()
{
$this->click(' Envoyer ');
$this->see('Votre paste est disponible');
}
/**
* @Then get an url to share and retrieve my text
*/
public function getAnUrlToShareAndRetrieveMyText()
{
$paste_url = $this->grabAttributeFrom('#pasteurl', 'href');
$this->amOnUrl($paste_url);
$this->see('Ce document expirera');
$this->see($this->msg, '#prettyprint');
}
```
Avant d'exécuter les tests, on validera les modifications avec la commande : `vendor/bin/codecept dry-run Acceptance create_paste.feature`
Puis on peut lancer les tests : `vendor/bin/codecept run Acceptance create_paste.feature --steps`
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment