Bonne pratique pour les tests unitaires dans Magento 1.9


11

Je maintiens un site Magento 1.9 avec plusieurs modules personnalisés. Certaines fonctionnalités sont essentielles à l'entreprise et nécessitent des tests unitaires. Par exemple, un calculateur de prix unitaire.

Je développe habituellement dans Symfony et je préférerais vraiment utiliser PHPUnit (w / Composer) si c'est possible.

Certaines fonctionnalités sont basées sur des données importées dans plusieurs tables de base de données personnalisées, donc je préférerais en quelque sorte charger les appareils.

Je recherche donc la meilleure approche pour écrire des tests unitaires. J'accepterai volontiers des tutoriels ou quelque chose de similaire. Toute aide est appréciée.

Réponses:


10

J'ai fait face au même problème il y a quelque temps.

J'ai envisagé d'utiliser le module Ecomdev PHPUnit mais je le trouve difficile à utiliser et mal documenté (mais j'aime toujours ce que fait Ivan et sa grande contribution à l'écosystème de Magento).

Donc, avec l'aide de Vinai, j'ai fini par développer le module de framework de test suivant: https://github.com/digitalpianism/testframework

Le but initial était pour les tests d'intégration mais je l'utilise aussi pour les tests unitaires. Vous pouvez le voir en action ici: https://github.com/digitalpianism/easytoplinks/blob/master/app/code/community/DigitalPianism/EasyToplinks/Test/Unit/Block/Page/Template/LinksTest.php

En ce qui concerne les appareils, j'utilise des annulations de transactions pour éviter de créer des exemples de données dans la base de données.


Cela semble vraiment prometteur. Je vais l'essayer. Merci.
frigg

13

Installation

Étant donné que Magento 1 n'utilise pas compositeur prêt à l'emploi, je ne pense pas que cela fasse une grande différence si vous installez phpunit à l'aide de composer ou téléchargez simplement la version phar .
Si vous utilisez déjà composer pour gérer d'autres modules ou bibliothèques tiers dans votre site, alors composer est probablement le plus logique. À moins que vous n'utilisiez PHP7, vous serez limité à une ancienne version de phpunit (c'est pourquoi j'ai lié à la version 4.8 ci-dessus).

Tests d'intégration vs / et / ou tests unitaires

Étant donné que Magento 1 est une application très lourde, il est logique de séparer le bootstrap phpunit en un pour l'intégration et un pour les tests unitaires.
Le bootstrap de test unitaire n'a besoin que d'initialiser l'autochargeur, tandis que le bootstrap de test d'intégration doit initialiser tout l'environnement d'application, y compris le chargement de la configuration et la connexion db.
À cause de cela, les tests d'intégration dans Magento ont tendance à s'exécuter beaucoup plus lentement que les tests unitaires (encore plus que dans d'autres applications).

Amorçage de Magento dans phpunit

  • L'autochargeur de Magento n'est pas compatible PSR-0 car il lève une exception s'il ne trouve pas le fichier class_existsdans lequel se trouve une classe. Cela rompt certaines utilisations de dans phpunit. Il existe plusieurs solutions de contournement possibles (en cas de hacky):

    • Désenregistrez l'autochargeur Magento, encapsulant \Varien_Autoload::autoload()dans un décorateur en ignorant les exceptions levées, et enregistrez l'encapsuleur en tant que nouvel autochargeur. Cela a un faible risque de conflits avec les bibliothèques tierces qui enregistrent les chargeurs automatiques et dépendent d'une commande spécifique du chargeur automatique.
    • Utilisez un gestionnaire d'erreurs personnalisé encapsulant celui intégré à Magento 1. Le gestionnaire d'erreurs personnalisé avale les erreurs déclenchées par l'autochargeur Magento. C'est la solution utilisée par le framework de test de Raphael . Cela semble être le plus compatible avec d'autres extensions tierces.
    • Utilisez le hack de chemin d'inclusion pour remplacer \Varien_Autoload::autoload()afin de ne pas lancer l'erreur si le fichier n'existe pas. Cela entre cependant en conflit avec plusieurs modules qui remplacent également la même classe. Je n'utilise pas cette approche moi-même.
  • Pour éviter les erreurs de la session démarrée pendant les tests, définissez simplement $_SESSON = []le bootstrap.

  • Définissez un objet de réponse personnalisé via Mage::app()->setResponse($testResponse)qui étend le réel mais n'envoie pas de sortie ou d'en-têtes.

  • Pour réinitialiser Magento entre des tests d'intégration qui modifient complètement l'état d'exécution, utilisez Mage::reset(); Mage::app(). Notez qu'après cela, le gestionnaire d'erreurs devra être redécoré.

Agencements

Pour les appareils DB, j'ai tendance à utiliser les modèles habituels dans les méthodes d'appareils pour créer des appareils, par exemple createSimpleProduct($sku). Comme Raphael l'a dit, utilisez setUp()et tearDown()pour envelopper le test dans une transaction qui est annulée après le test (par exemple Mage::getSingleton('core/resource')->getConnection('default_setup')->beginTransaction()).

Pour les appareils de configuration de magasin, j'ai tendance à installer des appareils en mémoire uniquement à l'aide de Mage::app()->getStore()->setConfig($path, $value).

L' EcomDev_PHPUnitextension offre également la possibilité de créer des appareils DB à l'aide de fichiers yaml, mais pour moi, je trouve ceux-ci plus difficiles à maintenir par rapport aux appareils créés à l'aide de classes de modèles. YMMV.

Double test

Le registre peut être utilisé pour injecter des doublons de test pour les objets créés via Mage::getSingleton(), Mage::getResourceSingleton()et Mage::helper().
Certains autres objets centraux peuvent être activés Mage::app()(par exemple la demande).
Pour remplacer les classes créées via Mage::getModel()ou Mage::getResourceModel()avec des doubles de test, un wrapper d'objet de configuration personnalisé doit être utilisé. Voir cet exemple dans le framework de test de Raphael comment cela peut être accompli.

Résumé

Une fois Magento démarré, à peu près tout peut être testé assez bien. Soyez prêt à créer des moqueries profondes en raison de la grande quantité de méthode d'enchaînement utilisée par le code principal.
Même si la configuration est hacky, cela fonctionne bien et je trouve que les tests me donnent beaucoup de confiance et de valeur, à peu près comparable à une suite de tests pour une application Symphony.


Je ne l'ai jamais essayé mais pourquoi ne pas utiliser Magento Test Framework? ( docs.magento.com/m1/ce/user_guide/magento/… )
Fra

3
Oui, je l'ai essayé, mais c'est un test fonctionnel (pas unitaire ou d'intégration), c'est lent, c'est complexe et les tests ont tendance à être floconneux et cassants. Dans l'ensemble, j'ai considéré le temps passé avec elle comme une perte.
Vinai

@Vinai Je sais que c'est tard, mais généralement dans un contrôleur, il y a des appels au modèle et aux collections, dont nous n'aurons pas besoin pendant les tests. J'utilise votre framework de test (DigitalPianism), et là nous pouvons tester les modèles mais en faisant une requête get à une action de contrôleur qui à son tour utilise un modèle, comment puis-je me moquer de cet appel de modèle / collection?
arqam
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.