Il s’agit d’un bug dans atoum qui ne se produit que sous Windows et uniquement avec le code contenu dans la branche « autoloader ».

Il y a quelques jours, j’ai cherché une solution pour rendre insensible à la casse le mécanisme d’auto-chargement de classe d’atoum (l’objectif recherché ainsi que les raisons historiques du fonctionnement actuel sont hors de propos).

Pour y parvenir, j’ai donc fait en sorte que la méthode atoum\autoloader::addDirectory() parcourt chaque répertoire qu’elle reçoit en argument pour construire un tableau de correspondance entre un nom de classe et un chemin d’accès sur le système de fichier, tableau qui est ensuite utilisé pour localiser et charger à l’aide de require le fichier contenant la classe requise par le fonctionnement du programme.

Évidemment, ce parcourt a un impact sur les performances, et dans le cas d’atoum, il est très important, car chaque méthode de test est exécutée par défaut dans un processus PHP différent.

En conséquence, avec une implémentation trop naïve de ce mécanisme, les répertoires concernés sont donc parcourus pour chaque méthode de test, ce qui est coûteux et surtout complètement inutile.

J’ai donc modifié le moteur qui exécute chaque méthode de test de façon à ce qu’il transmette le tableau évoqué précédemment au processus PHP concerné pour supprimer ce trop coûteux et parfaitement inutile parcours de répertoire.

Pour cela, j’ai tout simplement passé en argument à la fonction var_export() l’objet responsable de l’autochargement de classe dans atoum et j’ai envoyé le résultat au processus PHP via un pipeline ouvert à l’aide de la fonction proc_open().

Sous UNIX, tout a alors fonctionné sans le moindre problème et j’ai obtenu des performances tout à fait similaires à celles obtenues avec l’ancienne version du mécanisme d’autochargement de classe.

Par contre, les tests effectués par thehawk (que je remercie grandement encore une fois pour sa patience), l’un des contributeurs à atoum utilisant Windows, ont révélé un problème.

En effet, il obtient systématiquement le message d’erreur suivant lorsqu’il exécute la commande php ./bin/atoum --test-it permettant d’exécuter l’intégralité des tests unitaires de atoum :

ERROR: PHP Parse error:  syntax error, unexpected ''O:26:"mageekguy\atoum\autoloa' (T_ENCAPSED_AND_WHITESPACE), expecting ')' in - on line 1

Évidemment, nous avons fait quelques vérifications et je peux déjà vous dire que :

  • Le code transmis au processus PHP est bien un code PHP syntaxiquement valide, car l’utilisation de la commande php -l l’a confirmé.
  • Le code transmis au processus PHP est parfaitement exécutable et génère le résultat escompté sous Windows comme sous UNIX lorsqu’il est mis dans un fichier et exécuté en ligne de commande à  l’aide de php path/to/file.php.
  • Le code généré sous Windows et envoyé au processus PHP s’exécute sans le moindre problème sous UNIX, si ce n’est qu’évidemment les chemins d’accès aux classes sont invalides et que cela provoque une erreur lors de l’inclusion des fichiers.
  • Le responsable de l’erreur de syntaxe semble se cacher dans le contenu de la propriété classes de la classe atoum\autoloader.

Pour obtenir ces informations, j’ai notamment remplacé l’appel à la fonction var_export() par un appel à la fonction serialize().

J’ai de plus implémenté l’interface serializable au niveau de la classe atoum\autoloader afin de pouvoir contrôler finement ce qu’il se passe lorsqu’une de ses instances est passée en argument à serialize().

Pour autant, je n’ai aucune idée de l’origine du problème qui semble être lié à l’utilisation de proc_open() puisque l’erreur de syntaxe ne se manifeste que dans ce contexte.

Je subodore que les \ utilisés dans les chemins de fichier sous Windows sont responsable, mais je n’ai pas réussi à en avoir la preuve.

Et j'ai encore plus étrange, si jamais cela ne vous suffit pas, puisque l'ajout d'un print_r($this->classes) dans le code de la méthode atoum\autoloader::serialize() fait disparaître l'erreur de syntaxe.

Donc, si vous êtes amateur de prise de tête, que vous êtes sous Windows et que vous plonger dans les rouages de atoum ne vous effraye pas le moins du monde, je vous invite à forker le dépôt d’atoum, à vous positionner sur la branche « autoloader » et à tenter de résoudre cette énigme.

Et si d’aventure vous trouvez la solution et surtout l’explication, je vous invite à la partager ici en commentaire ou bien en tout autre lieu que vous jugerez adéquat.

Et si vous voulez des informations supplémentaires, je vous propose de me les demander soit en commentaire, soit plus simplement sur le canal IRC officiel d’atoum, à savoir ##atoum sur le réseau Freenode.

Et j’ai failli oublier le plus important : <privatejoke>pour ceux qui ne saurait pas encore, atoum est un framework de test unitaire, simple, moderne et intuitif !</privatejoke>