Pasar al contenido principal

Aljibe: calidad y testeo para desarrollos Drupal con DDEV

Aljibe es un add-on de DDEV que proporciona herramientas y una base seleccionada para el desarrollo de proyectos de Drupal. Es lo que usamos en Metadrop como base para cada proyecto. Aunque está adaptado a nuestras necesidades, por lo que asume ciertas decisiones, sigue la llamada Drupal way y creemos que también puede ser útil para muchos otros equipos de desarrollo.

Está construido como un conjunto de add-ons de DDEV, siendo Aljibe el principal. Muchas de las herramientas que ofrece son proporcionadas por add-ons de DDEV que se puede usar de forma independiente si no se quiere usar Aljibe completo. Se puede consultar los add-ons que Metadrop proporciona en nuestro registro de complementos de DDEV.

Además, Aljibe utiliza Metadrop/drupal-dev para declarar las dependencias de todas las herramientas que proporciona. Es un paquete de Composer, no un add-on de DDEV. Es posible usarlo directamente, o puede servir como inspiración para crear una base de proyectos propia.

El objetivo principal de Aljibe, además de agilizar el inicio de los proyectos, es proporcionar una base sólida con muchas herramientas orientadas al control de calidad para el desarrollo de proyectos con altos estándares de calidad. Este es el verdadero enfoque de Aljibe: la calidad.

Entre las herramientas que proporciona se encuentran Behat, BackstopJS, PHPStan, PHP CodeSniffer, Unlighthouse, múltiples linters, un espacio para la documentación y algunas herramientas para facilitar ciertas acciones sobre Drupal como configurar rápidamente un sitio (o multisitio).

Uno de los enfoques que seguimos con Aljibe es colocar todos los archivos del proyecto en el repositorio del proyecto. Esto incluye no solo el código, sino también la documentación técnica, los scripts del proyecto, la configuración y los datos de prueba, y todo lo que puedas necesitar para empezar a trabajar en el proyecto. Esto evita tener la información del proyecto dispersa en diferentes herramientas y lugares, y facilita el onboarding.

Veamos lo que puedes encontrar en Aljibe.

Directorio base 

Aljibe proporciona una estructura de carpetas para todos las necesidades habituales de Drupal. Al crear un proyecto usando Aljibe se obtienen las siguientes carpetas:

  • backups: Una carpeta para almacenar cualquier copia de seguridad manual que puedas necesitar durante el desarrollo. Esta carpeta es ignorada por Git.
  • config: Una carpeta para la configuración del sitio de Drupal. Dentro, encontrarás una carpeta common para la configuración principal y una carpeta envs para las divisiones de configuración ('configuration splits'). Echa un vistazo a su archivo README.md para obtener más información sobre cómo organizar tu configuración de Drupal en escenarios más complejos.
  • docroot y public_html: Enlaces simbólicos a la carpeta 'web'. Se proporcionan para la compatibilidad con algunos entornos de alojamiento que podrían no funcionar bien con 'web' como la raíz del documento.
  • docs: Una carpeta para la documentación del proyecto. Consulta la sección de MkDocs para más información.
  • drush: Aquí es donde reside la configuración de Drush del proyecto, incluyendo alias, políticas y comandos personalizados de Drush.
  • patches: Se recomienda descargar los parchs y comitearlos localmente, y esta carpeta está destinada a almacenar esos parches descargados.
  • postman: Una carpeta con colecciones y entornos de Postman para ser ejecutados usando Newman (ver más abajo).
  • private-files: Contiene los archivos privados de Drupal. Los archivos privados no deben almacenarse bajo la raíz del documento del sitio web, por lo que se almacenan aquí.
  • recipes: Un lugar para almacenar recetas para este proyecto. Si no estás familiarizado con las recetas de Drupal, ¡ahora es el momento de investigar!
  • reports: Algunas herramientas proporcionadas por Aljibe generan informes, que generalmente se colocan aquí.
  • scripts: Si tu proyecto necesita un script personalizado, aquí es donde puedes almacenarlo.
  • tests: Aljibe está muy enfocado en las pruebas. La configuración de las herramientas de prueba y los datos de prueba se almacenan aquí.

