WordCamp Montreal 2019

@remyperona

PRÉPARER SON PROJET

À L'ÉCRITURE DE

TESTS UNITAIRES &

D'INTÉGRATION

WordCamp Montreal 2019

@remyperona

RAPPEL

WordCamp Montreal 2019

@remyperona

RAPPEL

TEST UNITAIRE

Teste le retour de chaque unité (fonction ou méthode) afin de garantir qu'il est le résultat attendu.

Ce test est exécuté en complète isolation, sans dépendance au système ou externalités

WordCamp Montreal 2019

@remyperona

RAPPEL

TEST D'INTÉGRATION

Teste le comportement du code une fois intégré dans le système : ici, WordPress

WordCamp Montreal 2019

@remyperona

RAPPEL

AVANTAGES

  • Apporte de la confiance dans votre travail et dans votre code
  • Gain de temps (sur le long terme)
  • Isole les problèmes potentiels
  • Etabli un point de comparaison pour les futurs changements

WordCamp Montreal 2019

@remyperona

PRÉREQUIS

WordCamp Montreal 2019

@remyperona

PRÉREQUIS

ENVIRONNEMENT DE DÉVELOPPEMENT LOCAL

Local by Flywheel

https://localbyflywheel.com

WordCamp Montreal 2019

@remyperona

PRÉREQUIS

COMPOSER

Gestionnaire de dépendances pour PHP

https://getcomposer.org

WordCamp Montreal 2019

@remyperona

ORGANISATION

WordCamp Montreal 2019

@remyperona

ORGANISATION

– Racine Projet

  |– composer.json

  |– phpunit.xml

  |– tests/

        |– Unit/

            |– bootstrap.php

        |– Integration/

            |– bootstrap.php

            |– phpunit.xml

WordCamp Montreal 2019

@remyperona

ORGANISATION

COMPOSER.JSON

  • Fichier de configuration de composer
  • A la racine du projet
  • Définit les dépendances du projet
  • Définit l'autoloading

WordCamp Montreal 2019

@remyperona

ORGANISATION

