Introduccion

Las pruebas unitarias o testing para plugins wordpress son unas de las cosas más importantes que debe tener un plugin y algo que confirmo luego de dos años de estar desarrollando herramientas digitales para inmobiliarias, especialmente para inmobiliarias que utilizan a WordPress como motor principal en su página web.

En codwelt estamos trabajando en un plugin de wordpress para las inmobiliarias. Específicamente estoy desarrollando en la versión gratuita, la cual contendrá algunas funcionalidades, pero estas funcionalidades, una como la de que la inmobiliaria o agente inmobiliario pueda crear un inmueble o crear inmuebles desde la administración de wordpress. Estas funcionalidades las quiero dejar de manera que sean reutilizables por otros plugins, es básicamente lo que hace woocomerce que tiene muchos ganchos que permiten que sea tan modificable o ajustable a las necesidades de los usuarios de wordpress.

📍 Objetivo del testing plugins wordpress

Crear un plugin para wordpress que pueda ser testeado unitariamente de manera que no necesite tener instalador un wordpress para poder probar su logica de negocio. En resumidas cuentas estamos buscando burlarnos de las funciones de wordpress o lo que en ingles se llama hacer mocks

🤓 Investigación de testing para plugin wordpress

Si quieres ir directamente a como implementarlas en un plugin de wordpress saltante esta parte que simplemente hago un story time de como fue el proceso de investigación para lograr el objetivo mencionado en el en el párrafo anterior.

Después de un rato leyendo artículos en ingles, viendo videos de indios que no pueden faltar. Llegue a una pagina oficial de WordPress donde encontré que un posible candidato para lo que estaba buscando hacer era WP-CLI. Sin embargo, no me convencía de todo porque según leía su pagina de instalación si necesitaba si o si tener un WordPress corriendo y es lo que no queremos hacer.

Pero despues de un rato mas buscando información encontramos 🥳 lo que buscabamos.

Del que estamos hablando es BrainMonkey una librería para crear pruebas unitarias especialmente diseñada para wordpress dicen los creadores y hablan de lo que inicialmente yo pensaba que es la realidad. Pero las pruebas unitarias están destinadas a ejecutarse sin cargar el entorno de WordPress.

La utilicé pará probar que se registre en enganche con el hook de WordPres de registro de Endpoint para el API-Rest.

Configuración del entorno de testing

BrainMockey

Antes que nada debemos tener bien configurado el archivo phpunit.xml que debe estar en la raiz del proyecto, así que el mío se ve como este.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         verbose="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Test visualinmueble free Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
    <php>
        <ini name="error_reporting" value="-1" />
        <ini name="xdebug.mode" value="coverage" />
        <env name="XDEBUG_MODE" value="coverage" />
    </php>
    <report>
        <html outputDirectory="coverage/"/>
    </report>
    <coverage processUncoveredFiles="true">
        <include>
            <directory suffix=".php">src</directory>
            <directory suffix=".php">DDD</directory>
        </include>
    </coverage>
</phpunit>

Info 🚨

Quería hacer también pruebas de cobertura, asi que dentro del phpunit.xml también están algunas cositas de configuración para esto. Lo cual les puede generar problema si no tienen instalado la librería de php xdebug. Recuerda que puedes dejar tu comentario si necesitas aiuudaa

Luego lo que tenemos que hacer es añadir un test case que extienda de phpunit y añadir las configuraciones de brainmonkey. Aqui tienen el mio.

<?php
namespace Codwelt\Wordpress\VisualInmuebleFree\Tests;

use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use Brain\Monkey;
use PHPUnit\Framework\TestCase;

class TestCasePadre extends TestCase {

    use MockeryPHPUnitIntegration;


    protected function setUp(): void
    {
        parent::setUp();
        Monkey\setUp();
    }

    protected function tearDown(): void
    {
        Monkey\tearDown();
        parent::tearDown(); // TODO: Change the autogenerated stub
    }
}

Con esta clase comienzo a extender todas las clases de las pruebas unitarias para este plugin desarrollado para wordpress. Despues de un rato ya haciendo uso de la librería, un poco mas de investigación porque necesitaba burlarme de la función register_rest_route de wordpress.

Uno de mistest ya se via como esto

<?php
namespace Codwelt\WordPress\VisualInmuebleFree\Tests;
use Brain\Monkey\Actions;
use Brain\Monkey\Filters;
use Brain\Monkey\Functions;
use Codwelt\WordPress\VisualInmuebleFree\RegistorEndpointsHooks;

class EngancheEndpointsTest extends TestCasePadre
{

    protected function setUp(): void
    {
        parent::setUp(); // TODO: Change the autogenerated stub

    }

    /**
     * @return void
     */
    function testEngancheEnpoints()
    {
        $regisorHooksEndpoints = new RegistorEndpointsHooks();
        $regisorHooksEndpoints->init();
        self::assertNotFalse(has_action('rest_api_init',[RegistorEndpointsHooks::class,'restApiInit']));
    }

}

Y lo mejor de todo pues podria programar el plugin sin tener que tener instalador una base de datos, el wordpress, un docker, etc.

WP_MOCK

