Mejores prácticas para pruebas unitarias en Magento 1.9

11

Mantengo un sitio Magento 1.9 con varios módulos personalizados. Parte de la funcionalidad es crítica para el negocio y necesita urgentemente algunas pruebas unitarias. Por ejemplo, una calculadora de precio unitario.

Normalmente desarrollo en Symfony y realmente preferiría usar PHPUnit (w / Composer) de alguna manera si es posible.

Algunas funciones se basan en datos importados a varias tablas de bases de datos personalizadas, por lo que preferiría cargar de alguna manera los accesorios.

Así que estoy buscando el enfoque de mejores prácticas para escribir algunas pruebas unitarias. Glady aceptaré tutoriales o algo similar. Cualquier ayuda es apreciada.

frigg
fuente

Respuestas:

10

Me enfrenté al mismo problema hace un tiempo.

Pensé en usar el módulo Ecomdev PHPUnit, pero me resulta difícil de usar y está mal documentado (pero todavía me encanta lo que hace Ivan y su gran contribución al ecosistema de Magento).

Entonces, con la ayuda de Vinai, terminé desarrollando el siguiente módulo de marco de prueba: https://github.com/digitalpianism/testframework

El propósito original era para las pruebas de integración, pero también lo estoy usando para las pruebas unitarias. Puede verlo en acción aquí: https://github.com/digitalpianism/easytoplinks/blob/master/app/code/community/DigitalPianism/EasyToplinks/Test/Unit/Block/Page/Template/LinksTest.php

Con respecto a los accesorios, estoy usando reversiones de transacciones para evitar crear datos de muestra en la base de datos.

Raphael en Digital Pianism
fuente
Esto se ve muy prometedor. Voy a tratar de salir. Gracias.
Viernes
13

Instalación

Dado que Magento 1 no usa el compositor de fábrica, no creo que haga una gran diferencia si instala phpunit usando el compositor o simplemente descarga la versión phar .
Si ya usa Composer para administrar otros módulos o bibliotecas de terceros en su sitio, entonces Composer probablemente tenga más sentido. Sin embargo, a menos que use PHP7, estará limitado a una versión anterior de phpunit (es por eso que me vinculé a la versión 4.8 anterior).

Pruebas de integración vs / y / o pruebas unitarias

Dado que Magento 1 es una aplicación tan pesada, tiene sentido separar el arranque de phpunit en uno para integración y otro para pruebas unitarias.
El programa de arranque de prueba de la unidad solo necesita inicializar el autocargador, mientras que el programa de arranque de prueba de integración debe inicializar todo el entorno de la aplicación, incluida la carga de configuración y la conexión db.
Debido a que las pruebas de integración en Magento tienden a ejecutarse mucho más lentamente que las pruebas unitarias (aún más que en otras aplicaciones).

Bootstrapping Magento en phpunit

  • El cargador automático de Magento no es compatible con PSR-0, ya que arroja una excepción si no puede encontrar el archivo en el que se encuentra una clase. Esto rompe algunos usos de class_existsphpunit. Hay varias soluciones posibles (si es hacky):

    • Anule el registro del cargador automático de Magento, envuélvala \Varien_Autoload::autoload()en un decorador, ignorando las excepciones lanzadas dentro, y registre el contenedor como un nuevo cargador automático. Esto tiene pocas posibilidades de conflictos con las bibliotecas de terceros que registran cargadores automáticos y dependen de un orden específico del cargador automático.
    • Utilice un controlador de errores personalizado que envuelva el integrado en Magento 1. Los controladores de errores personalizados tragan los errores activados por el cargador automático de Magento. Esta es la solución que utiliza el marco de prueba de Raphael . Esto parece ser el más compatible con otras extensiones de terceros.
    • Use el hack de ruta de inclusión para anular \Varien_Autoload::autoload()y no arrojar el error si el archivo no existe. Sin embargo, esto entra en conflicto con varios módulos que también anulan la misma clase. Yo no uso este enfoque yo mismo.
  • Para evitar errores durante el inicio de la sesión durante las pruebas, simplemente configure $_SESSON = []en el arranque.

  • Establezca un objeto de respuesta personalizado a través de Mage::app()->setResponse($testResponse)que extienda el real pero no envíe salida o encabezados.

  • Para reiniciar Magento entre pruebas de integración que cambian completamente el estado de tiempo de ejecución, use Mage::reset(); Mage::app(). Tenga en cuenta que después de eso, el controlador de errores tendrá que volver a decorarse.

Accesorios

Para los accesorios DB, tiendo a usar los modelos regulares en los métodos de accesorios para crear accesorios, por ejemplo createSimpleProduct($sku). Como dijo Raphael, use setUp()y tearDown()para ajustar la prueba en una transacción que se revierte después de la prueba (por ejemplo Mage::getSingleton('core/resource')->getConnection('default_setup')->beginTransaction()).

Para los dispositivos de configuración de la tienda, tiendo a configurar dispositivos solo en memoria usando Mage::app()->getStore()->setConfig($path, $value).

La EcomDev_PHPUnitextensión también ofrece la opción de crear dispositivos de base de datos utilizando archivos yaml, pero para mí es más difícil de mantener en comparación con los dispositivos creados usando clases de modelos. YMMV.

Dobles de prueba

El registro se puede usar para inyectar dobles de prueba para objetos creados mediante Mage::getSingleton(), Mage::getResourceSingleton()y Mage::helper().
Se pueden establecer algunos otros objetos centrales Mage::app()(por ejemplo, la solicitud).
Para reemplazar las clases creadas mediante Mage::getModel()o Mage::getResourceModel()con dobles de prueba, se debe usar un contenedor de objetos de configuración personalizado . Vea este ejemplo en el marco de prueba de Raphael cómo se puede lograr eso.

Resumen

Una vez que Magento se inicia, casi todo se puede probar bastante bien. Sin embargo, prepárate para crear simulacros profundos debido a la gran cantidad de métodos que encadena el código central.
Aunque la configuración es hacky, funciona bien y creo que las pruebas me dan mucha confianza y valor, más o menos comparable a un conjunto de pruebas para una aplicación Symphony.

Vinaí
fuente
Nunca lo probé, pero ¿por qué no usar Magento Test Framework? ( docs.magento.com/m1/ce/user_guide/magento/… )
Fra
3
Sí, lo he intentado, pero es una prueba funcional (no unidad o integración), es lenta, es compleja y las pruebas tienden a ser escamosas y frágiles. En general, consideré un desperdicio el tiempo que pasé con él.
Vinai
@Vinai Sé que es tarde, pero en general en un controlador hay llamadas a modelos y colecciones, que durante las pruebas no necesitaremos. Estoy usando su marco de prueba (DigitalPianism), y allí podemos probar Duplicar los modelos, pero al hacer una solicitud de obtención de una acción de controlador que a su vez usa un modelo, ¿cómo puedo burlarme de esa llamada de modelo / colección?
arqam