Lucas Fiege

Configurar Laravel Dusk + Pipelines Gitlab CI

Laravel Dusk Logo Original image stored in Laravel News

La suite de testing Laravel Dusk es un paquete oficial que nos permite ejecutar pruebas dentro del navegador web con la finalidad de asegurarnos de que ciertos comportamientos se ejecuten correctamente y/o se puedan visualizar/ocultar elementos del DOM, entre muchas otras posibilidades. (Asumiré de que estamos trabajando con Laravel 5.5 y Dusk 2.0 en adelante)

Para ejecutar estas pruebas, normalmente basta con crear un archivo específico de acuerdo a la documentación y seguir los pasos de acuerdo a lo que se quiera probar. Y finalmente ejecutar dicha prueba mediante la terminal de nuestro equipo; posteriormente podremos ejecutar todas las pruebas en conjunto para ver el estado global del proyecto según las pruebas, lo cual nos permitirá realizar refactorizaciones con facilidad y aumentar el nivel de confianza en el código de la aplicación. (Lo cual no implica que sea 100% infalible). Sí, últimamente adopté por fin la metodología TDD para mis desarrollos, acá un porqué de ello.

En la documentación de Laravel Dusk se ofrecen ejemplos de configuraciones para ejecutarlo en entornos de integración contínua (CI), por defecto: Circle CI y Travis CI.

Para quienes tenemos nuestros repositorios en GitLab y queremos aprovechar las herramientas que nos provee, existe una alternativa viable: los gitlab-runners, los cuales nos permiten ejecutar nuestras pruebas para asegurar el correcto estado del sistema en desarrollo para todo el equipo de desarrollo. E incluso nos permite mejorar los procesos, ya que podríamos agregar auto-deployment una vez dadas las condiciones, y quitarnos otra tarea de encima, permitiendo concentrarnos en lo que importa: el código.

Configuración básica

Asumiendo de que tenemos pruebas escritas para Laravel Dusk (además podemos tenerlas escritas para la suite básica HTTP y/o browser-kit-testing), debemos añadir el siguiente archivo a la raíz del proyecto: gitlab-ci.yml.

stages:
  - build
  - test

variables:
  MYSQL_ROOT_PASSWORD: root
  MYSQL_USER: homestead
  MYSQL_PASSWORD: secret
  MYSQL_DATABASE: homestead
  DB_HOST: mysql
  DB_CONNECTION: mysql

build:
  stage: build
  services:
     - mysql:5.7

  image: chilio/laravel-dusk-ci:stable
  script:
    - composer install --prefer-dist --no-ansi --no-interaction --no-progress --no-scripts
  cache:
      key: ${CI_BUILD_REF_NAME}
      paths:
        - vendor
        - node_modules
        - public
        - resources


test:
  stage: test
  cache:
    key: ${CI_BUILD_REF_NAME}
    paths:
      - vendor
      - node_modules

  services:
    - mysql:5.7

  image: chilio/laravel-dusk-ci:stable
  script:
    - cp .env.gitlab .env
    - configure-laravel
    - start-nginx-ci-project
    - ./vendor/bin/phpunit -v --coverage-text --colors --stderr --stop-on-failure
    - php artisan dusk --colors --debug --stop-on-failure

  artifacts:
    paths:
      - ./storage/logs # for debugging
      - ./tests/Browser/screenshots
      - ./tests/Browser/console
    expire_in: 7 days
    when: always

Vamos a utilizar como base la imagen de docker chilio/laravel-dusk-ci en su versión estable, la cual nos permitirá ahorrar tiempo y esfuerzo para configurar el entorno de ejecución del servidor. Además provee de ciertos comandos utilizados en el archivo .yml que permiten inicializar la configuración para facilitar aún más el proceso (tranquilamente podemos no usar docker o bien crear nuestra propia imágen de acuerdo a lo que necesitemos, solo hay que asegurarse de incluir todo lo necesario para que pueda ejecutarse Google Chrome en modo headless).

Adicionalmente, deberemos agregar un archivo .env.gitlab con los datos mínimos y necesarios para que el proyecto pueda ser ejecutado. (Como se ve en la etapa de test, este archivo será renombrado a .env), opcionalmente podemos realizar modificaciones al archivo phpunit.xml si necesitamos alguna configuración adicional. Lo recomendable para este ultimo archivo es que la llave php tenga los siguientes valores:

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="FILESYSTEM_DRIVER" value="public"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="QUEUE_DRIVER" value="sync"/>
</php>

Finalmente, nos queda subir los cambios al repositorio y deberá ejecutarse automáticamente la primer pipeline de integración contínua del proyecto, ya que al detectar el archivo gitlab-ci.yml GitLab lanzará el proceso de pipelines.

Tip1: probar primero localmente, y cuando todas las pruebas pasen subir los cambios al repositorio. (ahorremos sorpresas)

Tip2: editar el método driver del DuskTestCase.php agregando el flag "--no-sandbox"

protected function driver()
{
    $options = (new ChromeOptions)->addArguments([
        '--no-sandbox',
        '--disable-gpu',
        '--headless'
    ]);

    return RemoteWebDriver::create(
        'http://localhost:9515', 
        DesiredCapabilities::chrome()->setCapability(ChromeOptions::CAPABILITY, $options)
    );
}

Solucionando algún inconveniente: "no such sesion"

En proyectos pequeños puede ocurrir que no tengamos ningún problema al ejecutar las pipelines de CI. Al aumentar la cantidad de pruebas que tengamos incrementará seguramente la cantidad de memoria que se necesite para ejecutarlas, además dependerá de como las hayamos construido. Puede ocurrir que, aunque hagamos las cosas de la manera correcta de igual manera tengamos errores extraños, que no se producen cuando las ejecutamos en nuestro ordenador, un caso recurrente es:

Facebook\WebDriver\Exception\NoSuchDriverException: no such session
  (Driver info: chromedriver=2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9),platform=Mac OS X 10.12.3 x86_64)

Este error normalmente se relaciona con la cantidad de memoria compartida (shm_size) dentro del ejecutor de docker, según la documentación de GitLab, podemos incrementarla, pero para ello es necesario que instalemos y registremos un gitlab-runner en un servidor, lo cual es muy sencillo y solo consiste en:

  • Elegir el equipo/servidor donde será instalado (recomendado AWS o DigitalOcean, o bien un server con buena conexión a internet)
  • Instalar de acuerdo al tipo de sistema operativo
  • Registrarlo y configurarlo de acuerdo a lo que necesitemos (para todo el grupo, para todos los proyectos o proyecto específico, etc.)
  • Deshabilitar los runners compartidos para el proyecto/grupo.
  • Establecer el valor shm_size = 536870912 en /etc/gitlab-runner/config.toml (o donde se encuentre alojado dicho archivo de configuración) TOML ejemplo
concurrent = 2
check_interval = 0

[session_server]
  session_timeout = 5400

[[runners]]
  name = "******"
  url = "https://gitlab.com/"
  token = "******"
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    cache_dir = "cache"
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
    shm_size = 536870912
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]

Con esto tendremos solucionados los problemas de configuración conocidos para ejecutar pruebas de laravel dusk en el entorno de CI de GitLab.

Si te gustó este post y queres ayudarme invitame un café Invitame un café en cafecito.app


almost 4 years ago

Lucas Fiege