Este conjunto de carpetas cubre la mayoría de las necesidades de Drupal siguiendo la Drupal way (por ejemplo, carpetas que deben estar fuera del docroot, una carpeta para las nuevas recipes de Drupal, informes, etc.).

Análisis estático de código

Aljibe proporciona muchas herramientas para el análisis de código estático. Dado que no es trivial ejecutar cada una de ellas, Aljibe ofrece dos formas sencillas de ejecutar todas las herramientas de análisis: GrumPHP y phpqa.

Ambas herramientas sirven como wrapper para el resto de herramientas, pero cada una se ejecuta de manera diferente y en situaciones distintas.

GrumPHP

La primera forma es automática y se ejecuta antes de cada commit gracias a GrumPHP. Verifica el contenido del commit para asegurarse de que cumple con varias políticas: ejecuta PHPStan, PHP CodeSniffer y varios linters en el código añadido. También comprueba el archivo composer.json, el tamaño de los archivos de imagen y el mensaje del commit, entre otras cosas. Y sí, es cierto que puede ser molesto a veces, pero es la primera barrera para mantener el código de baja calidad fuera del proyecto. Siempre se puede saltar al hacer un commit, aunque hay sentirte un poco mal cada vez que se haga. Puede GruimPHP que sea gruñón, pero lo hacer para cuidar del proyecto.

Aljibe ya añade el hook de Git para GrumPHP se ejecute en cada commit automáticamente.

phpqa

Es similar a GrumPHP en el sentido de que ejecuta muchos analizadores de código estático sobre el código. Sin embargo, esta herramienta está pensada para ser utilizada en CI/CD, o manualmente en una máquina de desarrollo. De nuevo, utiliza PHPStan, PHP CodeSniffer, linters, PHPMD, etc.

Se puede ejecutar phpqa fácilmente mediante un solo comando:

ddev exec phpqa

Los analizadores

Veamos algunas de las herramientas que GrumPHP y phpqa usan internamente.

PHPStan

Esta herramienta analiza el código buscando posibles errores y bugs. Yo diría que es una herramienta indispensable y, de hecho, se utiliza por defecto en los GitLab Drupal Templates.

Para ejecutar PHPStan manualmente usa el siguiente comando:

ddev exec phpstan

Está configurado para revisar el código custom porque se supone que el código contribuido ya tiene sus propios mecanismos de revisión. Sin embargo, es posible ejecutarlo en cualquier parte del código manualmente.

Para analizar una carpeta concreta basta con añadir la ruta:

ddev exec phpstan analyze /path/to/folder

De forma predeterminada, PHPStan está configurado en el nivel 8. Esto es bastante estricto, pero todos los proyectos que desarrollamos desde cero usan este nivel. A veces puede ser un poco molesto, pero los beneficios bien valen la pena.

phpcs 

PHP Code Sniffer revisa los estándares de codificación de Drupal, incluso corrigiendo algunos de ellos automáticamente, y está preconfigurado para que no tengas que hacer nada.

Además de ser ejecutado por GrumPHP y phpqa, puedes ejecutarlo manualmente

ddev exec phpcs

Ese comando analizará el código custom (la opción por defecto).

Para analizar una carpeta específica basta con añadir la ruta al final del comando:

ddev exec phpcs /path/to/folder

PHPMD

PHP Mess Detector analiza el código, buscando posibles errores, código subóptimo, expresiones demasiado complicadas y parámetros, métodos y propiedades no utilizados.

Si se necesita ejecutarlo a mano en lugar de esperar a GrumPHP o ejecutar phpqa, puede ser llamado con este comando:

ddev exec phpmd /path/to/fodler/or/file format ruleset

La opción -h permite ver todos los posibles formatos de informe (cómo la herramienta muestra los resultados) y los  ruleset o conjunto de reglas. Para los conjuntos de reglas, puedes proporcionar más de uno separándolos con comas.

Linters

Los linters para archivos YAML y JSON son ejecutados por GrumPHP y PHPQA. Por supuesto, también se pueden ejecutar manualmente. Revisa la carpeta vendor/bin y juega con los ejecutables que encuentres allí.

