> Manuales > Manual de Testing en Laravel

Explicamos el proceso de pruebas funcionales de los formularios, en aplicaciones Laravel, con nuevas aserciones enfocadas a las vistas. Además explicamos cómo y cuando realizar cada tipo de test, feature o browser test.

Cómo testear con Laravel una página web que tiene un formulario

En el artículo anterior hemos visto lo sencillo que es testear una página que recibe datos por post. Pero ya que hablamos de formularios, vamos a ver cómo podríamos testear la propia página que muestra el formulario.

Para explicar cómo testear con Laravel una página web que tiene un formulario vamos a abordar los siguientes puntos.

Cuándo constriur el formulario

Si te fijas, hasta ahora no hemos necesitado construir la página que muestra el formulario donde el usuario debe introducir los datos, ya que el propio código de test es capaz de enviar la información sin que un usuario deba interactuar con un formulario.

Por tanto, el trabajo de crear el formulario en sí, con su código HTML y eventualmente Javascript para validaciones, podríamos incluso desarrollarlo después de haber creado y probado el código de la recepción del formulario.

Si trabajamos con TDD lo normal sería diseñar los test antes que construir la propia vista del formulario. Sería una opción perfectamente posible, pero para lo que respecta al manual creo que didácticamente es más conveniente mostrar primero el código de lo que queremos testear, ya que encontraremos más sentido a nuestros tests. Así que, aunque paremos un poco el enfoque del TDD, vamos a comenzar con ello.

Cómo testear un formulario

A la hora de hacer test de las páginas que muestran un formulario tenemos dos posibilidades.

En este caso cada tipo de test es capaz de llegar a un nivel de comprobación distinto. Mientras que en el test de feature nos centramos en verificar el código HTML de la vista del formulario, en el test de browser nos centramos en experimentar con el formulario levantando un navegador, como lo haría un usuario real.

Los browser test son más fiables, ya que nos permiten comprobar mejor la funcionalidad, incoporando un flujo más realista. Sin embargo son un poco más complejos de configurar y de desarrollar. Pero no solo eso, también son más lentos de ejecutar, y sabemos que los test deben ser muy rápidos para poder ejecutarlos constantemente en el proceso de desarrollo dirigido por pruebas. Así pues, aunque los test de feature no pueden verificar la funcionalidad como la haría un usuario real, también tiene sentido hacerlos.

En resumen, y sin querer entrar todavía en muchos detalles, generalmente ambos tipos de test son complementarios, y tienen sus ventajas e inconvenientes. Por tanto lo ideal es balancearlos.

En este manual, ya que estamos comenzando por los test de features (pruebas funcionales), vamos a verlo primero por este enfoque y al final del manual podremos hablar con más calma de los test del navegador y explicar sus procesos.

Construyendo la funcionalidad de la aplicación Laravel

Como hemos dicho, esto podríamos hacerlo después de escribir el test. Sin embargo, a nivel didáctico pensamos que es mejor mostrar el código primero del formulario y luego explicar qué test podríamos hacer sobre esa vista.

Esta sería la ruta que muestra el formulario:

Route::get('/panel', function () {
    return view('panel.add-activity-form');
});

Me he ahorrado en este caso crear el controlador aunque generalmente esto no sería así en una aplicación comúnmente. Como todos sabéis desarrollar bien en Laravel, ya entendéis cómo se haría.

Esta sería la vista que queremos testear:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Añadir una actividad</title>
</head>
<body>
    <div>
        <h1>Enviando un tiempo</h1>

        <form action="/panel/store" method="POST">
            @csrf

            <div>
                <label for="start_time">Hora de inicio</label>
                <div>
                    <div>
                        <select name="start_hour" id="start_hour" required>
                            <option value="" disabled selected>Hour</option>
                            @for ($hour = 0; $hour < 24; $hour++)
                                <option value="{{ str_pad($hour, 2, '0', STR_PAD_LEFT) }}">{{ str_pad($hour, 2, '0', STR_PAD_LEFT) }}</option>
                            @endfor
                        </select>
                    </div>
                    <div>
                        <select name="start_minute" id="start_minute" required>
                            <option value="" disabled selected>Minutes</option>
                            @foreach (["00", "15", "30", "45"] as $minute)
                                <option value="{{ $minute }}">{{ $minute }}</option>
                            @endforeach
                        </select>
                    </div>
                </div>
            </div>

            <button type="submit">Submit</button>
        </form>
    </div>
