Unicorn, de Yosuke Muroya

Por fin llegamos a la última entrada del año sobre tests unitarios en WordPress. Si has seguido (y disfrutado) todas las anteriores, ¡te felicito! Ahora ya puedes decir que sabes qué son y para qué sirven los tests unitarios, cómo testear tu código PHP con PHPUnit y cómo testear tu código JavaScript con QUnit. Hay que reconocer que hemos aprendido muchísimo en sólo tres entradas, ¿eh? Pero todavía nos queda lo más importante de todo: ¡ponerlo en práctica en un ejemplo «real»!

Como te adelanté en la entrada anterior, hoy vamos a ver cómo testear los componentes PHP y JavaScript de tus plugins (o temas, da igual). Así pues, empezaremos creando un pequeño plugin que implemente una llamada AJAX (con lo cual tendrá una parte en PHP y otra en JavaScript) y veremos qué tests crear y cómo.

Nuestro Plugin: El Buscador de Entradas

Recordemos que el objetivo de la entrada de hoy es que practiques un poco tus habilidades de testing, así que intentaré que el plugin que diseñemos sea sencillo para que no perdamos mucho tiempo con él,  pero lo suficientemente complejo como para que podamos jugar un poco.

Vamos a empezar por definir el tipo de plugin que queremos implementar. He pensado que podríamos hacer un plugin que te permitiera buscar entradas desde el front-end a través de su título. Para ello, lo que haremos es añadir un pequeño formulario de búsqueda al final del contenido de todas las entradas con un campo de texto; cuando el usuario escribe texto, de forma dinámica, se lanzará una petición AJAX que devuelva las entradas que contienen la cadena de búsqueda en el título. Es decir, quiero el siguiente formulario:

Formulario de búsqueda por AJAX
Pequeño campo de búsqueda al final de las entradas.

que devuelva una lista como la siguiente cuando hay resultados:

Lista de resultados
Lista con las entradas que coinciden con la búsqueda.

y que, si no hay ninguna coincidencia, nos diga esto:

Sin resultados
Si no encontramos ninguna entrada con la cadena de búsqueda especificada, mejor avisamos al usuario.

Sencillo, ¿verdad? Pues vamos a implementarlo.

1. Crear el esqueleto

Como imagino que ya sabes, podemos organizar el código del plugin de mil y una formas, pero para no complicarnos demasiado la vida voy a usar dos únicos ficheros: uno donde habrá todo el código PHP y otro con el código JavaScript. Sé que no es la mejor forma de hacerlo… pero, insisto, quiero hacer las cosas sencillas y no quiero que nos perdamos en detalles innecesarios.

Empecemos, pues, por definir el fichero principal de nuestro plugin: crea un directorio llamado nelio-post-searcher dentro de wp-content/plugins/ y añade el fichero nelio-post-searcher.php con el siguiente contenido:

Con esto ya tienes creado un plugin que no hace absolutamente nada. ¡Felicidades! Ya que estamos, aprovecha para añadir también un par de ficheros JavaScript: searcher.jsfunctions.js que, de momento, dejaremos vacíos.

Aprovecha para activar el plugin ahora ?

2. Añadir el formulario de búsqueda al final de las entradas, junto con el JavaScript

A continuación, vamos a hacer que el formulario de búsqueda aparezca al final de todas las entradas. Para ello usaremos un filtro llamado the_content (puedes encontrar la documentación aquí) en nuestro fichero PHP. Como lo único que queremos es un pequeño cuadro de búsqueda y un área donde mostrar los resultados, añadiremos los dos elementos al final del contenido:

Fíjate que únicamente tenemos un input de tipo texto y un div donde añadiremos los resultados. De nuevo, esta forma de proceder no es la mejor; lo ideal sería separar las plantillas HTML del código que hace las cosas (poniéndolo en un directorio partials o similar)… pero eso ya lo sabías, ¿verdad?

Finalmente, tenemos que asegurarnos de que estamos incluyendo los scripts de búsqueda. Para ello, basta con hacer lo siguiente:

3. Implementemos la función de búsqueda…

Ahora necesitamos implementar la función que busque las entradas. Esto lo podemos hacer fácilmente con una función como la siguiente:

la cual toma como parámetro la cadena de texto a buscar. Fíjate que entre los argumentos que pasamos a WP_Query hay uno llamado post_title__like; este parámetro no existe por defecto en WordPress, así que vamos a tener que añadirlo nosotros mismos a través de una función extra y su hook pertinente:

Si no lo hiciéramos así, la búsqueda que incluye por defecto WordPress encontraría todas las entradas que contienen la cadena de texto en el título o en el contenido, y nosotros, insisto, sólo queremos entradas que incluyan la cadena en el título. Como de momento no estamos testeando nada, vamos a suponer que está bien escrita…

4. …y dejemos preparado un callback AJAX para usar esta llamada

La función que hemos escrito para realizar la búsqueda está muy bien, es muy bonita… ¡pero no sirve de nada si no la llamamos! Lo que vamos a hacer ahora es exponer un callback para que se pueda invocar mediante JavaScript. Para ello, basta con hacer lo siguiente:

Esta nueva función comprueba que exista un parámetro llamado q (de query, por supuesto). Si no existe, lanza un mensaje de error al usuario. Si está presente, recoge el valor (fíjate que saneamos la entrada, algo que siempre hay que hacer cuando le pedimos datos a los usuarios) y se lo pasamos a la función que hemos definido en el punto 3.

También es interesante comentar que esta función no tiene ningún return; al tratarse de una llamada AJAX, hay que devolver el resultado usando las funciones wp_send_json*. Podríamos haber devuelto el resultado usando echo y tal… pero es mejor aprovechar las funciones que nos da WordPress.

5. ¡Y saltamos al mundo JavaScript!

Ahora que ya tenemos todo listo, es hora de preparar el JavaScript. Si viste el vídeo de Rebecca Murphey que compartí en la entrada anterior, ya sabrás cómo hay que escribir código JavaScript para que sea testeable. Si todavía no lo has hecho, ¿a qué esperas? ¡Ve en seguida a verlo!

Básicamente, queremos que nuestro JavaScript haga lo siguiente:

  • Cuando el usuario empieza a escribir en el campo, el script tiene que avisar de que «estamos buscando» lo que escribe.
  • Cuando deja de escribir, lanzar la petición AJAX a nuestro callback con la cadena de texto que nos han dado.
  • Cuando recibimos el resultado, pintarlo por pantalla.
  • Si no hay resultados, mostrar un texto que nos lo indique.
  • Si se borra la cadena de búsqueda, los resultados tienen que quedar vacíos también.

Aunque podríamos hablar largo y tendido sobre la implementación JavaScript de todo esto, voy a mostrarte el fichero searcher.js final aplicando los principios del vídeo que te comentaba antes:

Como puedes ver, tenemos una función onQueryChanged que se encarga de recoger lo que escribe el usuario y que, pasado un cierto tiempo (cuando asumimos que ya ha acabado de escribir, usando la función _.debounce de la librería underscorejs.org), realiza la petición AJAX para obtener los resultados usando la función searchPosts. Una vez los resultados se han encontrado, se invoca la función processResult, la cual utilizará el método draw para mostrar los resultados pertinentes al usuario si hubiera habido (recordemos que nuestro callback no devuelve directamente la lista de entradas, sino que viene en un objeto con los atributos successdata). Finalmente, he añadido la función especial clear que limpia la zona de resultados cuando no hay ninguna cadena de búsqueda.

Para que esto funcione, necesitamos otro script que lo ponga todo en marcha (lo que en el vídeo de Rebecca llamaba «glue code»), y es lo que meteremos en el functions.js:

Poniendo a prueba nuestro plugin

Ahora que ya tenemos todo el plugin escrito es hora de ponerlo a prueba. Si haces las cosas como solía hacerlas yo antes, este «poner a prueba» quiere decir que probarías manualmente que el formulario devuelve lo que tiene que devolver. ¿Cómo? Abriendo la página en tu navegador y «jugando» con él. Y, cuidado, no estoy diciendo que no puedas o no debas hacerlo así… ¡pero ahora sabemos cómo hacerlo mejor!

El gran error que hemos cometido en la primera parte de nuestra entrada es que hemos escrito todo el código sin probar absolutamente nada. Sé que somos buenos, pero igual ir añadiendo los tests a medida que implementábamos el código no hubiera sido mala idea, ¿no? Veamos los diferentes tests que podríamos haber ido escribiendo a medida que programábamos.

Testeando el código PHP con PHPUnit

Como hemos empezado escribiendo el código PHP, tiene sentido que empecemos hablando de cómo testearlo con PHPUnit. Lo primero que habíamos hecho es «añadir» un formulario de búsqueda al final de nuestras entradas, aunque no hemos llegado a comprobar si realmente se había añadido. Para comprobar que lo hemos hecho bien, podemos crear el siguiente test:

Este test genera una entrada nueva en nuestro sistema de test con el título y contenidos especificados y, a continuación, comprueba que el contenido incluye el formulario. Fácil y para todos los públicos.