Hasta este punto estaba todo ok pero…. necesitaba también burlarme del $wpdb esa variable global de wordpress que nos da un api para controlar la base de datos. Y brainmonkey no tenia mucha documentación y recuerden que yo también era nuevo en este mundo de las pruebas unitarias para los plugins de wordpress.

Así que pensando que brianmonkey no era mi solución seguí explorando y me encuentre con la librería. WP_MOCK. Esta librería parecía un poco más desordenada en su documentación pero realmente si estaba más completa porque hasta me mostró como podía burlarme de esa variable global $wpdb y aunque al final termine utilizando WP_MOCK en todas mis pruebas unitarias también me doy cuenta de que burlar esta variable de wordpress era tan sencillo que solo se debía utilizar la clase Mockery, esta clase que utiliza WP_MOCK y brainmonkey es la que permite crear la burla.

Realmente la configuración es un poco más compleja a comparación de BrainMonkey. Lo primero es que tenemos que crear un archivo de carga o bootstrap y ese archivo tenemos que llamarlo desde el phpunit.xml y debe quedar algo asi.

Configuracion phpunit para utilizar pruebas unitarias o testing para plugin de wordpress
Testing para plugins Wordpress con 2 librerías 4

Dentro del archivo bootstrap solo se invoca a vendor/autoload, a un metodo de WP_MOCK y finalmente a l archivo de lanzamiento que wordpress nos pide que nuestro plugin tenga en la raiz. Asi se veria:

<?php

// First we need to load the composer autoloader, so we can use WP Mock
require_once __DIR__ . '/vendor/autoload.php';

// Bootstrap WP_Mock to initialize built-in features
WP_Mock::bootstrap();

/**
 * Now we include any plugin files that we need to be able to run the tests. This
 * should be files that define the functions and classes you're going to test.
 */
require_once __DIR__ . '/visualinmueble-free.php'; 

Y en segundo lugar es llamar a nuestro archivo bootstrap desde el phpunit.xml como se muestra en la imagen anterior.

Mock o burla de la variable $wpdb

Para burlar a la variable fue realmente todo, se resumen en el siguiente código, donde burlamos el nombre de la clase WPDB y tenemos que hacerlo con Mockery porque con la mock de phpunit no se puede, ya que este último nos pide, es una clase existente dentro del plugin y recuerda que estamos es trabajando fuera de wordpress por consiguiente esa clase no existe en nuestro proyecto.

Este es el mejor ejemplo para burlarse de esa variable, donde simplemente se declara globalmente como nula y luego con Monkery se burla con su nombre de clase(este nombre es el que wordpress le tiene a la clase, no lo invente) y ya con el uso de la documentación de Mockery hacemos uso del método shouldReceive para decir que el método get_col debe ser llamada una vez con un parámetro tipo string y el valor «Selecct ID ….» Por último que el método get_col va a retornar un array . Simplemente, eso asi es la base para burlar los demás método insert, update, etc. El que estemos usando en nuestro plugin.

use Mockery;

function test_get_post_ids() {
	global $wpdb;

	$wpdb = Mockery::mock( '\WPDB' );
	$wpdb->shouldReceive( 'get_col' )
		->once()
		->with( "select ID from wp_posts LIMIT 3" )
		->andReturn( array( 1, 2, 3 ) );
	$wpdb->posts = 'wp_posts';

	$post_ids = get_post_ids();

	$this->assertEquals( array( 1, 2, 3 ), $post_ids );
}

Aquí les voy a poner el código de como me quedo a mi la burla de esta variable donde usaba el método insert.

 /**
     * Se prueba que la integracion entre el controlador y el servicio de almacenamiento esten coordinados
     * @return void
     * @throws ParametrosCreacionIncompletosException
     */
    function testIntegracionApiControllerAlamacenamientoExitoso()
    {
        $paramsBody = $this->getParametros();
        $paramsBody["valor_venta"] = 100000000;
        $request = $this->buildMockRequest($paramsBody);

        global $wpdb;
        $wpdb = \Mockery::mock( '\WPDB' );

        $id = random_int(1,10);
        $wpdb->shouldReceive( 'insert' )
            ->once()
            ->withArgs(function ($nombre,$columnas): bool {
                return true;
            });
        $wpdb->insert_id = $id;

        $paramsBody["id"] = $id;
        $controller = new ApiAdminInmueblesController();

        $result = $controller->crearInmueble($request);

        $resultadoEsperado = [
            'message' => 'Inmueble creado exitosamente',
            'inmueble' => $paramsBody
        ];

        $this->assertEquals($resultadoEsperado,$result);
    }

A este punto ya nos queda es comenzar a probar con las distintas configuración que tienen las librerías y acomodarlo a nuestros casos de prueba.

Despedida

Esto a sido todo por este post, recuerden que si tienen alguna duda dejen su comentario y espero que puedan añadirle pruebas unitarias a todos los plugin que desarrollen. Me despido con una imagen de los resultados de mis pruebas unitarias para que se animen.

Resultados exitosos de las pruebas unitarias o testing realizadas a un plugin de wordpres
Testing para plugins Wordpress con 2 librerías 5

Saludos.

TIKTOK: DonJuanc.developer

Links de Interes