DÉPENDANCES POUR TESTS

  • PHPUnit : Framework de test pour PHP (https://phpunit.de/)
  • Brain Monkey : Outil pour simplifier l'écriture de tests pour des projets WordPress
    (https://brain-wp.github.io/BrainMonkey/)

WordCamp Montreal 2019

@remyperona

ORGANISATION

PHPUNIT.XML

  • Fichier de configuration pour PHPUnit
  • Un fichier par type de test (donc 2 fichiers)
  • Un à la racine pour les tests unitaires
  • Un dans le dossier tests/Integration

 

WordCamp Montreal 2019

@remyperona

ORGANISATION

BOOTSTRAP.PHP

  • Fichier d'initialisation des tests
  • Vérification de la version de PHP
  • Chargement de l'autoloader de composer

 

WordCamp Montreal 2019

@remyperona

CONFIGURATION

WordCamp Montreal 2019

@remyperona

CONFIGURATION

PHPUNIT.XML UNITAIRE

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
         bootstrap="tests/Unit/bootstrap.php">
    <testsuites>
        <testsuite name="unit">
            <directory suffix=".php">./tests/Unit/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">.</directory>
        </whitelist>
    </filter>
</phpunit>

WordCamp Montreal 2019

@remyperona

CONFIGURATION

PHPUNIT.XML INTEGRATION

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
		 bootstrap="bootstrap.php">
	<testsuites>
		<testsuite name="integration">
			<directory suffix=".php">.</directory>
		</testsuite>
	</testsuites>
</phpunit>

WordCamp Montreal 2019

@remyperona

CONFIGURATION

COMPOSER.JSON

{
    "name": "wp-media/wp-rocket",
    "require": {
	"php": "^5.6|^7"
    },
    "require-dev": {
	"brain/monkey": "^2.2",
	"phpunit/phpunit": "~5.7.9",
    },
    "autoload-dev": {
	"psr-4": {
	    "WP_Rocket\\Tests\\Unit\\": "tests/Unit",
	    "WP_Rocket\\Tests\\Integration\\": "tests/Integration"
	}
    }
}

WordCamp Montreal 2019

@remyperona

CONFIGURATION

QUELQUES COMMANDES

// Installation des dépendances via composer
// Génération du contenu à autoload
composer install

// Exécution des tests unitaires
vendor/bin/phpunit --testsuite unit --colors=always
// Exécution des tests d'intégration
vendor/bin/phpunit --testsuite integration --colors=always --configuration tests/phpunit/integration/phpunit.xml

WordCamp Montreal 2019

@remyperona

CONFIGURATION

COMPOSER.JSON (MàJ)

{
    "name": "wp-media/wp-rocket",
    "require": {
	"php": "^5.6|^7"
    },
    "require-dev": {
	"brain/monkey": "^2.2",
	"phpunit/phpunit": "~5.7.9",
    },
    "autoload-dev": {
	"psr-4": {
	    "WP_Rocket\\Tests\\Unit\\": "tests/Unit",
	    "WP_Rocket\\Tests\\Integration\\": "tests/Integration"
	}
    },
    "scripts": {
        "test-unit": "\"vendor/bin/phpunit\" --testsuite unit --colors=always",
        "test-integration": "\"vendor/bin/phpunit\" --testsuite integration --colors=always --configuration tests/phpunit/integration/phpunit.xml"
  }
}

WordCamp Montreal 2019

@remyperona

CONFIGURATION

NOUVELLES COMMANDES

// Exécution des tests unitaires
composer test-unit
// Exécution des tests d'intégration
composer test-integration

WordCamp Montreal 2019

@remyperona

CONFIGURATION

WordPress TEST SUITE

Script pour installer tout le nécessaire pour Local by Flywheel (instructions incluses):

https://gist.github.com/keesiemeijer/a888f3d9609478b310c2d952644891ba

WordCamp Montreal 2019

@remyperona

CONFIGURATION

WordPress TEST SUITE

  • Packages installés: PHPUnit, curl wget, rsync, git, subversion and composer
  • WordPress est installé dans le dossier /tmp/wordpress pour PHPUnit
  • La WordPress test suite est installé dans le dossier /tmp/wordpress-tests-lib
  • Les chemins de WordPress et de la test suite sont ajoutés au fichier ~/.bashrc en tant que variables d'environnement

WordCamp Montreal 2019

@remyperona

CONFIGURATION

BOOSTRAP TESTS UNITAIRES (PARTIE 1)

if (version_compare(phpversion(), '5.6.0', '<')) {
    die('WP Rocket Plugin Unit Tests require PHP 5.6 or higher.');
}

define('WP_ROCKET_PLUGIN_TESTS_ROOT', __DIR__);
define('WP_ROCKET_PLUGIN_ROOT', dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR);

$rocket_common_autoload_path = WP_ROCKET_PLUGIN_ROOT . 'vendor/';

WordCamp Montreal 2019

@remyperona

CONFIGURATION

BOOSTRAP TESTS UNITAIRES (PARTIE 2)

if (! file_exists($rocket_common_autoload_path . 'autoload.php')) {
    die('Whoops, we need Composer before we start running tests.  Please type: `composer install`.  When done, try running `phpunit` again.');
}

require_once $rocket_common_autoload_path . 'autoload.php';

unset($rocket_common_autoload_path);

WordCamp Montreal 2019

@remyperona

CONFIGURATION

BOOSTRAP TESTS D'INTÉGRATION

if (version_compare(phpversion(), '5.6.0', '<')) {
    die('WP Rocket Plugin Integration Tests require PHP 5.6 or higher.');
}

// Define testing constants.
define('WP_ROCKET_PLUGIN_TESTS_ROOT', __DIR__);
define('WP_ROCKET_PLUGIN_ROOT', dirname(dirname(__DIR__)));

WordCamp Montreal 2019

@remyperona

CONFIGURATION

/**
 * Gets the WP tests suite directory
 *
 * @return string
 */
function WPRocketPluginGetWPTestsDir()
{
    $tests_dir = getenv('WP_TESTS_DIR');

    // Travis CI & Vagrant SSH tests directory.
    if (empty($tests_dir)) {
        $tests_dir = '/tmp/wordpress-tests-lib';
    }
    // If the tests' includes directory does not exist, try a relative path to Core tests directory.
    if (! file_exists($tests_dir . '/includes/')) {
        $tests_dir = '../../../../tests/phpunit';
    }
    // Check it again. If it doesn't exist, stop here and post a message as to why we stopped.
    if (! file_exists($tests_dir . '/includes/')) {
        trigger_error('Unable to run the integration tests, as the WordPress test suite could not be located.', E_USER_ERROR);  // @codingStandardsIgnoreLine.
    }
    // Strip off the trailing directory separator, if it exists.
    return rtrim($tests_dir, DIRECTORY_SEPARATOR);
}

WordCamp Montreal 2019

@remyperona

CONFIGURATION

$rocket_tests_dir = WPRocketPluginGetWPTestsDir();

// Give access to tests_add_filter() function.
require_once $rocket_tests_dir . '/includes/functions.php';

/**
 * Manually load the plugin being tested.
 */
function rocket_manually_load_plugin()
{
    require WP_ROCKET_PLUGIN_ROOT . '/wp-rocket.php';
}
tests_add_filter('muplugins_loaded', 'rocket_manually_load_plugin');

require_once $rocket_tests_dir . '/includes/bootstrap.php';

unset($rocket_tests_dir);

WordCamp Montreal 2019

@remyperona

EN ACTION

WordCamp Montreal 2019

@remyperona

EN ACTION

TESTS UNITAIRES

composer test-unit
> "vendor/bin/phpunit" --testsuite unit --colors=always
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.3.2 with Xdebug 2.7.0RC2
Configuration: /app/public/wp-content/plugins/wp-rocket/phpunit.xml.dist

...............                                                   15 / 15 (100%)

Time: 1.48 seconds, Memory: 14.00MB

OK (15 tests, 15 assertions)

WordCamp Montreal 2019

@remyperona

EN ACTION

TESTS D'INTÉGRATION

composer test-integration
> "vendor/bin/phpunit" --testsuite integration --colors=always --configuration tests/Integration/phpunit.xml.dist
Installing...
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.3.2 with Xdebug 2.7.0RC2
Configuration: /app/public/wp-content/plugins/wp-rocket/tests/Integration/phpunit.xml.dist

..............                                                    14 / 14 (100%)

Time: 1.13 seconds, Memory: 36.50MB

OK (14 tests, 14 assertions)

WordCamp Montreal 2019

@remyperona

INTÉGRATION CONTINUE

WordCamp Montreal 2019

@remyperona

INTÉGRATION CONTINUE

https://travis-ci.org/

  • Outil d'intégration continue
  • Lien avec un repository GitHub
  • Configuration via .travis.yml

 

WordCamp Montreal 2019

@remyperona

INTÉGRATION CONTINUE

.travis.yml (partie 1)

sudo: false
language: php
branches:
  only:
  - master
  - develop
  - /branch-.*$/
cache:
  directories:
  - vendor
  - "$HOME/.composer/cache"

WordCamp Montreal 2019

@remyperona

INTÉGRATION CONTINUE

.travis.yml (partie 2)

matrix:
  include:
  - php: 7.3
    env: WP_VERSION=latest
  - php: 7.2
    env: WP_VERSION=latest
  - php: 7.2
    env: WP_VERSION=4.7.13
  - php: 7.1
    env: WP_VERSION=latest
  - php: 7.0
    env: WP_VERSION=latest
  - php: 5.6
    env: WP_VERSION=latest

WordCamp Montreal 2019

@remyperona

INTÉGRATION CONTINUE

.travis.yml (partie 3)

before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- composer install --no-progress
- |
  if [[ ! -z "$WP_VERSION" ]] ; then
    bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
  fi
script:
- composer test-unit
- composer test-integration

WordCamp Montreal 2019

@remyperona

WordCamp Montreal 2019

@remyperona

QUESTIONS ?

Rémy Perona

Lead développeur de WP Rocket chez WP Media

Préparer son projet à l’écriture de tests unitaires et d’intégrations

By Remy Perona

Préparer son projet à l’écriture de tests unitaires et d’intégrations

  • 2,823