Voici l'avant dernier billet de la série sur la prise en main de Behat. Pour rappel, on a vu :
Allons un peu plus loin :-)
Assez rapidement on se retrouve à devoir gérer des cas particuliers, par exemple :
Quand je suis à découvert
<p>Alors le bouton "retirer de l'argent" doit être désactivé
On sort des cas classiques de Mink. Comment faire ?
La solution consiste à développer nous même ce comportement :
/**
* @Then /^le bouton "([^"]*)" doit être désactivé$/
*/
public function leBoutonDoitEtreDesactive($button)
{
throw new PendingException();
}
On commence par récupérer notre page à partir de l'objet de session:
$page = $this->getSession()->getPage();
Ensuite on va récupérer l'élément html concerné. Il existe différente manière de faire cela. Le plus simple dans notre cas consiste à passer par un des raccourcis de sélection de Mink : findButton(libellé | id | nom)...
$element = $page->findButton($button);
Si l'élément html n'est pas trouvé, on va lever une exception, sinon on va continuer en faisant une assertion simple : l'élément doit avoir l'attribut "disabled". Ce qui donne au final :
$page = $this->getSession()->getPage();
$element = $page->findButton($button);
if (null === $element) {
throw new Behat\Mink\Exception\ElementNotFoundException(
$this->getSession(), 'element', 'css', $button
);
}
<p>assertEquals(true, $element->hasAttribute('disabled'));
Au passage, remarquez qu'il s'agit d'une assertion classique de PHPUnit, mais en mode fonction. Pour cela on aura bien entendu ajouté au début de notre fichier :
require_once 'PHPUnit/Autoload.php';
<p>require_once 'PHPUnit/Framework/Assert/Functions.php';
Je vous laisse regarder la documentation ou la feuille d'astuce pour Mink pour plus d'informations. Sachez juste qu'on peut faire pas mal de chose, comme exécuter du JavaScript par exemple (avec $session->evaluateScript() ) ;-) ...
Jusqu'ici on a systématiquement mis notre code dans le fichier FeatureContext.php. C'est pas l'idéal : on va très vite se retrouver avec un fichier énorme et imbuvable. Il nous suffit de découper notre contexte en sous-contextes. Tout se fait dans le constructeur du contexte principal :
class FeatureContext extends BehatContext
{
public function __construct(array $parameters) {
$this->useContext('mink', new MinkContext($parameters));
$this->useContext('example1', new MyExample1Context($parameters));
}
On a donc isolé le contexte de Mink pour en faire un sous-contexte, et on a plus ajouté le nôtre ('example1').
L'utilisation des contextes est assez simple. Chaque sous-contexte a un nom (ici 'mink' et 'behat'), que l'on peut utiliser pour les récupérer :
Par exemple :
$session = $this->getMainContext()->getSubContext('mink')->getSession();
On va donc créer le fichier MyExample1Context.php :
class MyExample1Context extends BehatContext
{
/**
* @Then /^le bouton "([^"]*)" doit être désactivé$/
*/
public function leBoutonDoitEtreDesactive($button) {
$session = $this->getMainContext()->getSubContext('mink')->getSession();
$page = $session->getPage();
$element = $page->findButton($button);
if (null === $element) {
throw new Behat\Mink\Exception\ElementNotFoundException(
$this->getSession(), 'element', 'css', $button
);
}
assertEquals(true, $element->hasAttribute('disabled'));
}
}
Et voilà, nous voici avec un code découpé et des fichiers plus spécialisés.
Comme pour les tests unitaires, il est possible d'exécuter du code à certaines phases du déroulement du tests. Il suffit d'utiliser des annotations :
/**
* @BeforeSuite
*/
<p>public static function prepare(SuiteEvent $event)</p>
{
// (...)
}
les déclencheurs disponibles sont :
Un dessin valant mieux qu'un long discours, le plus simple est de regarder ici.
On voit qu'on a quand même peu de limites avec Mink et Behat. Bien plus, on peut même l'intégrer à une PIC (Jenkins, Hudson...). C'est d'ailleurs ce qu'on verra dans le prochain billet, qui sera le dernier de la série ^^
=> Juste par curiosité : j'utilise exclusivement Sahi pour mes tests. Beaucoup de monde utilise Selenium ? C'est mieux ? Vous avez des avis ?© Jean-François Lépine, 2013 - 2024