- Accueil
- Programmation Web S4
- Objectifs de la séance
- Mise en place du projet
- Versionnage du projet
- Installer et configurer
Composer
- Initialiser le projet
Composer
- Création du projet dans
PhpStorm
- Installation des outils de qualité de code
- Configuration du projet
- Principe du jeu et de la réalisation
- Rock, Paper, Scissors
- Rock, Paper, Scissors, Lizard, Spock
- Généralisation et refonte
Objectifs de la séance ¶
- Installer
Composer
- Créer un nouveau projet avec
Composer
- Installer
PHPUnit
- Découvrir
PhpStorm
- Installer des outils de tests statiques dans
PhpStorm
- Installer et configurer
PHP Mess Detector
(a.k.a.PHPMD
) - Installer et configurer
PHP Coding Standards Fixer
(a.k.a.PHP CS Fixer
) - Écrire des tests unitaires
- Écrire des tests d'intégration
- Prendre en main
PHPUnit
- Utiliser des Stubs
- Utiliser des Mock objects
- Découvrir l'analyse de couverture de code
Mise en place du projet ¶
Quelques considérations liées à la configuration système de l'IUT ¶
Remarque importante
Si vous travaillez sur votre ordinateur personnel, sur Linux ou sur Windows, vous pouvez placer le répertoire « tests-conception
» du projet où bon vous semble. La partie qui suit concerne uniquement le travail sur les ordinateurs de l'IUT. Cela ne vous empêche pas d'en prendre connaissance.
Votre répertoire d'accueil « $HOME
» se trouve sur un emplacement réseau NFS, ce qui vous permet de retrouver vos fichiers quel que soit le PC du département sur lequel vous vous connectez. Symfony
utilise le sous-répertoire « var
» du projet pour la gestion de son cache, des traces d'exécution et des données de session. Les traces d'exécution et plus particulièrement le cache sont des tâches générant de nombreuses entrées-sorties sur le système de fichiers, particulièrement inadaptées aux systèmes de fichiers en réseau. Il en va de même pour PhpStorm
qui surveille les modifications de tous les fichiers de votre projet et ne peut pas fonctionner normalement lorsque ces fichiers sont sur un partage NFS
. Afin d'améliorer les performances de votre application et d'éviter de saturer le serveur de fichiers du département informatique, vous allez travailler dans le répertoire « /working/votre_login
» de la machine sur laquelle vous êtes connecté.
En fin de séance ¶
En fin de séance, vous devez impérativement synchroniser votre dépôt distant (en ligne de commande ou avec PhpStorm
)
git commitpuis
git pushfaute de quoi vous perdrez votre travail entre chaque séance !
Pensez également à supprimer votre répertoire de travail /working/votre_login/tests-conception
pour éviter la saturation du disque local :
rm -Rf /working/votre_login/tests-conception
En début de séance ¶
Lorsque vous reprenez le travail la séance suivante, vous avez trois choix possibles, qui dépendent de la façon dont vous avez travaillé :
- Mettre à jour votre dépôt local
cd /working/votre_login/tests-conception
git pull
- Effacer votre dépôt local et repartir de zéro
cd /working/votre_login
rm -Rf /working/votre_login/tests-conception
git clone https://iut-info.univ-reims.fr/gitlab/votre_login/tests-conception.git
cd /working/votre_login/tests-conception
- Réinitialiser votre dépôt local selon le dépôt distant
cd /working/votre_login/tests-conception
git fetch
git reset --hard origin/main
Ensuite, dans le répertoire de votre projet, vous devez et (ré)installer les composants nécessaires à son fonctionnement :
composer install
Versionnage du projet ¶
Pour chaque nouveau sujet de TP, vous créerez un nouveau répertoire, vous initialiserez un dépôt Git dans ce répertoire et créerez un dépôt distant sur GitLab. Vous réaliserez une opération de validation avec git commit
au moins une fois par question du sujet.
Initialisation du dépôt ¶
- Ouvrez un terminal, utilisez la commande
mkdir
pour créer un nouveau répertoiretests-conception
dans/working/votre_login
et utilisez la commandecd
pour vous placer dans le répertoire - Initialisez le dépôt Git du projet
git init
- Éditez le fichier
.gitignore
pour exclure les fichiers binaires de type image (JPEG, PNG, …), les fichiers qui contiennent des mots de passe ou les fichiers créés par votre éditeur de texte (*.swp
pourvim
, par exemple) - Éditez un fichier
README.md
dans lequel doivent figurer votre nom et votre prénom - Ajoutez les fichiers au dépôt
git add .
- Effectuez une première validation
git commit -m "Initial commit"
- Connectez-vous à l'application GitLab et créez un dépôt portant le même nom que votre nouveau répertoire
- Accordez la permission «
Reporter
» à votre enseignant de TP - Associez le dépôt local et le dépôt distant
git remote add origin https://iut-info.univ-reims.fr/gitlab/votre_login/tests-conception.git
- Poussez le dépôt local vers le dépôt distant
git push
Consignes ¶
- Vous effectuerez une validation après chaque question.
- A la fin de chaque séance, vous effectuerez une validation. Si cette validation contient du code incomplet ou ne fonctionnant pas, mentionnez-le dans le message de validation. Vous pousserez ensuite votre travail vers le dépôt distant.
- Ce dépôt sera utilisé par votre enseignant(e) de TP pour évaluer votre travail. Assurez-vous donc régulièrement que tous les fichiers que vous souhaitez lui rendre sont bien présents dans le dépôt. Respectez les noms des fichiers qui vous sont demandés si des consignes particulières vous sont données.
- Le dépôt lui-même sera évalué : soignez l'écriture de vos messages.
L'aide-mémoire Git et l'aide-mémoire GitLab de Monsieur Nourrit pourront vous être utiles.
Installer et configurer Composer
¶
Composer
simplifie grandement la gestion de projets PHP
. Afin d'accélérer les installations futures et de limiter l'impact sur votre quota d'espace disque, nous allons déporter le cache de Composer
dans le répertoire temporaire.
Travail à réaliser
- Si ce n'est pas déjà fait, installez
Composer
- Mettez
Composer
à jour - Si ce n'est pas déjà fait, relocalisez le cache de
Composer
InformationCette configuration est une nouvelle fois particulière à l'infrastructure de l'IUT. La modification du répertoire de cache de
Composer
n'est pas nécessaire sur votre ordinateur personnel. - Si ce n'est pas déjà fait, ajoutez un jeton d'authentification
GitHub
associé àComposer
Initialiser le projet Composer
¶
Vous allez initialiser un projet Composer
pour installer des paquets et profiter de l'auto-chargement.
Attention
commit
= danger !Dans cette partie, ne faites PAS de « commit
» tant que cela ne vous est pas demandé. Vous devrez dans un premier temps vérifier ou compléter votre fichier « .gitignore
» pour ne pas intégrer inutilement des centaines de fichiers et de répertoires à votre dépôt.
Travail à réaliser
- Si ce n'est pas déjà fait, installez
Composer
- Lisez la documentation de «
composer init
» - Dans le répertoire de votre projet, initialisez interactivement un nouveau projet
Composer
:composer init Welcome to the Composer config generator This command will guide you through creating your composer.json config. Package name (<vendor>/<name>) [cutron01/tests-conception]: Description []: Tests avec PHPUnit Author [Jérôme Cutrona <jerome.cutrona@univ-reims.fr>, n to skip]: Minimum Stability []: Package Type (e.g. library, project, metapackage, composer-plugin) []: project License []: Define your dependencies. Would you like to define your dependencies (require) interactively [yes]? n Would you like to define your dev dependencies (require-dev) interactively [yes]? n Add PSR-4 autoload mapping? Maps namespace "Cutron01\TestsConception" to the entered relative path. [src/, n to skip]: n { "name": "cutron01/tests-conception", "description": "Tests avec PHPUnit", "type": "project", "authors": [ { "name": "Jérôme Cutrona", "email": "jerome.cutrona@univ-reims.fr" } ], "require": {} } Do you confirm generation [yes]?
- Lancez l'installation et la configuration de l'auto-chargement
composer install
- Constatez l'apparition du répertoire «
vendor
» - Vérifiez le contenu du fichier «
.gitignore
» afin de vous assurer que le répertoire «vendor
» est bien exclu - Vérifiez le contenu de l'index avec la commande :
git status
dont le résultat doit être :Sur la branche master Votre branche est à jour avec 'origin/master'. Modifications qui ne seront pas validées : (utilisez "git add <fichier>..." pour mettre à jour ce qui sera validé) (utilisez "git restore <fichier>..." pour annuler les modifications dans le répertoire de travail) modifié : .gitignore Fichiers non suivis: (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé) composer.json composer.lock aucune modification n'a été ajoutée à la validation (utilisez "git add" ou "git commit -a")
Remarque importantele répertoire «
vendor
» ne doit PAS être présent dans la précédente liste de fichiers non suivis. Si tel est le cas, votre fichier «.gitignore
» est incorrect ou mal nommé. - Ajoutez les fichiers à l'index
Git
git add .
- Enregistrez les modifications dans le dépôt :
git commit
- Poussez les modifications sur le dépôt distant :
git push
- Vérifiez le contenu du dépôt distant sur https://iut-info.univ-reims.fr/gitlab/
Création du projet dans PhpStorm
¶
La gestion de nombreux fichiers dans une arborescence complexe demande un IDE adéquat. Vous utiliserez PhpStorm
pour l'édition de code et la gestion globale du projet. Des greffons apportent le support de Symfony
, Composer
, PHPUnit
, des fichiers YAML
, Twig
, … Certains sont préinstallés dans la configuration générale.
Vous allez créer un nouveau projet PhpStorm
pour gérer vos sources et vos suites de tests.
Référez-vous au sujet Installation et configuration de PhpStorm
.
Travail à réaliser
- Dans votre terminal et dans le répertoire du projet, lancez la commande
phpstorm . &
InformationCette commande est la façon la plus simple et la plus rapide de créer un nouveau projet
PhpStorm
dans un répertoire. Il n'est pas utile de la lancer une fois le projet créé puisque vos anciens projets sont proposés à l'ouverture dePhpStorm
ou dans son menu « File » puis « Recent Projects ». - Patientez pendant l'indexation des fichiers du projet visible dans la partie droite de la barre d'état
Information
Il est légitime d'inclure à votre index
Git
le répertoire «.idea
» de configuration dePhpStorm
afin que vous n'ayez pas à reconfigurer votre environnement lorsque vous clonerez votre dépôt en début de séance lors d'un changement de salle. Veillez néanmoins à effectuer descommits
distincts pour les modifications de ce répertoire.
Installation des outils de qualité de code ¶
La qualité de votre code, par son style cohérent ou l'absence de problèmes potentiels, est un atout majeur pour la maintenance et la fiabilisation de vos applications. Vous avez jusqu'à présent utilisé PHP CS Fixer
pour standardiser votre style de codage. Vous allez à présent découvrir PHP Mess Detector
, un autre outil d'analyse statique de code, dont l'objectif est de mettre en évidence des problèmes potentiels de nommage, de conception, de taille de code ou encore de code inutile.
La qualité du code passe également par des tests unitaires, fonctionnels ou d'intégration pour analyser dynamiquement le comportement du code testé. Aussi, vous utiliserez PHPUnit
et écrirez vos premiers tests unitaires pour valider le fonctionnement de votre code.
Ces trois outils, aussi puissants soient-ils, ne servent à rien si vous ne prenez pas la peine de les exécuter, de lire leurs alertes ou de suivre leurs suggestions. C'est pourquoi vous allez utiliser GrumPHP
! Cet outil de qualité de code s'appuie sur les « hooks » de Git
pour se déclencher avant chaque commit
et appliquer certaines tâches de contrôle. Il peut alors interrompre le commit
si les tâches échouent. Il devient donc impossible d'ajouter du code de mauvaise qualité (au sens des tests mis en place) au dépôt Git
local, et au dépôt distant par voie de conséquence.
PHPUnit
¶
PHPUnit
exécute les codes à travers les tests qui décrivent son comportement attendu. C'est un outil puissant et reconnu sur lequel s'appuient la plupart des outils de test dynamique de code PHP
.
Travail à réaliser
- Recherchez le paquet de
PHPUnit
à l'aide deComposer
:composer search phpunit
- Installez
PHPUnit
à l'aide deComposer
Remarque importanteLa version 10 de
PHPUnit
vient juste de sortir. Afin d'éviter tout problème, vous installerez la version 9 sur laquelle ce TP a été conçu. N'oubliez pas de forcer la version à l'installation !composer require --dev phpunit/phpunit:^9
- Constatez l'apparition du répertoire «
vendor/bin
» - Observez le contenu du répertoire «
vendor/bin
» - Vérifiez que
PHPUnit
fonctionne :vendor/bin/phpunit --version PHPUnit 9.6.3 by Sebastian Bergmann and contributors.
- Générez un fichier de configuration avec la commande :
vendor/bin/phpunit --generate-configuration PHPUnit 9.6.3 by Sebastian Bergmann and contributors. Generating phpunit.xml in /working/votre_login/tests-conception Bootstrap script (relative to path shown above; default: vendor/autoload.php): Tests directory (relative to path shown above; default: tests): Source directory (relative to path shown above; default: src): Cache directory (relative to path shown above; default: .phpunit.cache): Generated phpunit.xml in /working/votre_login/tests-conception. Make sure to exclude the .phpunit.cache directory from version control.
- Passez l'option «
forceCoversAnnotation
» à «false
» - Excluez le répertoire «
.phpunit.cache
» des fichiers suivis du dépôt
PHP CS Fixer
¶
PHP CS Fixer
, outil d'analyse statique de code développé par Fabien Potencier, créateur de Symfony
, détecte ou corrige les défauts de style de codage de vos sources.
Travail à réaliser
- Placez le fichier de configuration de
PHP CS Fixer
(télécharger) à la racine de votre projet (le style de codage défini est iciSymfony
)Remarque importanteVotre navigateur risque de renommer en
php-cs-fixer.dist.php
, supprimant ansi le.
initial. Veillez à ce que le nom du fichier soit bien.php-cs-fixer.dist.php
. - Référez-vous au sujet Installation et configuration de
PhpStorm
pour installer et configurerPHP CS Fixer
- Exluez le fichier
.php-cs-fixer.cache
du dépôtGit
PHP Mess Detector
¶
PHP Mess Detector
est un analyseur statique de code basé sur PHP Depend
qui mettra en évidence des bugs, du code sous-optimal, une complexité trop élevée ou des éléments inutilisés.
Travail à réaliser
- Référez-vous au sujet Installation et configuration de
PhpStorm
pour installer et configurerPHP Mess Detector
- Placez le fichier de configuration de
PHP Mess Detector
(télécharger) à la racine de votre projet (la détection porte sur toutes les règles possibles)InformationSi vous avez correctement suivi le guide d'installation de
PHP Mess Detector
, vous devez avoir une configuration dePHP Depend
. Elle est indispensable sur les PC de l'IUT. En effet,PHP Depend
génère des fichiers et répertoire de cache dans «$HOME/.pdepend
», donc dans le système de fichier partagé enNFS
, ce qui ralentit considérablement le temps d'analyse des fichiers du projet.
GrumPHP
¶
GrumPHP
vient parfaire votre contrôle de code en le validant avant chaque commit
. Dans un cadre d'un développement logiciel avec intégration continue, il doit être impossible d'introduire du code non valide dans le dépôt central et GrumPHP
permet de s'en assurer.
Remarque importante
Dans le cadre des TP, il n'est pas possible de vous interdire de soumettre du code invalide, tout particulièrement lors du « commit
de fin de séance ». Il vous sera donc possible, uniquement à cette occasion, de soumettre du code non validé. Pour cela, vous utiliserez l'option « --no-verify
» de git
en ligne de commande qui permet de sauter les « hooks » et donc l'exécution de GrumPHP
. Vous ferez alors mention de l'état invalide du code dans le message de commit
.
Travail à réaliser
- Installez
GrumPHP
à l'aide deComposer
composer require --dev phpro/grumphp
Remarque importanteDeux questions vous sont posées pendant l'installation.
Répondez «
y
» à la question suivante :phpro/grumphp contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins Do you trust "phpro/grumphp" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?]
Répondez «
n
» à la question suivante :Run composer recipes at any time to see the status of your Symfony recipes. Do you want to create a grumphp.yml file? [Yes]:
- Placez le fichier de configuration de
GrumPHP
(télécharger) à la racine de votre projet - Observez les tâches du fichier de configuration fourni et lisez la documentation associée à chacune d'entre elles
- Afin de vérifier le bon fonctionnement de
GrumPHP
:- Supprimez la description de votre projet dans «
composer.json
» - Ajoutez le fichier «
composer.json
» à l'indexGit
:git add composer.json
- Tentez de valider votre modification :
git commit -m "test GrumPHP" GrumPHP detected a pre-commit command. GrumPHP is sniffing your code! Running tasks with priority 0! ============================== Running task 1/4: composer... ✘ Running task 2/4: phpcsfixer2... Running task 3/4: phpmd... Running task 4/4: phpunit... ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▄███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ █▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▐█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▀█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▀▀▓▓▓▓▓▓▓▓▓▓▓▓█▀▀▀▀▀▀▀▀▀▀▀▀▀▀████████████▄ ▄███████ ██████████ ███████▀ ▀▀▀▀▀▄ ▄▀▀▀▀▀ █████ ▀ ▐████ ▐██ ▐██ ████▌ ████▌ ███ ▌██▌ ▄▄ ▄▄ ▐███ ███ ▄▄▄▄▄▄▄▄▄▄▄▄ ▐███ ██▄ ▐███████████████████████████ █▀███████████▀ ▀▀███████████ ██████████▄███████▄███████████ ▐█████████████████████████████ █████████████████████████████ ██ █████████████████████▐██▀ ▀ ▐███████████████████▌ ▐▀ ████▀████████▀▐███ ▀█▌ ▐█████ ██▌ ██▀ ▐▀ ██████████████████████████████████ █░░░░░░▀█▀░░░░░░▀█░░░░░░▀█▀░░░░░▀█ █░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█ █░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█ █░░▐█▌░░█░░░██░░░█░░░░░░▄█░░▄▄▄▄▄█ █░░▐█▌░░█░░░██░░░█░░░░████░░░░░░░█ █░░░█░░░█▄░░░░░░▄█░░░░████▄░░░░░▄█ ██████████████████████████████████ composer ======== ./composer.json is valid for simple usage with Composer but has strict errors that make it unable to be published as a package See https://getcomposer.org/doc/04-schema.md for details on the schema # Publish errors - description : The property description is required
- Si le test de
commit
n'a pas déclenchéGrumPHP
, initialisez-le dans votre projet avec :vendor/bin/grumphp git:init
- Si le test de
commit
n'avait pas déclenchéGrumPHP
et que vous souhaitez défaire votre derniercommit
:git reset --soft HEAD~1
- Annulez la suppression de la description de votre projet dans «
composer.json
» («CTRL+Z
» dans votre IDE)
- Supprimez la description de votre projet dans «
Remarque importante
Si vous utilisez les fonctionnalités Git
à travers PhpStorm
sur Linux
, vous rencontrerez certainement le message d'erreur suivant, rendant impossible la validation de la tâche « composer
» :
The executable for "composer" could not be found.
Ceci est lié à l'installation de Composer
dans la sous-arborescence des fichiers de l'utilisateur ainsi qu'à la configuration de l'environnement du « shell » « bash
» lié à ses divers fichiers d'initialisation.
La solution la plus appropriée est de déporter la configuration de la variable « PATH
» dans le fichier « $HOME/.profile
». Vous devez donc transférer les lignes concernées du fichier « $HOME/.bashrc
» vers « $HOME/.profile
» (que vous devez créer s'il n'existe pas dans votre compte). Une déconnexion/reconnexion est nécessaire pour que les modifications soient prises en compte.
Information
Vous pouvez changer les images ASCII utilisées pour vous signifier le succès ou l'échec des contrôles faits par GrumPHP
.
Scripts Composer
¶
Pour faciliter l'invocation des divers outils de qualité de code, vous pouvez utiliser les scripts Composer
. Pour gagner un peu de temps, nous vous proposons de copier les scripts fournis :
test:cs
qui vérifie le style de codage avecPHP CS Fixer
fix:cs
qui arrange le style de codage avecPHP CS Fixer
test:md
qui vérifie le style de codage avecPHP Mess Detector
test:phpunit
qui lance les tests définis avecPHPUnit
test
qui lance tous les tests définis précédemmentgrumphp:precommit
qui lance les tâches définies avecGrumPHP
sur les fichiers indexés dansGit
grumphp:run
qui lance les tâches définies avecGrumPHP
sur tous les fichiers
Travail à réaliser
- Ajoutez les scripts suivants au fichier
composer.json
:InformationIl est possible d'invoquer un script
Composer
sans donner son nom complet, à condition que le nom tronqué conduise à un seul choix possible. À titre d'exemple, dans les scripts fournis, la commandecomposer grumphp:precommit
peut être abrégée encomposer grumphp:p
Configuration du projet ¶
Avant de commencer à coder, quelques consignes seront à respecter pour respecter la structure de fichiers habituelle des projets écrits en PHP
et ainsi permettre bien valider votre code avec les tests.
- Les sources se trouvent dans un répertoire «
src
» dans lequel des sous-répertoires correspondent aux espaces de noms - Les tests se trouvent dans un répertoire «
tests
» dans lequel des sous-répertoires correspondent aux espaces de noms - La classe «
MonNamespace\MaClasse
» se trouve dans le fichier «src/MonNamespace/MaClasse.php
» - Les tests de la classe «
MonNamespace\MaClasse
» sont faits dans la classe «Tests\MonNamespace\MaClasse
» qui se trouve dans le fichier «tests/MonNamespace/MaClasseTest.php
» - Un fichier contenant une classe ne fait pas d'inclusions («
require
», …), ceci est à la charge de l'application - Un fichier contenant une classe de test ne fait pas d'inclusions («
require
», …), ceci est à la charge du framework de tests - Afin de détecter les problèmes liés au type des variables, il est recommandé de passer en typage strict dans chacune de vos classes
- Votre code doit être conforme aux standards de codage
Ces consignes impliquent la création de répertoires ainsi que la configuration de l'auto-chargement par Composer
. Toutes les tâches sont réalisables dans PhpStorm
et seront donc réalisées dans PhpStorm
.
Travail à réaliser
- Vérifiez que la version de
PHP
indiquée dansPhpStorm
soit la bonne - Vérifiez que les modèles de
PhpStorm
intègrent le typage strict - Configurez les outils d'analyse statique / de tests statiques de code
PHP
- Créez les répertoires «
src
» et «tests
» en effectuant un clic droit sur le projet puis « New » suivi de « Directory » - Lisez la documentation de
Composer
sur l'auto-chargementPSR-4
- Ouvrez le fichier «
composer.json
» - Ajoutez le répertoire «
src
» comme chemin de recherche de l'ensemble des namespaces en profitant des suggestions dePhpStorm
- Ajoutez le répertoire «
tests
» comme chemin de recherche de l'ensemble des namespaces de développement qui commencent par «Tests\
» en profitant des suggestions dePhpStorm
- Mettez à jour l'auto-chargement de
Composer
à l'aide de l'option «dump-autoload
»composer dump-autoload Generating autoload files Generated autoload files
Remarque importante
L'auto-chargement PSR-4
ne nécessite PAS de refaire la commande composer dump-autoload
lors de l'ajout de nouvelles classes dans le répertoire « src
».
Principe du jeu et de la réalisation ¶
Vous allez vous intéresser au développement d'un jeu « Rock, Paper, Scissors » et ses évolutions possibles à travers l'ajout de nouveaux gestes comme dans la variante « Rock, Paper, Scissors, Lizard, Spock ». Le jeu sera exécuté en PHP
ligne de commande.
Le principe de ces jeux repose sur l'opposition de deux joueurs qui choisissent chacun un geste parmi 2n+1
. Chaque geste l'emporte contre n
gestes et perd contre n
autres gestes. Si les deux joueurs choisissent le même geste, il y a égalité.
Les combinaisons gagnantes pour « Rock, Paper, Scissors » (n=1
) sont triviales :
Les combinaisons gagnantes pour « Rock, Paper, Scissors, Lizard, Spock » (
n=2
) sont :
Vous pouvez consulter des variantes à 7, 9, 11, 15, 25 voire 101 gestes.
La réalisation de ces jeux va se faire, en fonction des spécifications, selon les bonnes pratiques de conception afin de permettre flexibilité, robustesse et évolutivité, avec une implémentation réfléchie et des tests garantissant le bon fonctionnement des composants et de l'ensemble.
Rock, Paper, Scissors ¶
Pour commencer, la réalisation va se limiter à la variante la plus simple du jeu avec trois gestes.
Gestion des règles ¶
Une partie du fonctionnement du jeu réside dans la détermination du geste gagnant. Lorsque les gestes des deux opposants sont confrontés, si le premier est gagnant, il remporte 1 point, s'il est perdant, il perd 1 point et en cas d'égalité, le résultat est nul.
Travail à réaliser
- Observez le diagramme de classes
Le diagramme précédent est celui des classes associées aux règles.
- Créez l'interface et les classes avec l'assistant de
PhpStorm
- Écrivez les méthodes de la classe «
RockPaperScissors
»- «
getGestures()
» donne l'ensemble des gestes - «
compare()
» retourne1
,-1
ou0
selon que «gesture1
» gagne, perd ou est à égalité avec «gesture2
» - «
checkGesture()
» vérifie que son paramètre est un geste valide - «
gestureIndex()
» donne l'indice du geste dans le tableau «GESTURES
» afin de faciliter l'évaluation de la comparaison (cette méthode n'est pas obligatoire, vous pouvez réaliser «compare()
» sans elle)
- «
- Écrivez les tests de la classe «
RockPaperScissors
»Remarque importanteLes classes de test font partie de l'espace de noms «
Tests
» suivi de l'espace de noms de la classe qu'elles testent.
Les joueurs ¶
Les joueurs, machine ou humain, peuvent jouer un coup valide.
Le diagramme précédent est celui des classes associées aux joueurs.
Travail à réaliser
- Observez le diagramme de classes
- Créez les classes et interface avec
PhpStorm
- Écrivez les méthodes de la classe «
Player
» - Écrivez la méthode de la classe «
Computer
» qui réalise un tirage aléatoire parmi l'ensemble des gestes connus dans les règles - Écrivez les méthodes de la classe «
Human
»- «
showPossibilities()
» retourne l'ensemble des gestes possibles sous forme d'une chaîne de caractères - «
prompt()
» affiche les gestes possibles et invite l'utilisateur à en choisir un - «
getInput()
» effectue une lecture au clavier et la retourne - «
playOneMove()
» qui effectue toutes les opérations nécessaires pour récupérer un geste valide du joueur
- «
- Écrivez les tests des classes «
Human
» et «Computer
»Remarque importanteLes classes de test font partie de l'espace de noms «
Tests
» suivi de l'espace de noms de la classe qu'elles testent.NamespacesLa classe «
Human
» produisant une sortie écran, lisez la documentation concernant ce point.
Le jeu ¶
Le jeu nécessite deux joueurs et un jeu de règles.
Le diagramme précédent est celui des classes associées au jeu.
Travail à réaliser
- Observez le diagramme de classes
- Créez la classe avec
PhpStorm
- Écrivez les méthodes de la classe «
Game
»- le constructeur
- «
play()
» qui lance la partie pour un certain nombre de tours minimum jusqu'à obtenir un vainqueur et qui cumule dans «score
» les résultats obtenus par «playOneMove()
» - «
playOneMove()
» qui correspond à un tour de jeu - «
getScore()
» - «
winner()
» qui retourne le vainqueur ou lève une «RuntimeException
» s'il n'y en a pas
- Lisez la documentation de
PHPUnit
sur «onConsecutiveCalls()
» ainsi que celle dePHP
sur l'utilisation de «...
» pour fournir des arguments qui vous seront utiles pour simuler les coups des joueurs durant la partie de test - Écrivez les tests de la classe «
Game
»NamespacesLes classes de test font partie de l'espace de noms «
Tests
» suivi de l'espace de noms de la classe qu'elles testent.Sortie écranVotre programme produisant une sortie écran qui va polluer la sortie de
PHPUnit
, lisez la documentation concernant ce point.
Couverture de code ¶
Tous les composants nécessaires étant présents et testés, il est utile de vérifier la couverture de code.
Travail à réaliser
- Générez un rapport d'analyse de couverture de code dans le répertoire «
coverage
» - Excluez ce répertoire
coverage
de votre dépôtGit
- Ajoutez un nouveau script
Composer
«test:coverage
» qui efface le répertoire «coverage
» avant de lancer la commandePHPUnit
que vous venez d'élaborer - Vérifiez que votre couverture de code est suffisante
Programme pour jouer ¶
Tous les composants nécessaires étant présents, il reste à pouvoir jouer.
Travail à réaliser
- Créez un répertoire «
bin
» dans lequel vous mettrez vos programmes - Dans le répertoire «
bin
», créez un programme «playRPS
» qui commence par :#!/usr/bin/env php <?php
- Rendez le programme «
playRPS
» exécutableInformationVous pouvez à présent lancer vos programmes avec :
bin/nom_programme
- Ajoutez au début du programme l'inclusion de l'auto-chargement de
Composer
en utilisant la constante magique «__DIR__
» pour déterminer le chemin du programme - Écrivez le programme «
playRPS
» qui permet à un humain « Bob » de jouer contre la machine « HAL » pour 3 tours minimum, qui pourrait donner :bin/playRPS Saisissez votre geste (R, P, S) : R R R --> 0 Saisissez votre geste (R, P, S) : o Saisissez votre geste (R, P, S) : R R S --> 1 Saisissez votre geste (R, P, S) : R R P --> -1 Saisissez votre geste (R, P, S) : P P R --> 1 Bob won!
Rock, Paper, Scissors, Lizard, Spock ¶
Vous allez reproduire ce qui vient d'être fait pour « Rock, Paper, Scissors » afin d'arriver à la création des composants nécessaires à la variante « Rock, Paper, Scissors, Lizard, Spock ».
Travail à réaliser
- Dupliquez la classe «
RockPaperScissors
» en «RockPaperScissorsLizardSpock
» - Complétez les gestes possibles dans les constantes de classe : «
'R'
», «'P'
», «'S'
», «'L'
», «'V'
» («'V'
» pour « Vulcan Salute » 🖖) - Vous pouvez construire un tableau des gestes gagnants sur le modèle « Rock gagne face à Scissors et Lizard », …
- Donnez une version fonctionnelle de la méthode «
compare()
» - Écrivez les tests permettant de le vérifier
- Écrivez le programme «
playRPSLV
» qui permet à un humain « Bob » de jouer contre la machine « HAL » pour 3 tours minimum
Généralisation et refonte ¶
En fonction de la façon dont vous avez réalisé la variante « Rock, Paper, Scissors, Lizard, Spock », votre code est plus ou moins redondant par rapport à « Rock, Paper, Scissors ». Qu'en sera-t-il pour les variantes comportant plus de gestes ?
En réorganisant astucieusement les gestes en « Rock, Spock, Paper, Lizard, Scissors », les scores associés aux combinaisons sont :
R | V | P | L | S | |
---|---|---|---|---|---|
R | 0 | -1 | -1 | 1 | 1 |
V | 1 | 0 | -1 | -1 | 1 |
P | 1 | 1 | 0 | -1 | -1 |
L | -1 | 1 | 1 | 0 | -1 |
S | -1 | -1 | 1 | 1 | 0 |
Dans une vision cyclique des gestes, pour un geste donné, les deux suivants l'emportent alors que les deux précédents sont battus :
La généralisation à 2n+1
gestes donne les n
gestes suivants vainqueurs et les n
gestes précédents perdants. Le fonctionnement réside alors sur l'ordre des gestes qui permet de connaître les points pour chaque confrontation, ce qui va entrainer la création d'une nouvelle hiérarchie de classes.
Les gestes ¶
Vous allez séparer les gestes des règles :
Le diagramme précédent est celui des classes associées aux gestes.
Travail à réaliser
- Créez une interface «
MyGame\Rules\Gestures\IGestures
» représentant les gestes associés à des règles - Ajoutez une méthode «
getGestures()
» à votre nouvelle interface - Parcourez rapidement la documentation de «
ReflectionClass
» et lisez attentivement celle de sa méthode «getConstants()
» - Créez une classe abstraite «
MyGame\Rules\Gestures\Gestures
» qui implémente «IGestures
» et qui aura pour but de retourner les constantes des classes qui dériveront d'elle - Lisez la documentation concernant la résolution statique à la volée (« Late Static Bindings »)
- Donnez le code suivant à la méthode «
getGestures()
» :$reflectionClass = new ReflectionClass(static::class); return array_values($reflectionClass->getConstants());
- Testez votre classe abstraite «
Gestures
» en créant une classe anonyme en héritant - Dérivez la classe abstraite «
Gestures
» en «RockPaperScissorsLizardSpockGestures
» - Ajoutez les constantes des gestes à votre nouvelle classe
- Testez «
RockPaperScissorsLizardSpockGestures
»
Les règles ¶
Les règles vont également être revues :
Le diagramme précédent est celui des classes associées aux règles généralisées.
Travail à réaliser
- Créez avec
PhpStorm
la classe «GenericRules
» qui implémente «IRules
» - Ajoutez à «
GenericRules
» un constructeur qui reçoit une instance de «IGestures
» qui sera mémorisée dans une propriété d'instance - En vous appuyant sur les principes énoncées au début de cette partie, donnez une version fonctionnelle des méthodes :
- «
getGestures()
» - «
checkGesture()
» - «
compare()
» - «
getGestureIndex()
»
- «
- Modifiez la classe «
RockPaperScissorsLizardSpock
» afin qu'elle hérite de «GenericRules
» et qu'elle ne comporte plus qu'un constructeur - Adaptez éventuellement les tests de «
RockPaperScissorsLizardSpock
» et vérifiez qu'ils passent - Modifiez la classe «
RockPaperScissors
» afin qu'elle hérite de «GenericRules
» et qu'elle ne comporte plus qu'un constructeur - Adaptez éventuellement les tests de «
RockPaperScissors
» et vérifiez que votre classe les passe
Couverture de code ¶
Tous les composants nécessaires étant présents et testés, il est utile de vérifier la couverture de code.
Travail à réaliser
- Générez un rapport d'analyse de couverture de code dans le répertoire «
coverage
» - Vérifiez que votre couverture de code est suffisante
Remarque importante
Vous devrez fixer le mode de fonctionnement de Xdebug
en préfixant votre commande de calcul de couverture de code par
l'affectation de la variable d'environnement XDEBUG_MODE
avec la valeur « coverage
» :
XDEBUG_MODE=coverage vendor/bin/phpunit
RPS-9 ¶
Mettons votre code à l'épreuve de RPS-9.
Travail à réaliser
- Téléchargez le code de la classe de gestes
RockGunWaterAirPaperSpongeHumanScissorsFireGestures.php
(télécharger) - Téléchargez le code de la classe de règles
RockGunWaterAirPaperSpongeHumanScissorsFire.php
(télécharger) - Téléchargez le code de la classe de tests
RockGunWaterAirPaperSpongeHumanScissorsFireTest.php
(télécharger) - Vérifiez que vos classes passent ces nouveaux tests