Herramientas de testeo

Como Aljibe se enfoca en la calidad, no solo proporciona analizadores de código estático, sino también herramientas de testeo completas. Todas estas herramientas se pueden ejecutar desde la línea de comandos o en un sistema CI/CD. De hecho, en Metadrop tenemos todas estas herramientas integradas en nuestro flujo de trabajo de control de calidad automático de nuestros proyectos.

PHPUnit

Esta es la herramienta de tests estándar de Drupal, pero desafortunadamente, es necesario configurarla antes de usarla. Aljibe se encarga de esto, proporcionando un archivo de configuración que funciona sin más modificaciones.

Media widget. Press Enter to type after or press Shift + Enter to type before the widgetddev exec phpunit

Este comando ejecute todos los tests de PHPUnit, incluyendo los del core, lo que probablemente no sea lo que se necesita habitualmente.

Para testear un módulo concreto basta con añadir la ruta adecuada:

ddev exec /path/to/module

Behat

Behat es una herramienta de Desarrollo Guiado por el Comportamiento (BDD) que permite escribir tests que describen cómo debería comportarse una aplicación desde el punto de vista de las interacciones del usuario (Historias de Usuario). Las pruebas se escriben en lenguaje natural, lo que las hace más fáciles de entender que las pruebas de código puro. Cada prueba consta de varios pasos, y cada paso puede realizar una acción en el sitio (visitar una URL, crear contenido, hacer clic en botones y enlaces, esperar a AJAX, ejecutar 'cron' y muchas otras acciones) o verificar algo (si un texto está presente, si un elemento es visible, si la URL actual coincide con una expresión determinada, etc).

Además, se incluyen algunas librerías para mejorar el soporte de Drupal, añadiendo varios pasos de Behat para los casos de uso más comunes, como iniciar sesión como un usuario con un rol particular, crear contenido de prueba o buscar expresiones dentro de regiones de contenido específicas.

Las librerías incluidas son:

Behat está preconfigurado, por lo que se pueden ejecutar las pruebas básicas proporcionadas como ejemplo pr Aljibe con el siguiente comando:

ddev behat

Al ejecutar estos tests se obtendrá una salida como esta: 

Behat execution output with tests results

Notar que Aljibe añade un plug-in para mostrar el tiempo consumido por cada tipo de paso. Los tests pueden requerir mucho tiempo para ser ejecutados, y es bastante útil poder localizar oportunidades de optimización como parte de la salida de los tests.

BackstopJS

BackstopJS es una herramienta de regresión visual. Compara un conjunto de capturas de pantalla de una lista de URLs con un conjunto de capturas de pantalla de referencia. Si hay una diferencia significativa, el test se marca como erróneo. También se pueden comparar partes de la página web renderizada, como elementos específicos usando selectores de CSS. Esta herramienta detecta errores en CSS, en el renderizado o incluso en el contenido que no serían detectados por herramientas de prueba que verifican la funcionalidad. Además, proporciona un informe para detectar fácilmente el problema.

A BackstopJS report screenshot displaying an error because article tags disspeared.

A BackstopJS report screenshot displaying an error because article tags disspeared.

BacktopJS viene preconfigurado. Para generar las imágenes de referencia hay que lanzar el siguiente comando:

ddev backstopjs reference

Más adelante, para generar nuevas capturas y comprarlos con las imágenes de referencia, hay que usar:

ddev backstopjs test

Pa11y

Pa11y es una herramienta de accesibilidad que carga páginas web y resalta cualquier problema de accesibilidad que encuentre. Dado que la accesibilidad es cada vez más importante, no solo porque debemos crear sitios web inclusivos sino también porque es un requisito legal, esta herramienta es inestimable.

ddev pa11y

Los resultados se obtienen casi inmediatamente:

Una salida pa11y que informa de un error en una imagen porque no hay texto alternativo

Pa11y encuentra una imagen sin alt text.

Pa11y puede ser lanzado sobre cualquier URL, no solo el proyecto local:

ddev pa11y https://random.site

Newman

