Vous avez une mise en production hyper importante aujourd'hui. Votre client (interne) vous a mis la pression et vous avez dû raccourcir les délais pour être à l'heure. Vous packagez votre release d'application, vous la passez sur l'environnement de tests fonctionnels, tout se passe bien. Vous la passez sur l'environnement d'intégration et tout se passe bien, mais vous noter un ou deux comportement étrange, sans gravité, bizarre. Vous décidez de la passer en pré-production, et là ... Tout plante ! L'application ne se lance même plus et c'est la page blanche...

Pourquoi ?

Vous investiguez et vous découvrez que l'environnement de pré-production n'est absolument pas à jour (choisissez une ou plusieurs lignes dans la liste) :

- mauvaise version de PHP

- mauvaise version de votre framework MVC habituel

- mauvaise version de votre librairie de composants interne partagée

- extension SOAP manquante

- répertoire de log inexistant sur la machine (votre application ne le crée pas si il n'existe pas...)

- connexion à la base de données non fonctionnelle car les identifiants ont changé...

- ...

La catastrophe.

Vous décidez donc de regarder sur la machine de production, et bien sûr vous faites les mêmes découvertes...

Résultat: votre mise en production est décalée de 1/2 journée, vous mettez la pression aux équipes plateformes pour qu'elles mettent tous les environnements à jour, et vous prenez un savon par votre client (interne) qui vous prend pour un amateur.

Comment éviter cela ?

Vous pouvez acheter le dernier outils à la mode qui compte XXXX k€ et qui vérifie tout, mais c'est long à mettre en place et surtout ca coûte très cher dans votre budget (ou celui des équipes plateformes), en plus les tests réalisés seront soit très générique soit il faudra peut être un peu tordre l'outils pour faire certaines vérifications un peu spécifique à votre application (test de la connexion mysql, vérification de la version de votre framework préféré...)

Une autre solution consiste à réaliser un petit script, PHP, qui va faire tous les tests spécifiques qui vous intéresse et vous faire un rapport directe. Appellons le "PHP Sanity Check(er)".

Une contrainte cependant : tout doit tenir dans un script (1 fichier) et aucune installation ou dépendance autre que le dépôt du fichier dans l'arborescence du serveur web ne doit être nécessaire. En effet, il serait dommage que votre script ne fonctionne qu'avec une dépendance à la librairie TUTU et que cette librairie ne soit pas installée sur la plateforme (qui le vérifierait ?)

Le script peut être très simple et faire une série de version_compare(), de stream_socket_client(), de file_exists(), extension_loaded(), de vérification de variable $_SERVER.... c'est du PHP, vous pouvez donc tout faire ;), par contre, avant d'utiliser mysql(i)_connect, vérifiez (via un test dans le script) que l'extension mysql(i) est bien chargée !

Oui mais j'ai plusieurs applications croisées avec plusieurs environnements, ce qui m'oblige à faire des suites de tests différentes, comment faire ? je duplique le script pour chacun des cas et je maintiens les différentes versions ? une usine à gaz !

Non.

Vous êtes malin.

Vous développez donc une seule fois, vous faites des fichiers de configuration spécifiques à chacun des applications/environnements et "vous générez un script spécifique pour chacun des cas".

Comment ?

Grâce, par exemple à Phing et Phar.

Vous créez votre script générique qui prend une liste de tests écrit dans un fichier de configuration (par exemple xml). Voici un exemple de fichier :

<?xml version='1.0' encoding='iso-8859-1' ?>

<psc>
	<test info="PHP Version" type="php:minimum-version" arg1="5.0.0"/>
	<test info="Windows Platform" type="php:os" arg1="winnt"/>
	<test info="Google is Reachable" type="network:tcp-port-reachable" arg1="www.google.com" arg2="80"/>
</psc>

Votre script lit le contenu du fichier xml, en sort une liste de tests correspondant à des appels de méthodes de classes :

- Php::checkMinimumVersion('5.0.0')

- Php::checkOs('winnt')

- Network::checkTcpPortReachable('www.google.com','80')

Vous écrivez ensuite les classes Php (dans Php.php ;)) et Network (dans Network.php) qui contiennent chacunes les méthodes listées, vous pouvez bien sûr en rajouter d'autres, si elles ne sont pas listées dans le fichier de configuration elle ne seront pas utilisées.

Vous faites en sorte que chacune des méthodes lève une exception si le test ne passe pas avec un message d'erreur compréhensible sur le problème.

A l'exécution, vous récupérez le résultat d'exécution de chacune des méthodes (en faisant un try/catch par dessus) et vous affichez cela dans un tableau HTML qui va bien avec des couleurs verte et rouge.

Mais à quoi sert Phar ?

Venons-en à Phar. Phar ou encore "PHP Archive" permet de condenser plusieurs scripts PHP dans un seul fichier (.phar), il peut être compressé ou non. Le moteur PHP saura exécuter le fichier .phar comme si il était un script .php La seule différence est que le .phar contenant plusieurs fichiers php, il faut lui indiquer précisément quel est le premier script a exécuter (celui-ci pourra faire des includes des autres éventuellement).

Vous pouvez donc faire plein de fichiers/scripts/classes dans votre outils et les packager dans un seul et même fichier .phar en y embarquant même le fichier de configuration nécessaire. A l'exécution, vos scripts se comporteront comme si ils étaient dans un répertoire sur le disque et vous pourrez utiliser les includes.

Mais à quoi sert Phing ?

Phing, est un outils de scripting cross-platform (xml) écrit en PHP (port de Ant venant de Java). Il permet de décrir des batchs de commandes (systèmes souvent) à réaliser sous forme xml (ca marche donc sous windows, mac, linux...), voici ce que nous pourrions faire pour packager notre PHP sanity Checker pour générer un .phar à installer sur les plateformes pour notre application TOTO :

    <target name="package" depends="init" description="Packages the phar script to deploy on platform (use -Dsuite=<your-suite>)">
    	<delete dir="tmp/package"/>
    	<mkdir dir="tmp/package"/>
    	<mkdir dir="tmp/package/config/suites"/>
    	<copy file="config/suites/${suite}.xml" tofile="tmp/package/config/suites/default.xml"/>
    	<copy todir="tmp/package">
    		<fileset dir=".">
    			<include name="**/*.php"/>
    		</fileset>
    	</copy>
    	<phar to="tmp/check.phar">
    		<fileset dir="tmp/package">
    			<include name="**/*"/>
    		</fileset>
    	</phar>
    </target>

Pour exécuter cette liste de commandes, vous faites :

$ phing package -Dsuite=mon-application

ce qui aura pour but de packager le fichier mon-application.xml avec vos scripts php (ceux de votre outils de tests) dans un fichier tmp/check.phar.

Dernière étape, vous déployez (vous copiez) le fichier check.phar sur votre plateforme cible dans l'arborescence du serveur web, et vous accédez à ce fichier comme si il s'agissait d'un fichier .php (configurer apache pour qu'il traite les fichiers .phar comme les fichiers .php).

Des commentaires ?