Contactez-nous
Kitpages
17 rue de la Frise
38000 Grenoble
tel : 04 58 00 33 81
Behat PHP code coverage
Introduction
Ce petit tutoriel explique comment mettre en place le code coverage sur des tests Behat, dans notre cas sur une application Symfony 2 (et plus précisément la distribution api-platform)
Prérequis
Dans ce tutoriel nous partons du principe que vous avez déjà mis en place vos tests Behat et que vous souhaitez simplement profiter de la couverture de code.
Pour cela nous allons utiliser l'excellente librairie php-code-coverage de Sebastian Bergmann.
Veuillez toutefois noter que l'installation de xdebug est de dehors du périmètre de ce tutoriel, mais google est votre ami.
Installation via composer :
composer require phpunit/php-code-coverage
Mise en contexte
Pour ce tutorial nous utiliserons comme context de test une API Rest de gestion simplifié des Users.
Voici la configuration behat.yml qui nous utiliserons :
default: calls: error_reporting: 16383 # E_ALL & ~E_USER_DREPRECATED suites: default: contexts: - FeatureContext: { doctrine: "@doctrine" } - Behat\MinkExtension\Context\MinkContext - Sanpi\Behatch\Context\RestContext - Sanpi\Behatch\Context\JsonContext extensions: Behat\Symfony2Extension: kernel: env: "test" debug: "true" Behat\MinkExtension: base_url: "http://localhost/" sessions: default: symfony2: ~ Sanpi\Behatch\Extension: ~
Et voici la feature Behat associé :
Feature: User I need to be able to retrieve, create, update and delete users trough the API. # "@createSchema" creates a temporary SQLite database for testing the API @createSchema Scenario: Create a user When I send a "POST" request to "/users" with body: """ {"email": "test@example.com", "name": "Tester"} """ Then the response status code should be 201 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json" And the JSON should be equal to: """ { "@context": "/contexts/User", "@id": "/users/1", "@type": "http://schema.org/Person", "email": "test@example.com", "memberOf": null, "name": "Tester" } """ Scenario: Create a user with invalid email When I send a "POST" request to "/users" with body: """ {"email": "test@example", "name": "Tester"} """ Then the response status code should be 400 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json" And the JSON node "root->hydra:description" should contain "email: This value is not a valid email address." Scenario: Get single user When I send a "GET" request to "/users/1" Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json" And the JSON should be equal to: """ { "@context": "/contexts/User", "@id": "/users/1", "@type": "http://schema.org/Person", "email": "test@example.com", "memberOf": null, "name": "Tester" } """ Scenario: Get single user not exist When I send a "GET" request to "/users/10" Then the response status code should be 404 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json" And the JSON node "root->hydra:description" should be equal to "Not Found" @dropSchema Scenario: Get user list When I send a "GET" request to "/users" Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json" And the JSON should be equal to: """ { "@context": "/contexts/User", "@id": "/users", "@type": "hydra:PagedCollection", "hydra:totalItems": 1, "hydra:itemsPerPage": 30, "hydra:firstPage": "/users", "hydra:lastPage": "/users", "hydra:member": [ { "@id": "/users/1", "@type": "http://schema.org/Person", "email": "test@example.com", "memberOf": null, "name": "Tester" } ] } """
Création du context Behat
Nous allons créer un contexte Behat dédié au coverage, pour cela il suffit de récupérer la classe CoverageContext ici : https://gist.github.com/eliecharra/9c8b3ba57998b50e14a6 et de la recopier dans votre projet parmis vos contextes.
<?php use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; /** * Created by PhpStorm. * User: elie * Date: 01/09/15 * Time: 11:29 */ class CoverageContext implements Context { /** * @var PHP_CodeCoverage */ private static $coverage; /** @BeforeSuite */ public static function setup() { $filter = new PHP_CodeCoverage_Filter(); $filter->addDirectoryToBlacklist(__DIR__ . "/../../vendor"); $filter->addDirectoryToWhitelist(__DIR__ . "/../../src"); self::$coverage = new PHP_CodeCoverage(null, $filter); } /** @AfterSuite */ public static function tearDown() { $writer = new PHP_CodeCoverage_Report_HTML(); $writer->process(self::$coverage, __DIR__ . "/../../app/logs/coverage"); } private function getCoverageKeyFromScope(BeforeScenarioScope $scope) { $name = $scope->getFeature()->getTitle() . '::' . $scope->getScenario()->getTitle(); return $name; } /** * @BeforeScenario */ public function startCoverage(BeforeScenarioScope $scope) { self::$coverage->start($this->getCoverageKeyFromScope($scope)); } /** @AfterScenario */ public function stopCoverage() { self::$coverage->stop(); } }
Au besoin vous pouvez modifier les lignes suivantes pour coller à votre environnement.
Ces paramètres ont vocation à être variabilisés
// Modifier ces lignes pour ajouter / exclure des dossiers au coverage $filter->addDirectoryToBlacklist(__DIR__ . "/../../vendor"); $filter->addDirectoryToWhitelist(__DIR__ . "/../../src"); //Modifier cette ligne pour changer le type de sortie générée $writer = new PHP_CodeCoverage_Report_HTML(); // Modifier cette ligne pour rediriger la sortie du résultat du coverage $writer->process(self::$coverage, __DIR__ . "/../../app/logs/coverage");
On va ensuite rajouter un profil Behat avec le contexte CoverageContext que l'on viens de créer.
Dans votre fichier de config behat.yml, créez un nouveau profil :
coverage: suites: default: contexts: - FeatureContext: { doctrine: "@doctrine" } - Behat\MinkExtension\Context\MinkContext - Sanpi\Behatch\Context\RestContext - Sanpi\Behatch\Context\JsonContext - CoverageContext # On rajoute CoverageContext aux contextes déjà existants
Tests
On peux maintenant lancer nos test soit avec, soit sans coverage en utilisant ces deux profils.
bin/behat
et
bin/behat --profile coverage
Commentaires
Note : on ne peut plus ajouter de commentaire sur ce site