A veces se necesitan probar API, y Newman es una buena opción para ello. Esencialmente, es una herramienta de CLI que puede ejecutar colecciones de Postman e detectar cualquier resultado inesperado. Aljibe proporciona un contenedor para Newman y un ejemplo base de test. El ejemplo es interesante: prueba que la Dynamic Page Cache del sitio está funcionando. Se pueden testear otras cabeceras, o incluso la API del sitio, si es que ofrece una.

Ejecutarlo requiere algunos parámetros ya que no hay valores predeterminados que puedan valor siempre: Newman requiere una colección y un entorno para ejecutarse. Para ejecutar el ejemplo proporcionado por Aljibe se puede usar el siguiente comando:

ddev newman run postman/collections/example_cache_headers.postman_collection.json -e postman/envs/example_ddev.postman_environment.json

Newman ejecutará la colección y mostrará una tabla con el resultado:

Salida de una ejecución de una colección de Newman

Ejecución de una colección sencilla de Newman.

Unlighthouse

Lighthouse es una herramienta automatizada de auditoría, métricas de rendimiento y mejores prácticas para la web que se puede encontrar en los navegadores basados en Chromium. Si bien es una buena herramienta, solo analiza una URL. Unlighthouse, por su parte, detecta las páginas de un sitio y ejecuta Lighthouse en cada URL descubierta, ofreciendo un informe resumido de todos los resultados.

Reporte de Unlighthouse, que muestra la puntuación del sitio web a partir de las puntuaciones individuales de las páginas de Lighthouse.

Un ejemplo de informe de Unlighthouse.

Unlighthouse ofrece maneras de limitar el número de páginas que visita y también detecta automáticamente patrones comunes para evitar bombardear el sitio con URL que pueden tener puntuaciones similares de Lighthouse.

Para lanzarlo se debe usar el siguiente comando:

ddev unlighthouse

Al final de la ejecución, Unlighthouse se queda en ejecución porque el informe que ofrece debe servirse a través de un servidor web para que funcione correctamente. Una vez terminada la revisión del informe se puede detener.

Para los sistemas de CI/CD, se proporciona el comando unlighthouse-ci. Es casi lo mismo que el comando anterior, pero Unlighthouse genera el informe y se detiene sin servirlo. Debido a que los sistemas de CI/CD suelen permitirte servir artefactos—y el informe es un artefacto—normalmente se puede consultar sin problema.

Entornos de test y prueba de humo

Las herramientas de testeo que proporciona Aljibe están configuradas para poder tener diferentes entornos de prueba, es decir, diferentes configuraciones de prueba por entorno. Normalmente, se prueba todo en cada entorno, especialmente antes de pasar a producción, para asegurar que todo funcione correctamente. Sin embargo, a veces hay diferencias sutiles que deben ser tenidas en cuenta.

Esto abre la puerta a las pruebas de humo (smoke tests). ¿Qué pasa si el proceso de despliegue falla dejando algo roto en producción? ¿Quién no ha navegado manualmente por el sitio después de un despliegue solo para asegurarse de que todo está en su lugar? Supongo que todos lo hemos hecho en algún momento. Lo bueno es que esto también se puede automatizar. Se puede ejecutar un conjunto diferente de pruebas en producción usando la configuración para el entorno de producción. Por ejemplo, se podría ejecutar BackstopJS para comprobar que el sitio se renderiza correctamente. O ejecutar Behat para probar la funcionalidad de búsqueda del sitio y confirmar que los usuarios pueden seguir buscando.

Estas pruebas, llamadas pruebas de humo, no prueban a fondo todo el sitio. Solo prueban los errores más obvios y críticos, como la página de inicio, la búsqueda o la renderización de la página. No alteran la web testeada y son similares a lo que se haría manualmente para asegurarte de que el proyecto sigue funcionando sin errores graves.

Documentation

