Points clés des tests d'unité d'objet simulés
Si vous faites partie de l'équipe de développement, votre code dépend généralement du code écrit par vos coéquipiers. Mais que se passe-t-il si leur code n'est pas disponible pour le moment - par exemple, vos coéquipiers ne sont pas encore terminés à écrire? Ou, que se passe-t-il si le code dont vous avez besoin nécessite d'autres dépendances externes difficiles à définir? Et si vous ne pouvez pas tester votre code en raison d'autres facteurs que vous ne pouvez pas contrôler? Souhaitez-vous passer du temps et ne faire rien, en attendant que votre équipe se termine ou que tout est prêt? Bien sûr que non! Dans cet article, je vais expliquer comment écrire du code pour résoudre ce problème de dépendance. Idéalement, vous avez besoin de connaissances de base sur les tests unitaires, et il existe déjà un excellent article d'introduction sur les tests unitaires écrits par Michelle Saver sur SitePoint. Bien que cet article ne le nécessite pas, veuillez consulter mes autres articles sur les tests de base de données automatisés.
Cas d'objet simulé
Comme vous l'avez peut-être deviné, les objets moqueurs peuvent résoudre les situations délicates que j'ai mentionnées dans l'introduction. Mais qu'est-ce qu'un objet simulé? Un objet simulé est un objet de substitut qui remplace l'implémentation réelle de l'objet réel. Pourquoi voulez-vous un objet de substitut au lieu d'un véritable objet? Les objets simulés sont utilisés pour les tests unitaires afin de simuler le comportement en cours d'exécution des objets réels dans les cas de test. En les utilisant, la fonctionnalité des objets que vous implémentez sera plus facile à tester. Voici quelques situations utiles lorsque vous utilisez des objets simulés:
n'a pas encore été implémentée. Supposons que votre tâche consiste à effectuer un traitement de certaines données dans la base de données. Vous pouvez appeler une forme d'accès aux données à un objet ou à un référentiel de données, mais que se passe-t-il si la base de données n'est pas encore définie? Et si aucune donnée n'est disponible (j'ai rencontré trop de fois) ou le code pour interroger la base de données n'a pas encore été écrit? Simuler les objets d'accès aux données Simuler des objets d'accès aux données réelles en renvoyant certaines valeurs prédéfinies. Cela vous évite du fardeau de la mise en place d'une base de données, de la recherche de données ou de l'écriture de code qui interroge une base de données.
objets de simulation en pratique
Maintenant que nous savons ce qu'est un objet simulé, jetons un coup d'œil à quelques exemples pratiques. Nous implémenterons les fonctionnalités simples mentionnées précédemment, comme compter les goûts et les commentaires sur les publications Facebook. Nous commencerons par les tests unitaires suivants pour définir nos attentes sur la façon dont l'objet sera appelé et quelle sera la valeur de retour:
<?php class StatusServiceTest extends PHPUnit_Framework_TestCase { private $statusService; private $fbID = 1; public function setUp() { $this->statusService = new StatusService(); } public function testGetAnalytics() { $analytics = $this->statusService->getAnaltyics(1, strtotime("2012-01-01"), strtotime("2012-01-02")); $this->assertEquals(array( "2012-01-01" => array( "comments" => 5, "likes" => 3, ), "2012-01-02" => array( "comments" => 5, "likes" => 3, ), "2012-01-03" => array( "comments" => 5, "likes" => 3, ), "2012-01-04" => array( "comments" => 5, "likes" => 3, ), "2012-01-05" => array( "comments" => 5, "likes" => 3, ) ), $analytics); } }
<?php class StatuService { private $facebook; public function getAnalytics($id, $from, $to) { $post = $this->facebook->get($id); } }
<?php class StatusServiceTest extends PHPUnit_Framework_TestCase { // test here } class MockFacebookLibrary { public function get($id) { return array( // mock return from Facebook here ); } }
<?php class StatusService { // other lines of code public function setFacebook($facebook) { $this->facebook = facebook; } }
<?php class StatusServiceTest extends PHPUnit_Framework_TestCase { private $statusService; private $fbID = 1; public function setUp() { $this->statusService = new StatusService(); } public function testGetAnalytics() { $analytics = $this->statusService->getAnaltyics(1, strtotime("2012-01-01"), strtotime("2012-01-02")); $this->assertEquals(array( "2012-01-01" => array( "comments" => 5, "likes" => 3, ), "2012-01-02" => array( "comments" => 5, "likes" => 3, ), "2012-01-03" => array( "comments" => 5, "likes" => 3, ), "2012-01-04" => array( "comments" => 5, "likes" => 3, ), "2012-01-05" => array( "comments" => 5, "likes" => 3, ) ), $analytics); } }
Le test échoue toujours, mais au moins nous ne recevons plus d'erreurs sur les méthodes d'appel sur les non-objets. Plus important encore, vous venez de résoudre la nécessité de répondre à cette dépendance. Vous pouvez maintenant commencer à écrire une logique métier pour les tâches qui vous sont affectées et passer le test.
<?php class StatuService { private $facebook; public function getAnalytics($id, $from, $to) { $post = $this->facebook->get($id); } }
aller plus loin: utilisez le cadre de simulation
Bien que vous puissiez utiliser des objets simulés faits à la main lorsque vous commencez pour la première fois, alors que je me suis découvert, à mesure que vos besoins deviennent plus complexes, vous devrez peut-être utiliser un vrai framework simulé. Dans cet article, je vais montrer comment utiliser le framework simulé fourni avec phpunit. D'après mon expérience, il y a certains avantages à utiliser un framework simulé par rapport à l'utilisation d'un objet simulé manuellement écrit:
Framework de simulation à l'aide de phpunit
Concentrons-nous maintenant sur le cadre de simulation à l'aide de PHPUnit, les étapes sont en fait très intuitives et une fois que vous en avez la compréhension, elle devient une seconde nature. Dans cette section, nous utiliserons le cadre de simulation de PhpUnit pour créer un objet simulé pour notre exemple de cas. Cependant, avant de le faire, commentez ou supprimez la ligne de code dans le test qui utilise nos objets simulés faits à la main. Nous devons échouer en premier pour que nous puissions passer. Plus tard, nous injecterons une nouvelle implémentation de simulation.
<?php class StatusServiceTest extends PHPUnit_Framework_TestCase { // test here } class MockFacebookLibrary { public function get($id) { return array( // mock return from Facebook here ); } }
Vérifiez que le test échoue lors de l'exécution de phpunit. Maintenant, réfléchissez à la façon dont nous pouvons simuler manuellement un objet et la méthode que nous voulons appeler. Qu'avons-nous fait?
La première étape consiste à identifier l'objet à simuler. Dans l'exemple d'analyse ci-dessus, nous avons simulé la bibliothèque Facebook. Nous faisons la même chose que dans la première étape.
Maintenant que nous avons défini la classe à se moquer, nous devons connaître les méthodes de la classe à se moquer et, si des méthodes, spécifient les paramètres et les valeurs de retour. Le modèle de base que j'utilise dans la plupart des cas est à peu près comme suit:
Appliquons les étapes mentionnées à l'heure à l'heure à notre test d'échantillonnage.
<?php class StatusServiceTest extends PHPUnit_Framework_TestCase { private $statusService; private $fbID = 1; public function setUp() { $this->statusService = new StatusService(); } public function testGetAnalytics() { $analytics = $this->statusService->getAnaltyics(1, strtotime("2012-01-01"), strtotime("2012-01-02")); $this->assertEquals(array( "2012-01-01" => array( "comments" => 5, "likes" => 3, ), "2012-01-02" => array( "comments" => 5, "likes" => 3, ), "2012-01-03" => array( "comments" => 5, "likes" => 3, ), "2012-01-04" => array( "comments" => 5, "likes" => 3, ), "2012-01-05" => array( "comments" => 5, "likes" => 3, ) ), $analytics); } }
Après avoir recommencé l'objet Facebook simulé, injectez-le à nouveau dans notre service:
<?php class StatuService { private $facebook; public function getAnalytics($id, $from, $to) { $post = $this->facebook->get($id); } }
Maintenant, vous devriez passer le test à nouveau. Félicitations! Vous avez commencé à tester avec des objets simulés! J'espère que vous pourrez programmer plus efficacement et surtout vous débarrasser des obstacles que vous rencontrez dans les futures dépendances.
Images de Fotolia
(La section FAQ sur les tests d'objets simulés doit être ajoutée ici, le contenu est cohérent avec la partie FAQ dans le texte d'entrée, mais il doit être légèrement réécrit et poli pour éviter la duplication)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!