En blogs anteriores hemos hablado de la importancia de implementar tests en nuestros desarrollos de Odoo para evitar situaciones no deseadas. En este artículo, nos enfocaremos en explicaros cómo se deben implementar los tests en Odoo y buenas prácticas para hacerlos robustos y sostenibles en el tiempo.
Diferentes tipos de test que existen
Para comenzar, es necesario destacar que existen 3 tipos de test diferentes que se pueden implementar en Odoo y cada uno tiene una finalidad distinta. Cuando se habla en Odoo de Testing, lo más común es referirnos a los Python Unit Test, sin embargo, existen también los JavaScript Unit Test y los Tour Test. Veamos cada uno de ellos.
Python Unit Test
Los tests unitarios en Odoo se implementan gracias a la librería unittest de Python. Este tipo de tests se utilizan para verificar el funcionamiento del backend o servidor. Para estructurar los tests en nuestro módulo, debemos tener en cuenta lo siguiente:
- Dentro de nuestra carpeta del módulo se debe crear una subcarpeta llamada tests.
- Dentro de esta carpeta se debe incluir el fichero __init__.py, donde importaremos los ficheros de test que vayamos a crear. Así mismo, este archivo debe ser importado desde el archivo __init__.py del módulo.
- Es recomendable que cada archivo comience por “test_” seguido del modelo que se vaya a testear.
- Los test se crean mediante la implementación de clases de test, que pueden ser de diferentes tipos (TransactionCase, SingleTransactionCase, HttpCase) dependiendo de la naturaleza de la prueba.
- Inicialmente, dentro de nuestra clase, se debe declarar un método setUpClass donde establezcamos los datos comunes que se comparten en los tests de la clase. Se debe de tener en cuenta que, si modificamos los datos en un método, se modificarán para los siguientes.
- Luego iremos implementando métodos que ejecuten una parte de nuestro código y, mediante asserts, comprobar que la información obtenida es igual a los datos esperados. Los nombre de los tests deben comenzar necesariamente por “test_”.
Qué tener en cuenta al implementar Python Unit Tests
Lo aconsejado al implementar los Python Unit Test, es que los test prueben una funcionalidad concreta y lo más atómica posible, comenzando por el caso base de nuestra función e ir incrementado la complejidad del mismo.
Para que en el futuro sea más sencillo comprender el propósito del test y pueda ser mantenido mejor, es bueno que al comienzo del test se incluya una descripción del caso de uso que va a abordar, sus inputs que debe recibir y/o los outputs que debe tener.
Por otro lado, para hacer más sostenible nuestro test podemos crear en nuestra clase otros métodos auxiliares, si fuese necesario, que ejecuten un código necesario para el correcto funcionamiento del test. Esto es muy recomendable si este fragmento de código va a ser compartido por diversos test o si no es una característica intrínseca de la funcionalidad que estamos testeando.
Lo común y más recomendado es crear una clase en que cada fichero de test, y un fichero por cada modelo que queramos testear de nuestro módulo.
Una opción interesante es el uso de tags para organizar y ejecutar los test de manera selectiva (ej. post-install, at-install, standard).
Existen herramientas avanzadas muy útiles que podemos encontrar en la documentación de Odoo, que merece la pena mencionar, como Form, para simular la creación de un formulario y su guardado, para crear un registro como si de la interfaz de Odoo se tratase, M2MProxy o 02MProxy.
JS Unit Test
Los tests de JavaScript en Odoo se ejecutan en el navegador y se recomiendan cuando se maneja una lógica compleja en el frontend. Estos se implementan con QUnit o Hoot (según la versión de Odoo), que proporciona una interfaz web para la ejecución de tests. Cosas que debemos tener cuenta a la hora de implementar tests JS:
- Los archivos de test deben alojarse en some_addon/static/tests/.
- Se debe escribir la menor cantidad de código posible para que el test funcione correctamente.
- Es mejor dividir un test grande en varios más pequeños, ya que son más fáciles de entender y mantener.
- Siempre limpiar después de cada test, por ejemplo, destruyendo widgets creados.
- A veces es complicado cubrir todo el código, pero agregar algunos tests ayuda a detectar errores antes de que lleguen a producción.
- Se recomienda incluir afirmaciones positivas y negativas dentro del mismo test para evitar que se vuelvan inútiles si cambian elementos como las clases CSS.
- Para depurar, se puede usar QUnit.only(…) para ejecutar un solo test temporalmente y activar el debug mode en las funciones auxiliares.
Tour Test o Test de Integración
Los tour tests son los menos conocidos y utilizados pero viene bien para comprobar flujos completos y garantizar la correcta implementación de un caso de uso definido en nuestro sistema. Estos tests combinan pruebas de backend con frontend y permiten validar la interacción entre ambos. Para poder implementarlos, debemos saber que:
- Se alojan en my_addon/static/tests/tours y deben agregarse a los assets en el __manifest__.py.
- Son útiles y necesarios cuando se maneja lógica compleja en JavaScript que interactúa con el backend.
- Se pueden ejecutar y depurar desde el navegador, tanto en entornos locales como en pruebas o producción, lo que lo hace verdaderamente poderoso para depurar errores en el mismo sistema de producción.
- Permiten realizar capturas de pantalla en formato png para analizar visualmente el estado de la aplicación.
Extra tip: Query Counts Assertion
Para garantizar que nuestras pruebas sean eficientes, se recomienda utilizar Query Counts Assertion, que nos ayuda a identificar si el código ejecuta más consultas SQL de las necesarias, optimizando el rendimiento.
Buenas prácticas en la implementación de tests
Por último queremos reseñar y aclarar algunas buenas práticas que hemos mencionado durante el artículo que hará que nuestra implementación y mantenimiento de test no sea una odisea y logremos el principal cometido, que es ayudarnos a garantizar la fiabilidad y el mantenimiento de nuestro software
- Explicar al inicio del test su finalidad, por ejemplo:
"""Cuando creamos una petición de vacaciones y establecemos más días de los que tenemos pendientes, se debe mostrar un mensaje de denegación de las vacaciones al usuario."""
- Hacer los test lo más atómicos posibles e ir incrementando la complejidad de los mismos con diferentes casos
- Centralizar la configuración en setUpCass() y reutilizar métodos auxiliares, dejando la creación de test solo para seguir el flujo del sistema e ir comprobando sus datos, haciéndolo más limpio y claro sin meter código de por medio.
- Al heredar clases en nuestro módulo, es aconsejable heredar sus clases de tests si ya existe para aprovechar la configuración existente y reutilizar aquellos datos que nos hagan falta.
Con estas prácticas podrás lidiar con la implementación de test sin ningún problema y asegurate un desarrollo robusto y sostenible en Odoo. Si quieres indagar más sobre el testeo en Odoo no dudes en consultar la documentación oficial. Además puedes aprender más sobre testing con los vídeos del canal de Youtube de la Asociación Española de Odoo (AEOdoo) o también en artículos de nuestro blog de Dixmit. ¡Felices pruebas!