Esta es una parte fundamental de un proyecto, que a menudo recibe menos importancia de la debida. Un problema habitual es que la documentación se encuentre dispersa en diferentes aplicaciones y recursos. Si bien hay muchas maneras de organizar la documentación, especialmente para proyectos grandes con múltiples tipos de usuarios—desde desarrolladores y DevOps hasta editores y personal de marketing—nuestro enfoque es mantener la documentación técnica del proyecto vinculada al código fuente, dentro del mismo repositorio. Esta documentación puede cubrir la arquitectura, la configuración del entorno, las operaciones o cualquier otra información útil para el personal de DevOps y de desarrollo.

Es por ello que Aljibe incluye MkDocs con Material. Juntos, ambos proporcionan una potente herramienta de documentación que es muy fácil de usar. Ofrece sintaxis Markdown, además de muchas otras características, incluyendo el resaltado de sintaxis, pestañas, formato con imagenes, diagramas de Mermaid y funcionalidad de búsqueda.

Una colección de ejemplos de MkDocs Material: diferentes tipos de notas, botones, pestañas, resaltado de sintaxis y diagramas Mermaid.

Varios ejemplos de las posibilidades de MkDocs Material.

Cuando DDEV lana el proyecto, este sistema de documentación basado en MkDocs, también es levatado y esá disponible para ser consultado y editado.

Onboarding

El onboarding es siempre un momento difícil, o al menos incómodo. Te unes a un proyecto existente que lleva desarrollándose durante meses y careces de familiaridad sobre su funcionamiento. En muchos casos esto significa que tener que preguntar al equipo para entender cómo configurar el entorno local y qué trucos de magia tecnológica se requieren para que funcione en local correctamente.

Es por ello que Aljibe proporciona algunos comandos para facilitar este proceso, junto con el sistema de documentación.

El comando site-install configura el proyecto automáticamente usando una exportación de la configuración de Drupal de la carpeta config o un volcado de la base de datos. En el primer caso, ni siquiera hace falta un parámetro, basta con ejecutar lo siguiente:

ddev site-install

En el segundo caso se debe pasar la ruta a un fichero con el volcado de la base de datos.

ddev site-intall /path/to/db/dump

En ambos casos el proyecto se inicia usando DDEV, se elimina cualquier base de datos anterior, los assets del front end se construyen usando npm, y los archivos de configuración, como settings.local.php, se copian a los lugares correctos. Aljibe incluso ofrece un sistema de hooks en caso de que el proyecto necesite ejecutar comandos especiales en ciertas etapas: antes y después de la configuración, antes y después de una instalación del sitio, y antes y después de la instalación desde la configuración o desde un volcado de la base de datos.

Cuando tengo que unirme a un proyecto, me basta con clonar el repositorio y ejecutar ddev setup, y la mayoría de las veces obtengo un proyecto funcional sin mayor esfuerzo.

El comando setup utiliza otros comandos, como site-install y frontend, por debajo. El primero realiza la instalación real, mientras que el segundo usa npm para compilar el theme.

Instalar desde configuración

Esto probablemente merezca un artículo aparte, pero en Metadrop solemos desarrollar y lanzar los tests sobre los proyectos con un el sitio instalado desde configuración. Esto permite tiempos de configuración más rápidos, ya que cargar un volcado de la base de datos puede llevar mucho tiempo. También significa que no tenemos que preocuparnos por sanear volcados de la base de datos o manejar datos sensibles; simplemente no gestionamos datos delicados. Dado que siempre se necesita cierto contenido, usamos el módulo Default Content para crear todo el contenido de prueba. 

Por supuesto, a veces aparece un bug oscuro que solo puede reproducirse con datos reales. En ese caso, con las medidas de seguridad adecuadas, no queda más remedio que cargar un volcado de la base de datos.

Otras herramientas

Aún hay más en Aljibe. ¿Actualización automática del core y de módulos y themes? Lo tiene. ¿Soporte para multisitios? Disponible. ¿Un interfaz gráfico para labase de datos? También lo tiene.

Actualizaciones automáticas