</body>
</html>

Desarrollando las pruebas funcionales para verificar la vista del formulario

Ahora voy a mostrar los distintos métodos de test que podríamos usar para probar la vista de ese formulario. Iremos comentando las cosas nuevas que vamos encontrando con respecto a las aserciones de testing en Laravel.

Veamos un test simple que solamente verifica el status de la respuesta y la vista que se ha cargado.

#[Test]
public function activity_time_form_loads_successfully()
{
    $response = $this->get('/panel');
    $response->assertStatus(200);
    $response->assertViewIs('panel.add-activity-form');
}

Este primer método de test hace comprobaciones que ya conoces, si has seguido el manual de testing en Laravel hasta este punto, como verificar el status code y que se invoca a la vista esperada.

Ahora vamos a ver cómo podrías testear el código HTML del formulario que tiene la vista. Aquí vamos a ver algunas pruebas representativas, aunque tú podrías ser mucho más exhaustivo si lo juzgases oportuno.

#[Test]
public function panel_page_contains_expected_elements()
{
    $response = $this->get('/panel');

    $response->assertSee('<form', false);
    $response->assertSee('name="start_hour"', false);
    $response->assertSee('name="start_minute"', false);
    $response->assertSee('<button type="submit">Submit</button>', false);
}

Este método de test usa el método assertSee() que ya conoces. Sin embargo, hay un detalle que sí que merece la pena comentar. Se trata del uso de un segundo argumento en el método assertSee(), al que siempre le pasamos el valor false.

Esto es necesario porque, cuando quieres validar contenido que incluye etiquetas HTML directamente (como <form>), tenemos que asegurarnos que el método no escape los caracteres especiales del HTML. Para eso enviamos el false como segundo argumento en assertSee().

Ahora vamos a ver cómo se podría comprobar que se envía el token SCRF típico de los formularios en Laravel.

#[Test]
public function form_includes_csrf_token()
{
    $response = $this->get('/panel');
    $response->assertSee('name="_token"', false);
}

Este método verifica que el formulario tiene un campo que tiene el name="_token", que debería crearse cuando se incluye el token csrf como campo hidden. Como puedes ver, no estamos verificando que el token tiene un valor correcto. Esto no es posible porque ese token va cambiando, pero al menos hemos comprobado que el campo que lo contiene está en la vista.

Podíamos haber agregado este assertSee() con los otros assertSee() del método panel_page_contains_expected_elements(), pero lo hemos decidido separar porque así si falla la aserción será más fácil entender el propósito de este test y qué es lo que debemos corregir.

Conclusión sobre los test en Laravel de las páginas de formulario

Antes de acabar quiero hacer una reflexión sobre los test que hemos visto en este artículo. Quizás te preguntes ¿Hasta qué punto me debo tomar la molestia de testear tanto la página que muestra el formulario como la página que lo recibe?

Es una buena pregunta porque en muchos casos la página que muestra el formulario no tiene ninguna lógica en especial, lo que puede hacernos suponer que sea un poco innecesaria verificar tan exhaustivamente el HTML que contiene. En ese caso ¿No sería suficiente con testear solamente la página que va a recibir el formulario y que debe procesar los datos?

La respuesta, como muchas veces ocurre, es un "depende". Depende de la filosofía del equipo de desarrollo, de la prisa que se tenga por entregar un proyecto y los objetivos de cobertura de los test.

En un proyecto común se suele priorizar el testeo de la funcionalidad que afecta al negocio, en este caso la página que recibe y procesa los datos del formulario. Esto se agudizará especialmente si el proyecto tiene recursos limitados o requiere tiempos de entrega cortos.

Obviamente los test son siempre positivos, pero a veces también pueden ser una dificultad adicional por el hecho de tener que mantenerlos, lo que puede ser bastante frecuente a veces si el código frontend tiende a cambiar con demasiada frecuencia. En todo caso, no es mala idea verificar al menos que estén presentes los campos de formulario que necesitamos para enviar los datos y otros elementos de seguridad como el token CSRF.

Para completar el testeo de la funcionalidad de envío de formularios, en el siguiente artículo vamos a añadir algunas validaciones a este proceso de recepción de datos por formulario. Así podremos explicar cómo testear el proceso de validación que realizamos en nuestra aplicación Laravel.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual