Maintenant qu'on a vu à quoi sert Behat, il est temps de passer à la pratique...
Vous trouverez une archive contenant toutes les sources de ce billet en bas de cette page.Le plus simple à mon goût : passer par pear :
pear channel-discover pear.symfony.com
<p>pear channel-discover pear.behat.org</p>
<p>pear install behat/behat
Un petit test pour vérifier que tout s'est bien passé :
behat --version
Voici la structure initiale de mon exemple :
mkdir -p application/library tests/product
Placez-vous dans le dossier tests/product, puis tapez :
behat --init
Cela a pour effet de créer les dossiers nécessaires à votre projet :
Il est temps de démarrer. Notre client (product owner) souhaite une application dans laquelle on puisse gérer un compte bancaire : on peut consulter son solde, ajouter des sous, en retirer... et on n'a pas le droit d'être découvert.
Le fichier de fonctionnalité livré par notre client ressemble à ceci >feature/banque.feature< :
# language: fr
<p>Fonctionnalité: posséder un compte bancaire</p>
Afin de gérer les comptes bancaires des utilisateurs
En tant que client
Je dois être capable d'effectuer des opérations basique sur mon compte
Scénario: Avoir un compte bancaire valide
Etant donné que je suis un nouveau client
Alors je dois avoir "0" euros sur mon compte
Scénario: Retirer de l'argent sur mon compte
Etant donné que je suis un client
Et que je possède "50" euros sur mon compte
Quand je retire "10" euros
Alors je dois avoir "40" euros sur mon compte
Plan du Scénario: Ajouter de l'argent sur mon compte
Etant donné que je suis un client
Et que je possède "<soldeInitial>" euros sur mon compte
Quand je dépose "<montant>" euros
Alors je dois avoir "<soldeFinal>" euros sur mon compte
Exemples:
| soldeInitial | montant | soldeFinal |
| 0 | 10 | 10 |
| 15 | 5 | 20 |
| 35 | 5 | 40 |
Scénario: Interdire les découverts
Etant donné que je suis un client
Quand j'essaye de retirer plus d argent que je n en ai sur mon compte
Alors j'ai un message d erreur "Vous ne pouvez pas être à découvert"
Le product owner sait ce qu'il veut, il nous a même donné des exemples pour mieux nous orienter dans notre développement.
Notez au passage le commentaire "# language: fr" au début du fichier. Il indique que notre fonctionnalité est décrite en français.
Il va être temps de lancer behat. Placez-vous dans le dossier tests/product/feature, puis tapez simplement :
behat --lang=fr
On commence par un rappel de la fonctionnalité et des scénarios testés.
S'il y avait eu des erreurs, le texte aurait été écrit en rouge, et si tout avait été ok, il serait vert. Là le texte est orange : il n'a pas encore de signification par rapport à notre produit.
On a ensuite des informations sur les tests :
Toutes nos étapes sont en attente de définition. En effet, on n'a rien qui fait le lien entre les scénarios (les souhaits du product owner) et notre produit (le code source). C'est là que Behat va être à mon sens magique : il nous fournit le code PHP nécessaire pour créer ce lien, avec pour chaque phrase :
Voici donc la dernière étape du traitement du résultat de la commande :
Behat nous fourni le code a copier-coller vers la classe qui gère notre contexte principal, à savoir la classe FeatureContext contenue dans /features/bootstrap/FeatureContext.php. Allons -y : copiez le code dans le fichier
Vous pouvez constater que chaque méthode lance une exception de type PendingException. Cela signifie qu'il va falloir modifier ces méthodes pour les relier à notre application.
Pour vous simplifier la vie, je vous propose de télécharger directement le code nécessaire au bon fonctionnement de ces tests : Account.php, à placer dans application/library. Sinon libre à vous d'écrire le code qui correspondra à l'application ; en soit, peu importe le code, ce qui nous intéresse c'est le produit ;-)
Nous allons maintenant convertir le texte (langue naturelle) en code (source) :
<!--?php use Behat\Behat\Context\ClosuredContextInterface, Behat\Behat\Context\TranslatedContextInterface, Behat\Behat\Context\BehatContext, Behat\Behat\Exception\PendingException; use Behat\Gherkin\Node\PyStringNode, Behat\Gherkin\Node\TableNode; require_once 'PHPUnit/Autoload.php'; require_once 'PHPUnit/Framework/Assert/Functions.php'; require_once __DIR__ . '/../../../../application/library/Account.php'; use \MyApp\Account as Account; /** * Features context. */ class FeatureContext extends BehatContext { /** * Testes account * * @var \MyApp\Account */ private $_account; /** * Contains the last exception * * @var \Exception */ private $_lastException; /** * @Given /^que je suis un nouveau client$/ */ public function queJeSuisUnNouveauClient() { $this--->_account = new Account;
}
/**
* @Then /^je dois avoir "([^"]*)" euros sur mon compte$/
*/
public function jeDoisAvoirEurosSurMonCompte($balance) {
assertEquals($balance, $this->_account->getBalance());
}
/**
* @Given /^que je suis un client$/
*/
public function queJeSuisUnClient() {
if(is_null($this->_account)) {
$this->_account = new Account;
}
}
/**
* @Given /^que je possède "([^"]*)" euros sur mon compte$/
*/
public function queJePossedeEurosSurMonCompte($balance) {
$this->_account->setBalance($balance);
}
/**
* @Given /^je retire "([^"]*)" euros$/
*/
public function jeRetireEuros($amount) {
$this->_account->takeMoney($amount);
}
/**
* @Given /^je dépose "([^"]*)" euros$/
*/
public function jeDeposeEuros($amount) {
$this->_account->addMoney($amount);
}
/**
* @Given /^j\'essaye de retirer plus d argent que je n en ai sur mon compte$/
*/
public function jEssayeDeRetirerPlusDArgentQueJeNEnAiSurMonCompte() {
try {
$this->_account->setBalance(50);
$this->_account->takeMoney(100);
} catch (\Exception $e) {
$this->_lastException = $e;
}
}
/**
* @Given /^j\'ai un message d erreur "([^"]*)"$/
*/
public function jAiUnMessageDErreur($message) {
assertEquals($message, $this->_lastException->getMessage());
}
}
Vous constaterez que :
Le suspense est à son comble : notre code correspond t--il au souhait du client quant à son produit ?
behat --lang=fr
Si besoin voici une archive contenant l'ensemble de ce projet : Découverte de behat - jour 2.zip.
Notre client (product owner) peut désormais s'assurer à tout moment que son produit est valide.Bien plus, il va pouvoir ajuster son produit au fur et à mesure des sprints en vous décrivant clairement son besoin : fini les specs de 500 pages, c'est le product owner qui est maître de son produit ! Et cela grâce à Behat.
La prochaine fois on verra comment mieux organiser son code : sous-contextes, configuration... et surtout comment tester une application web, grâce à Mink. mais en attendant, toute remarque / commentaire est le bienvenu ;-)
Je vous rappelle qu'une cheat sheet pour behat est disponible.
© Jean-François Lépine, 2013 - 2024