Aujourd’hui, nous allons parler des tests unitaires, mocks, client HTTP et PHP ! 😼

Sommaire

Tests unitaires

Les tests unitaires automatisĂ©s sont un outil essentiel pour garantir la stabilitĂ© d’un dĂ©veloppement et accĂ©lĂ©rer les phases de correction, d’Ă©volution ou refactoring. Cependant, pour qu’un test unitaire soit efficace, il doit s’assurer de respecter quelques recommandations (liste non-exhaustive) :

  • ĂȘtre trĂšs rapide Ă  exĂ©cuter : pour le lancer le plus souvent possible et avoir un feedback presque instantanĂ©
  • ĂȘtre rejouable indĂ©finiment : pour le lancer le plus souvent possible
  • ne tester que le composant ou la fonction Ă  tester : car c’est sa raison d’ĂȘtre

Mocks

Un test unitaire ne doit donc pas tester les dépendances du composant à tester. Les deux principales raisons sont :

  • Les dĂ©pendances ont leurs propres tests unitaires. Il n’est donc pas nĂ©cessaire de les tester une seconde fois.
  • Si une dĂ©pendance contient un bug, est-ce que le composant testĂ© a un bug ? Non !

Afin de rĂ©pondre Ă  cette problĂ©matique, il est possible d’utiliser des techniques de mocking (ou stubing). Elles permettent de simuler le comportement d’un composant et donc d’une dĂ©pendance. Ainsi, un contrat d’utilisation du sous-composant est dĂ©fini. Le test valide le comportement du composant principal en le mettant en condition normale (ie. comportement du sous-composant attendu). L’utilisation de mocks assure la stabilitĂ© des dĂ©pendances et augmente donc celle du test unitaire.

Architecture REST

Ce qui est intĂ©ressant avec les architectures REST actuelles, c’est qu’elles reposent souvent sur un unique et mĂȘme protocole de communication : HTTP. C’est donc le protocole qui est utilisĂ© pour matĂ©rialiser les dĂ©pendances entre les composants dans ce type d’architecture. L’enjeu des tests unitaires ici est donc d’ĂȘtre capable de crĂ©er des mocks HTTP.

Et en PHP ?

Venons en maintenant Ă  ce qui nous interesse : le PHP !

PHP propose des fonctions en standard pour faire des appels HTTP. NĂ©anmoins, il existe des composants plus avancĂ©s tels que Guzzle. Ce client HTTP pour PHP propose lui-mĂȘme de crĂ©er un mock HTTP.

Imaginons le composant suivant qui permet de rĂ©cupĂ©rer le dĂ©tail de ressources exposĂ©es via l’API « datas » :

class ApiBackup {
public $client;
public function __construct() { $this->client = new GuzzleHttp\Client();}
public function exportAll() {
  $response = $this->client->get('https://apis.company.com/datas');
  foreach($res->json()->results as $row) {
    $results[] = $this->client>get('https://apis.company/datas/'.$row->id);
  }
  return results;
}
}

CrĂ©er un test unitaire automatisĂ© de ce composant nĂ©cessite donc d’avoir une API « datas » toujours disponible, trĂšs rapide et toujours avec les mĂȘmes donnĂ©es. Autant dire : mission impossible ! C’est pourquoi nous allons « mocker » le client HTTP et crĂ©er le test uniaire suivant :

class ApiBackupTest extends PHPUnit_Framework_TestCase {
public function testExportAll() {
  // GIVEN
  $apiBackup = new ApiBackup();
  $mock = new GuzzleHttp\Subscriber\Mock();
  $mock->addResponse('./ressources/datas_all.txt'); //contient la réponse HTTP attendue (avec 3 résultats) pour l'appel à https://apis.company.com/datas
  $mock->addResponse('./ressources/datas_1.txt'); // contient la réponse HTTP attendue (avec le détail de la ressource) pour l'appel à 'https://apis.company/datas/'.$row->id
  $mock->addResponse('./ressources/datas_2.txt'); // idem
  $mock->addResponse('./ressources/datas_3.txt'); // idem
  $apiBackup->client->getEmitter()->attach($mock);

  // WHEN
  $results = $apiBackup->exportAll();

  // THEN
  $this->assertEquals(3,count($results));
}
}

Le test unitaire ci-dessus crĂ©Ă© un mock qui retournera toujours 3 ressources avec toujours le mĂȘme dĂ©tail. L’API « datas » ne sera pas appelĂ©e lors de l’exĂ©cution du test.

Pour explication, un fichier de réponse ressemble à ceci :

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Fri, 14 Mar 2014 07:53:27 GMT
Content-Length: 79
Connection: keep-alive

{
  "results": [
    {"id":"1571"},
    {"id":"2349"},
    {"id":"3727"},
  ]
}

Il est possible d’obtenir ces fichiers de rĂ©ponse HTTP avec les commandes suivantes (si l’API « datas » est dans l’Ă©tat souhaitĂ©) :

$ curl -iv --raw -o ressources/datas_all.txt 'https://apis.company.com/datas'
$ curl -iv --raw -o ressources/datas_1.txt 'https://apis.company.com/datas/1571'
$ curl -iv --raw -o ressources/datas_2.txt 'https://apis.company.com/datas/2349'
$ curl -iv --raw -o ressources/datas_3.txt 'https://apis.company.com/datas/3727'

Vous ĂȘtes maintenant armĂ© pour industrialiser les tests unitaires de vos applications PHP qui utiliseraient le client HTTP Guzzle.

https://blog.lecacheur.com/wp-content/uploads/2014/11/php-unit.jpghttps://blog.lecacheur.com/wp-content/uploads/2014/11/php-unit-150x150.jpgSeBDĂ©veloppementmock,php,restAujourd'hui, nous allons parler des tests unitaires, mocks, client HTTP et PHP ! 😼 Tests unitaires Les tests unitaires automatisĂ©s sont un outil essentiel pour garantir la stabilitĂ© d'un dĂ©veloppement et accĂ©lĂ©rer les phases de correction, d'Ă©volution ou refactoring. Cependant, pour qu'un test unitaire soit efficace, il doit s'assurer de respecter...Un blog, c'est un blog !