Actualizar un sitio de Drupal es una tarea tediosa que debe hacerse con frecuencia. La buena noticia es que con una buena cobertura de tests el proceso es automatizable. Es por ello que hace tiempo desarrollamos Drupal Updater, habiéndolo usado ya durante más de dos años. Es un paquete de PHP que actualiza automáticamente el core de Drupal, los módulos, los themes y el resto de dependencias. Crea una rama con todas las actualizaciones que, si los tests pasan, se puede mergear de forma segura con la rama principal para obtener todo actualizado casi sin esfuerzo. Si tienes curiosidad sobre esto, puedes leer más en este artículo: Drupal Updater: Simplificando el mantenimiento de actualizaciones de proyectos Drupal desde la consola.

Y, por supuesto, está incluido en Aljibe. Para actualizar un proyecto solo es necesario ejecutar el siguiente comando:

ddev exec drupal-updater

Quizá ahora te haya venido a la cabeza el módulo Automatic Updates. Si bien este módulo es una gran idea, creo que está más enfocado a usuarios menos experimentados. Además, no soporta actualizaciones menores del núcleo por defecto (aunque se puede habilitar), y la actualización de módulos y temas contribuidos aún es experimental. Drupal Updater es estable, probado y carece de estas limitaciones. Es, eso sí, más orientado a desarrollo.

Soporte mulitsitio 

Aljibe es compatible con proyectos multisitio. Los comandos que ofrece se pueden ejecutar apuntando a un sitio, o las herramientas utilizadas pueden ser configuradas para diferentes sitios. Incluso proporciona un comando para crear una nueva base de datos en el contenedor de la base de datos:

ddev create-database second_site

Adminer

Cuando se necesita acceder y revisar los datos de una base de datos, una interfaz gráfica puede ser bastante útil. Aljibe viene con Adminer, que proporciona una interfaz web compatible con MariaDB, MySQL, PostgreSQL y aún otras bases de datos.

Acceder a ella es tan simple como ejecutar un comando:

ddev adminer

Esto lanza un navegador local con los parámetros apropiados para iniciar sesión en la base de datos sin problemas:

An screenshot of the command `ddev adminer` with the resulting browser window running Adminer

 

¿Cómo empezar a usarlo?

Hay que seguir tres simples pasos.

Primero, inicializar DDEV en un directorio vacío:

ddev config --auto

Segundo, instalar Aljibe:

ddev add-on get metadrop/ddev-aljibe

Por último, ejecutar el asistente de Aljibe, que va haciendo preguntas para personalizar la instalación mientas la va realizando.

ddev aljibe-assistant

Quizá te preguntes, ¿puedo usarlo en proyectos ya existentes? Y la respuesta es que sí, es perfectamente posible. Se requieren más pasos, pero no es complicado. Echa un ojo a la sección Add Aljibe to existing project el repositorio de Aljibe.

Planes de futuro para Aljibe

Aljibe condensa gran parte de nuestra forma de desarrollar proyectos. A algunas personas les puede parecer que no se ajusta a sus necesidades, y es por ello que queremos hacerlo más flexible. Por ejemplo, Aljibe también instala Redis, pero esto no siempre es necesario. Planeamos usar el nuevo sistema de dependencias dinámicas de DDEV para instalar estos contenedores solo si un usuario realmente los quiere. Creemos que esto es clave si queremos Aljibe sea más usado por la Comunidad.

También instala un Artisan y crea un subtheme basado en él. Esto se debe a que es nuestra forma habitual de trabajar, pero entendemos que, aunque nos gusta Artisan, debería ser un paso opcional.

Además, dado que recientemente estamos usando Hoppscotch, la alternativa (en gran parte) Open Source a Postman y Newman, estamos pensando en añadir un nuevo add-on de DDEV para ejecutar colecciones de Hoppscotch, similar al add-on actual de Newman.

La idea es seguir desarrollando Aljibe mientras escuchamos lo que desde la Comunidad de Drupal se pueda opinar, y hacerlo así más atractivo como una herramienta de desarrollo local para proyectos Drupal. Nos encantaría saber de otros equipos que usen Aljibe, y estamos convencidos de que puede ser una herramienta muy útil para muchos de ellos. Así que, si crees que las funcionalidades que ofrece pueden ayudarte, pruébalo y cuéntanos qué te pareció, nos gustaría mucho conocer opiniones desde otros puntos de vista.

 

RIcardo Sanz Ante

Ricardo Sanz

CTO