Otro test que podríamos hacer (añadiendo una nueva función a la clase anterior) es comprobar que nuestro JavaScript se está encolando correctamente. Pero esto, amigo, te lo dejo a ti ?

A continuación nos podemos plantear si la función de búsqueda devuelve los resultados que esperamos. Aquí ya es cuestión de ponerle imaginación y pensar en los diferentes escenarios con los que te puedes encontrar y cuál quieres que sea el comportamiento:

  • ¿Qué pasa si la cadena de búsqueda es vacía?
  • ¿Qué devolvemos si no hay entradas?
  • ¿Qué pasa si ninguna entrada cumple la condición de búsqueda?
  • ¿Qué pasa si hay más de una entrada que cumple la condición de búsqueda?

Obviamente no hay una respuesta correcta a todas estas preguntas y, por lo tanto, depende totalmente de lo que queramos hacer. Yo, por ejemplo, he definido el siguiente comportamiento a través de los siguientes tests:

pero tú eres libre de hacer lo que quieras.

Finalmente, nos queda comprobar que el comportamiento del callback AJAX es el esperado. En este caso, yo recomendaría comprobar únicamente que se devuelve un error si el parámetro de búsqueda está vacío y que se devuelve el resultado si está presente:

Quizás te preguntes por qué no comprobamos que los resultados que devolvemos se corresponden a lo que hemos buscado. Pues bien, tienes toda la razón del mundo en pensar que es algo que se podría comprobar, pero en mi opinión es innecesario; fíjate que esta comprobación ya la hemos realizado en el test anterior, cuando probábamos la función neliops_search_posts. Pero, oye, si vas a quedarte más tranquilo… ¡no te cortes!

Y una vez tenemos todos estos tests escritos, lanzamos PHPUnit y…

PHPUnit funcionando con nuestro ejemplo de AJAX
PHPUnit funcionando con nuestro ejemplo de AJAX.

PAAAM! Todo de color verde y funcionando a las mil maravillas. ¿Acaso dudabas de nuestra eficiencia? ? High five! ✋

Testeando el código JavaScript con QUnit

Finalmente, ya sólo nos queda comprobar que el código JavaScript también funciona como esperábamos. Lo más importante en este punto es que no es tu responsabilidad comprobar que la llamada AJAX funciona; se supone que si tú pasas una cadena de búsqueda al callback que hemos definido, éste devolverá el resultado correcto. En otras palabras, todo el testing que realizaremos aquí será con datos de mentira.

Podemos empezar por lo más sencillo: comprobar que si pasamos una lista de entradas al visualizador de resultados, éste muestra lo que queremos:

¿Ves qué sencillo? Gracias a haber organizado el código en diferentes funciones, cada una de ellas con su responsabilidad perfectamente definida, y no haber sucumbido a la tentación de usar funciones anónimas, ahora podemos testear el código de forma lógica y sin problemas.

Y aunque quedan unos cuantos tests más por escribir, creo que te los puedo dejar a ti. ¿Te animas a pensarlos y escribirlos?

Conclusiones

¡Y eso es todo! Si has conseguido seguir la serie entera, te doy mi más sincera enhorabuena (y las gracias por aguantar la chapa).

En la entrada de hoy hemos puesto en práctica todo lo que hemos estado hablando durante el último mes. El test unitario nos permite probar los componentes de forma individual, sin tener que preocuparnos de cómo se integran entre ellos (esto es responsabilidad de otro tipo de tests). Gracias a este principio, podemos verificar que su funcionamiento aislado es el que esperábamos, sin complicarnos la vida en interacciones complicadas. Si ahora cambiaras cualquier método e introdujeras un error, tus tests lo detectarían.

Y ahora te lanzo una pregunta: ¿te ves capaz de realizar este pequeño proyecto empezando por escribir los tests? Esto es lo que se llama Desarrollo Dirigido por Tests (TDD por sus siglas en inglés) y es una fantástica forma de programar: primero escribes un test (que obviamente falla, porque no existe código que lo supere) y luego escribes el código para que se supere con éxito.

Te invito a que compartas tu experiencia con nosotros. Y si tienes cualquier comentario, aprovecha para mandárnoslo antes de que celebremos fin de año y nos olvidemos del blog por unos días ?

¡Feliz año nuevo a todos!

Imagen desatacada de Yosuke Muroya.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

He leído y acepto la política de privacidad de Nelio Software

Tus datos personales se almacenarán en SiteGround y serán usados por Nelio Software con el único objetivo de publicar tu comentario aquí. Con el envío de este comentario, nos das el consentimiento expreso para ello. Escríbenos para acceder, rectificar, limitar o eliminar tus datos personales.