{"id":4421,"date":"2025-10-04T09:39:42","date_gmt":"2025-10-04T07:39:42","guid":{"rendered":"https:\/\/davidperezgar.com\/?p=4421"},"modified":"2025-10-14T10:06:09","modified_gmt":"2025-10-14T08:06:09","slug":"desarrolla-crea-test-plugins-no-errores","status":"publish","type":"post","link":"https:\/\/davidperezgar.com\/es\/desarrolla-crea-test-plugins-no-errores\/","title":{"rendered":"Desarrolla y crea Test para que tus plugins no tengan errores"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Este es el tutorial que vamos a tener en cuenta para la charla de la WordCamp Galicia 2025.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Antes, dos conceptos:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"\">Test Driven Development<\/li>\n\n\n\n<li class=\"\"><a href=\"https:\/\/www.hostinger.com\/blog\/trunk-based-development-workflow-in-wordpress\" target=\"_blank\" rel=\"noopener\">Trunk Based Development Workflow<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Configurar tu plugin con Unit Tests<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Esta gu\u00eda est\u00e1 basada en la realizaci\u00f3n de Tests con PHPUNIT e instalado en el propio repositorio con composer. Es la forma m\u00e1s f\u00e1cil de que los desarrolladores puedan compartir un mismo entorno al desarrollar el plugin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En WordPress CLI tenemos un comando para configurar nuestro plugin para instalar los archivos iniciales para realizar tests.&nbsp;<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">wp scaffold plugin-tests plugin-name --ci=github<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Al ejecutar el comando, te instala los siguientes archivos:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"\">&nbsp;bin\/install-wp-tests.sh \u2192 bash que instala entorno de pruebas.<\/li>\n\n\n\n<li class=\"\">phpunit.xml.dist \u2192 configuraci\u00f3n de PHPUnit.<\/li>\n\n\n\n<li class=\"\">tests\/bootstrap.php \u2192 carga WordPress, configuraci\u00f3n y plugins antes de los tests. Aqu\u00ed podremos poner constantes del entorno.<\/li>\n\n\n\n<li class=\"\">tests\/test-sample.php \u2192 ejemplo de test.<\/li>\n\n\n\n<li class=\"\">.github\/workflows\/phpunit.yml \u2192 integraci\u00f3n con GitHub Actions.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Necesitamos ahora PHPUNIT en nuestro repositorio. Para tenerlo en nuestro repositorio, lo instalaremos con composer:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">composer require --dev yoast\/phpunit-polyfills:^1.0 wp-phpunit\/wp-phpunit:^6.3<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Con esto instala:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"\">WP-PHPUNIT. Una implementaci\u00f3n del entorno de testing de WordPress usando PHPUnit. Es un fork no oficial, mantenido por la comunidad, que hace m\u00e1s f\u00e1cil correr tests sin tener que clonar todo el core de WordPress manualmente.<\/li>\n\n\n\n<li class=\"\">PHPUNIT-Polyfills. Una librer\u00eda creada por <strong>Yoast<\/strong> para proporcionar compatibilidad entre m\u00faltiples versiones de <strong>PHPUnit<\/strong> y diferentes versiones de <strong>PHP<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Te recomiendo que luego uses distignore para quitar archivos de desarrollo que no queremos que aparezcan en nuestro plugin final al crear el ZIP de distribuci\u00f3n:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\"># PHP Unit\n.github\n.phpcs.xml.dist\n.phpunit.result.cache\nphpunit.xml.dist\nphpcs.xml.dist\ntests\/\nbin\/<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Y como vamos a tener el repositorio en Git, a\u00f1adiremos carpetas y archivos que no queremos que aparezcan. En el archivo .gitignore a\u00f1adir:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">vendor\/\n.phpunit.result.cache<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Y actualizar Composer con estos scripts para ejecutar los tests m\u00e1s r\u00e1pido.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A\u00f1adiremos los comandos correspondientes a la ejecuci\u00f3n de tests y a la creaci\u00f3n del entorno para facilitarnos el trabajo.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">,\n\"scripts\": {\n\t\t\"test\": \"phpunit\",\n\t\t\"test-debug\": \"XDEBUG_MODE=debug XDEBUG_TRIGGER=1 phpunit\",\n\t\t\"test-install\": \"bash bin\/install-wp-tests.sh wordpress_test root 'root' 127.0.0.1 latest\"\n\t}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">A mi me gusta organizar las carpetas por tipos de Test.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este caso crea las carpetas:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">tests\/Unit\n\ntests\/Data<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Ahora ejecutamos nuestro script para instalar nuestro entorno de pruebas de WordPress para poder crear tests.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">composer test-install<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Se habr\u00e1n creado los archivos en nuestro repositorio, pero antes de ejecutar los tests, te recomiendo estos ajustes que van a prevenir errores despu\u00e9s.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Personalizaremos el archivo phpunit.xml.dist y en la linea directory quitar prefix=\"test-\" porque dependiendo de la versi\u00f3n, dar\u00e1 conflictos y errores. Adem\u00e1s, he creado una subcarpeta para tener los tests en tests\/Unit\/. Puedes personalizarlo a tu gusto.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\"> &lt;testsuites&gt;\n   &lt;testsuite name=\"testing\"&gt;\n     &lt;directory suffix=\".php\"&gt;.\/tests\/Unit\/&lt;\/directory&gt;\n   &lt;\/testsuite&gt;\n &lt;\/testsuites&gt;<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Mueve el archivo test-example.php a la subcarpeta \/Unit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finalmente, te recomendar\u00eda a\u00f1adir estas l\u00edneas al principio del archivo bootstrap. Sirven para definir una constante donde vamos a encontrar los datos de entrada, y tambi\u00e9n para prevenir que no haya errores con la constante WP_CORE_DIR.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">define( 'TESTS_PLUGIN_DIR', dirname( __DIR__ ) );\ndefine( 'UNIT_TESTS_DATA_PLUGIN_DIR', TESTS_PLUGIN_DIR . '\/tests\/Data\/' );\n\n\/\/ Define WP_CORE_DIR if not already defined\nif ( ! defined( 'WP_CORE_DIR' ) ) {\n\t$_wp_core_dir = getenv( 'WP_CORE_DIR' );\n\tif ( ! $_wp_core_dir ) {\n\t\t$_wp_core_dir = rtrim( sys_get_temp_dir(), '\/\\\\' ) . '\/wordpress';\n\t}\n\tdefine( 'WP_CORE_DIR', $_wp_core_dir );\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">\u00a1Por fin! Ya estamos listos para ejecutar los tests en nuestro plugin de WordPress:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">composer test<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Deber\u00eda de aparecerte:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">PHPUnit 9.6.24 by Sebastian Bergmann and contributors.\n1 \/ 1 (100%)\nTime: 00:00.005, Memory: 42.50 MB\nOK (1 test, 1 assertion)<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Si queremos ejecutar los tests en un wordpress multisite, deberemos a\u00f1adir esta constante al final en bootstrap:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">\/\/ Enable multisite.\ndefine( 'WP_TESTS_MULTISITE', true );<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfQu\u00e9 viene a continuaci\u00f3n?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ya tenemos el entorno creado en nuestro plugin, y ahora toca desarrollar. Genera datos para las funciones, ejec\u00fatalo y comprueba que los resultados esperados son los correctos. Para comprobar dichos resultados puedes usar las funciones assert de PHPUNIT.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here are the most common <strong>assert functions<\/strong> you\u2019ll use in PHPUnit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"\"><strong>assertTrue($condition)<\/strong> \u2192 Checks that a condition is true.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertFalse($condition)<\/strong> \u2192 Checks that a condition is false.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertEquals($expected, $actual)<\/strong> \u2192 Verifies that two values are equal (non-strict).<br><\/li>\n\n\n\n<li class=\"\"><strong>assertSame($expected, $actual)<\/strong> \u2192 Verifies that two values are the same (strict: type and value).<br><\/li>\n\n\n\n<li class=\"\"><strong>assertNotEquals($expected, $actual)<\/strong> \u2192 Verifies that two values are not equal.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertNotSame($expected, $actual)<\/strong> \u2192 Verifies that two values are not the same (strict).<br><\/li>\n\n\n\n<li class=\"\"><strong>assertNull($variable)<\/strong> \u2192 Checks that a variable is null.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertNotNull($variable)<\/strong> \u2192 Checks that a variable is not null.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertEmpty($variable)<\/strong> \u2192 Checks that a variable is empty.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertNotEmpty($variable)<\/strong> \u2192 Checks that a variable is not empty.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertCount($expectedCount, $array)<\/strong> \u2192 Checks that an array (or countable) has the expected number of elements.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertContains($needle, $haystack)<\/strong> \u2192 Checks that a value exists within an array or string.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertNotContains($needle, $haystack)<\/strong> \u2192 Checks that a value does not exist within an array or string.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertInstanceOf($class, $object)<\/strong> \u2192 Verifies that an object is an instance of a given class.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertIsArray($variable)<\/strong>, <strong>assertIsString($variable)<\/strong>, <strong>assertIsInt($variable)<\/strong>, etc. \u2192 Type assertions.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertGreaterThan($expected, $actual)<\/strong> \u2192 Checks that a value is greater than another.<br><\/li>\n\n\n\n<li class=\"\"><strong>assertLessThan($expected, $actual)<\/strong> \u2192 Checks that a value is less than another.<br><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 These are the most frequently used, but PHPUnit provides many more for specialized cases.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finalmente te recomiendo ejecutar las funciones para datos de entrada correctos y tambi\u00e9n incorrectos o que le falten datos. De esta forma, haremos nuestras funciones m\u00e1s robustas y preparadas para diferentes datos de entrada. A ning\u00fan usuario le gusta ver Fatal error al usar su plugin.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ejecutar tests para plugins de WooCommerce<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Si necesitas ejecutar tests y tu plugin tiene dependencias, tienes que a\u00f1adir la instalaci\u00f3n del plugin en <a href=\"http:\/\/install-wp-tests.sh\" target=\"_blank\" rel=\"noopener\">install-wp-tests.sh<\/a> y adem\u00e1s cargarlo en _manually_load_plugin .&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vamos a hacer el ejemplo si quieres a\u00f1adir el plugin de WooCommerce en tus tests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En el archivo bin\/install-wp-tests.sh , antes de la linea install_wp, a\u00f1ade las lineas que te permiten bajar el plugin WooCommerce para las dependencias necesarias.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\"># Installs WooCommerce plugin in the test environment\ninstall_woocommerce() {\n\tlocal PLUGIN_DIR=\"$WP_CORE_DIR\/wp-content\/plugins\"\n\tmkdir -p \"$PLUGIN_DIR\"\nWOOCOMMERCE_URL=\"https:\/\/downloads.wordpress.org\/plugin\/woocommerce.zip\"\n\tdownload \"$WOOCOMMERCE_URL\" \"$TMPDIR\/woocommerce.zip\"\n\tunzip -q \"$TMPDIR\/woocommerce.zip\" -d \"$TMPDIR\/\"\n\trm -rf \"$PLUGIN_DIR\/woocommerce\"\n\tmv \"$TMPDIR\/woocommerce\" \"$PLUGIN_DIR\/woocommerce\"\n\techo \"WooCommerce plugin installed successfully.\"\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Y despu\u00e9s de la linea install_wp, a\u00f1ade el la funci\u00f3n para que se ejecute justo despu\u00e9s de haber instalado WordPress: install_woocommerce<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y tambi\u00e9n tendremos que&nbsp; incluirlo en tu bootstrap dentro de la funci\u00f3n _manually_load_plugin:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">\/\/ Load WooCommerce first from the standard WordPress plugins directory\nrequire_once WP_CORE_DIR . '\/wp-content\/plugins\/woocommerce\/woocommerce.php';<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Configurar los tests autom\u00e1ticos en GitHub<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En el archivo de configuraci\u00f3n que hay en .github\/workflows\/testing.yml, revisa la configuraci\u00f3n y comprueba que la rama principal de tu repositorio es la correcta, sino, tendr\u00e1s que actualizar el archivo yml:<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">on:\n  pull_request:\n    branches:\n      - trunk<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Actualiza trunk por tu rama principal del repositorio.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Te recomiendo actualizar las lineas de setup de PHP y adem\u00e1s, necesitar\u00e1s que tenga instalado SVN que por defecto no est\u00e1 instalado.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">     - name: Setup PHP\n        uses: shivammathur\/setup-php@v2\n        with:\n          php-version: ${{ matrix.php-version }}\n          tools: phpunit-polyfills:1.1\n          extensions: mbstring, xml, zip, intl, pdo, mysql\n          coverage: none\n\n      - name: Install SVN\n        run: sudo apt-get update &amp;&amp; sudo apt-get install -y subversion<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Problemas comunes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Could not find \/wordpress-tests-lib\/includes\/functions.php, have you run bin\/install-wp-tests.sh ?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aparece cuando la instalaci\u00f3n de WordPress temporal est\u00e1 incompleta. Borra las carpetas y vuelve a ejecutar la instalaci\u00f3n.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al ejecutar la instalaci\u00f3n del entorno de tests te indica el directorio donde est\u00e1 instalado WordPress. Por ejemplo yo tengo:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/var\/folders\/kk\/6287m8gj09xdkt2zgz432zhr0000gn\/T\/<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Habr\u00eda que eliminar las carpetas wordpress-tests-lib y wordpress, y volver a ejectar la instalaci\u00f3n.<\/p>\n\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\"><code class=\"\">rm -rfv \/var\/folders\/kk\/6287m8gj09xdkt2zgz432zhr0000gn\/T\/wordpress-tests-lib\/\nrm -rfv \/var\/folders\/kk\/6287m8gj09xdkt2zgz432zhr0000gn\/T\/wordpress\/\ncomposer test-install<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Class test-sample cannot be found in \/tests\/Unit\/test-sample.php<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si PHPUNIT es mayor que v9, el nombre del del archivo tiene que llamarse igual que la clase.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">PHPUnit Version Incompatibility: The project was using PHPUnit 12.3.4, which is very new and not compatible with the WordPress testing framework. This caused additional errors when trying to run the tests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Charla<\/h2>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex frontblocks-gallery-grid\" data-layout=\"grid\" data-columns=\"3\" data-gutter=\"20\" data-lightbox=\"false\">\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"596\" height=\"397\" data-id=\"5072\" src=\"\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-01-596x397-1.jpg\" alt=\"Wcgalicia 2025 David Test Automatizados 01\" class=\"wp-image-5072\" title=\"\" srcset=\"https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-01-596x397-1.jpg 596w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-01-596x397-1-300x200.jpg 300w\" sizes=\"auto, (max-width: 596px) 100vw, 596px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1082\" height=\"721\" data-id=\"5080\" src=\"\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-05-1082x721-1.jpg\" alt=\"Wcgalicia 2025 David Test Automatizados 05\" class=\"wp-image-5080\" title=\"\" srcset=\"https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-05-1082x721-1.jpg 1082w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-05-1082x721-1-300x200.jpg 300w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-05-1082x721-1-1024x682.jpg 1024w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-05-1082x721-1-768x512.jpg 768w\" sizes=\"auto, (max-width: 1082px) 100vw, 1082px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1082\" height=\"721\" data-id=\"5078\" src=\"\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-04-1082x721-1.jpg\" alt=\"Wcgalicia 2025 David Test Automatizados 04\" class=\"wp-image-5078\" title=\"\" srcset=\"https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-04-1082x721-1.jpg 1082w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-04-1082x721-1-300x200.jpg 300w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-04-1082x721-1-1024x682.jpg 1024w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-04-1082x721-1-768x512.jpg 768w\" sizes=\"auto, (max-width: 1082px) 100vw, 1082px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1082\" height=\"721\" data-id=\"5076\" src=\"\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-03-1082x721-1.jpg\" alt=\"Wcgalicia 2025 David Test Automatizados 03\" class=\"wp-image-5076\" title=\"\" srcset=\"https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-03-1082x721-1.jpg 1082w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-03-1082x721-1-300x200.jpg 300w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-03-1082x721-1-1024x682.jpg 1024w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-03-1082x721-1-768x512.jpg 768w\" sizes=\"auto, (max-width: 1082px) 100vw, 1082px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1082\" height=\"721\" data-id=\"5074\" src=\"\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-02-1082x721-1.jpg\" alt=\"Wcgalicia 2025 David Test Automatizados 02\" class=\"wp-image-5074\" title=\"\" srcset=\"https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-02-1082x721-1.jpg 1082w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-02-1082x721-1-300x200.jpg 300w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-02-1082x721-1-1024x682.jpg 1024w, https:\/\/davidperezgar.com\/wp-content\/uploads\/2026\/10\/wcgalicia-2025-david-test-automatizados-02-1082x721-1-768x512.jpg 768w\" sizes=\"auto, (max-width: 1082px) 100vw, 1082px\" \/><\/figure>\n<\/figure>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-incrustar-wordpress-tv wp-block-embed-incrustar-wordpress-tv wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"VideoPress Video Player\" aria-label=\"VideoPress Video Player\" width=\"500\" height=\"281\" src=\"https:\/\/video.wordpress.com\/embed\/uqznp1B2?hd=1&amp;cover=1\" frameborder=\"0\" allowfullscreen allow=\"clipboard-write; presentation\"><\/iframe><script src='https:\/\/v0.wordpress.com\/js\/next\/videopress-iframe.js?m=1790791280'><\/script>\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"\/wp-content\/uploads\/2026\/10\/presentacion-wcgalicia-2025-david-perez.pdf\">Diapositivas<\/a><\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Transcripci\u00f3n de la charla<\/summary>\n<p class=\"wp-block-paragraph\">Hola, hola. Bueno, vamos a continuar el siguiente taller con David, David es director t\u00e9cnico de la esencia de marketing y de desenvolvimento CLOSE. Ademais, forma parte do equipo de revisi\u00f3n de plugins de WordPress.org, as\u00ed que, se tedes alguna historia con \u00e9l. Vale, no sector da formaci\u00f3n, ten experiencia t\u00e9cnica creando secci\u00f3ns de contido para programas, conectando sitios web a CCRM para asistenar clientes potenciais, equipos, publicidade, etc. Ademais, David est\u00e1 moi implicado na comunidade de WordPress, colaborando activamente en eventos e encontros locais. As\u00ed que, nada m\u00e1is, deixo vos con David para que vos explique como facer test nosos plugins. Gracias. el resto que no veis y los que lo est\u00e1is haciendo podamos hacer test autom\u00e1ticos porque realmente ayuda much\u00edsimo a la calidad del plugin y sobre todo lo que yo me he dado cuenta cuando he implementado este tipo de trabajo es que no hay regresiones o sea que realmente cuando t\u00fa ya montas los test haces tus funciones y luego esperas una entrada normalmente cuando ya hace una nueva versi\u00f3n o hace alg\u00fan cambio no revierte o no rompe nada anterior que eso es muy importante porque muchas veces cuando hace una nueva versi\u00f3n resulta que puede romper cosas que a lo mejor y la gente se nos queja sobre todo si tenemos plugin comercial o plugin de comunidad esto est\u00e1 aqu\u00ed parpadeando no sabemos por qu\u00e9 y a ver si damos con la tecla pero bueno os voy contando mientras vale qu\u00e9 son los test automatizados un tematizado es un o los test unitarios hay varios tipos de test pero nosotros vamos a tocar el test unitario el test unitario est\u00e1 basado en que nosotros son pruebas autom\u00e1ticas que hacemos nuestra funci\u00f3n para ver si funciona o si dan un valor esperado que nosotros esper\u00e1bamos y lo bueno de ustedes unitarios que aparte podemos jugar mucho a putear esa funci\u00f3n o digamos a gastarle a gastarle porque muchas veces la vida real pues t\u00fa esperaba un n\u00famero y no te viene un n\u00famero tiene un string o un array t\u00edpico que le falta una clave y no viene la clave toda esa perfecto no s\u00f3lo voy a ahondar en la parte de dentro en una entrada perfecta como deber\u00eda venir los datos sino tambi\u00e9n vamos a ir a buscarle putadillas a la funci\u00f3n hablando mal y pronto para que se comporte bien porque nosotros lo que nos podemos dar un error fatal en nuestro plugin nuestras funciones que al final da un si una interfaz que se rompe wordpress y a lo mejor incluso podemos romper la web completa segundo de \u00e9ste la funci\u00f3n si es de admin pues en principio ser\u00eda s\u00f3lo la parte de m\u00ed y la parte de front no pero pero poder romper entonces es muy importante esa parte tambi\u00e9n que la vamos a ver tambi\u00e9n lo voy a ver con ejemplos vaya de funciones que son muy sencillas una suma pero y si no te viene un n\u00famero te viene un texto pues eso es s\u00faper importante y sobre todo utilizando en programaci\u00f3n negativa lo bueno es que t\u00fa en la funci\u00f3n primero depuras lo que te va a venir de entrada devuelve una cosa u otra y a partir de ah\u00ed pues ya va arreglando y no teniendo problemas al final lo que estamos hablando es que aislamos esa funci\u00f3n ejecutamos con una entrada de datos esperada y una salida esto es muy interesante porque por ejemplo muchas veces nos pide una funci\u00f3n de un cliente y nos dice pero mira esta funci\u00f3n tiene que dar este resultado y lo tiene muy f\u00e1cil entonces con esto lo graban en los test unitarios grabas o sea escribes lo que t\u00fa le das de entrada lo que t\u00fa esperas de salida y entonces ya empieza a desarrollar realmente en los test unitarios se ven como que hago mi funci\u00f3n y ahora tengo hacer los test es mucho m\u00e1s trabajo mucho m\u00e1s esto es m\u00e1s lento no lo hago no no si t\u00fa desde el principio ya integran los test unitarios y empiezas a escribir lo que c\u00f3mo deber\u00eda entrar la entrada de c\u00f3mo deber\u00eda entrar la salida lo que el desarrollo de la funci\u00f3n lo vas haciendo sobre la marcha entonces ya el test ya lo tienes grabado y cuando ya termina ya te aseguras de que se est\u00e1 ejecutando correctamente puede darse alguna vez que la funci\u00f3n se haya roto por cualquier cosa que nosotros no control\u00e1ramos no pasa nada cogemos esa entrada nueva la grabamos como test y ya nos aseguramos que nuestra funci\u00f3n no se va a romper m\u00e1s veces con ese tipo de entrada sobre todo muy importante es que no hay regresiones que al final pues en nuestro c\u00f3digo mucho m\u00e1s confiable y luego pues que da mejor sensaci\u00f3n a los clientes y a los usuarios en definitiva lo he insistido mucho por eso que previene las regresiones aumenta la fiabilidad de la confianza facilita el mantenimiento como dec\u00eda si sale un nuevo error ese error lo podemos meter a a\u00f1adir nuestros test y a partir de ah\u00ed ya el mantenimiento del siguiente ya va a ser la nueva versi\u00f3n va a tener ese arreglo a ese problema la calidad es mucho mejor de nuestro c\u00f3digo y evidentemente cuando tenemos un c\u00f3digo mucho m\u00e1s confiable, mucho m\u00e1s fiable, no tiene regresiones, pues va a bajar much\u00edsimo la percepci\u00f3n de nuestro usuario, que al final es un poco lo que buscamos. Aqu\u00ed solo vamos a tocar el test unitario, pero bueno que sep\u00e1is que hay tres, test unitario, test de integraci\u00f3n y test funcionales, y que a partir de ah\u00ed podemos hacer. Os quiero dejar dos conceptos, no es el objetivo de esta charla, hablas de m\u00e9todo de trabajo, pero por lo menos que os vaya sonando, es Test Drive Development, que bueno, aqu\u00ed he hecho el dibujillo este que es as\u00ed un poco de mal, pero b\u00e1sicamente se basa en que t\u00fa primero generas el c\u00f3digo con un test, o sea, no, perd\u00f3n, haces el test en el c\u00f3digo, generas el c\u00f3digo y vas haciendo hasta que ya se cumple todo correctamente y vas haciendo. Entonces, desde el principio, la funci\u00f3n antes de empezar a escribirla, est\u00e1s generando lo que tiene que entrar y lo que debe salir. Este, si os document\u00e1is un poquito m\u00e1s, ver\u00e9is que hay un mont\u00f3n de cosas. Y otro, tambi\u00e9n otro concepto muy interesante es Trunk Based Development. Os dejo un enlace que hice en un art\u00edculo en que se basa. Y esto es, como nosotros trabajamos normalmente con un control de versiones, bueno, ah\u00ed en el art\u00edculo os mandar\u00e9, lo ver\u00e9is. La ventaja de hacer el Trunk Based Development quiere decir que t\u00fa usas una sola rama y cuando crea una nueva funcionalidad, crea una rama nueva. Hace esa rama, desarrolla, hace los test y si utiliza Gihab, los test autom\u00e1ticos, antes de integrarlo en la rama principal, le ejecuta un mont\u00f3n de test. En Plugin Check Plugin, que es un plugin que os recomiendo que hemos hecho el equipo de plugin, se ejecuta casi 800 afirmaciones, 800 y pico, con distintos entornos de PHP, con lo cual cuando t\u00fa sacas una nueva funcionalidad en el plugin te aseguras de que est\u00e1 muy bien, vamos que es muy consistente y no vas a tener ning\u00fan problema. Esto lo que se va a hacer es que s\u00f3lo tiene una rama y hace una rama para cada desarrollo nuevo, no hace varias ramas y va complicando el c\u00f3digo ah\u00ed os dejar\u00e9 un art\u00edculo y yo para que lo profundicen en \u00e9l bueno lo que nosotros al final queremos es que antes de hacer esa mergeo a la rama principal es decir que vamos a sacar una nueva versi\u00f3n porque se ejecuta un T autom\u00e1tico aqu\u00ed os ense\u00f1a uno que da error evidentemente cuando este por ejemplo este entorno de prueba autom\u00e1tica hace pruebas sobre el 74 el 80 el 81 y 82 y 83 lo normal es que si tiene un plugin para un cliente pues ya el entorno lo ten\u00e9is m\u00e1s o menos comprobado sab\u00e9is que php eso lo control\u00e1is m\u00e1s bien controlado entonces pues si est\u00e1is en un php 82 pues pod\u00e9is vosotros subirle 83 entonces el plugin no hay problema pero cuando hac\u00e9is un plugin comercial un plugin por no controlar el entorno si es verdad que nosotros las cabeceras de los plugins podemos decirle que sea hasta una versi\u00f3n de php o desde una versi\u00f3n php y por ah\u00ed ya puedes controlar un poco m\u00e1s entonces le mete este unitario en distintas versiones php a las que t\u00fa das soporte que evidentemente pues tienes que empezar por lo menos de las 74 y puede darse por ejemplo a m\u00ed me pas\u00f3 que un t\u00e9 autom\u00e1tico fallaba en el 74 y en la 8 si funcionaba pues perfecto estoy en el momento de arreglar mi c\u00f3digo para que no haya problema y otro concepto que bueno aqu\u00ed es simplemente como referencia voy a dejar un enlace para que pod\u00e1is descargar la presentaci\u00f3n vamos a entrar ahora a m\u00f3vil es cuando t\u00fa haces los test para esa salida que t\u00fa esperas vale se hace con estas funciones de web y es t\u00fa esperas un valor vale el valor esperado expecte como hab\u00e9is expecte y actual y el actual es el que te da tu funci\u00f3n de manera que t\u00fa puedes hacer tu afirmaci\u00f3n puedes afirmar si es si es verdadero es decir si tu funci\u00f3n devuelve un un true o un false pues t\u00fa puedes seg\u00fan la entrada que t\u00fa le des puedes comprobar si te va a dar un booleano que se te y en este caso un true un false si es igual a un valor eso lo vamos a ver tambi\u00e9n si yo por ejemplo vamos a hacer ejemplos sencillos y algunos ense\u00f1ar\u00e9 tambi\u00e9n m\u00e1s complejos por ejemplo yo puedo decir si yo te pongo en esta funci\u00f3n que sume un 2 y el 4 el valor esperado tiene que ser un 6 pues hacer igual t\u00fa poner 6 ah\u00ed grabado en el c\u00f3digo y la actual el que se ejecuta de la funci\u00f3n bueno hay un mont\u00f3n m\u00e1s aqu\u00ed os dejo unos cuantos los que m\u00e1s se usan as\u00ed un poco pues por ejemplo va a ser count por ejemplo si t\u00fa si t\u00fa haces una funci\u00f3n de entrada y esperas que haya o no s\u00e9 cu\u00e1ntos elementos pues t\u00fa dices pues quiero que me digas cu\u00e1ntos elementos me ha devuelto por ejemplo, hacer empty, que el array que me devuelva de la funci\u00f3n no est\u00e9 vac\u00edo. Y bueno, hay un mont\u00f3n. Realmente, incluso ya cuando ten\u00e9is el c\u00f3digo, met\u00e9is la IA en el c\u00f3digo, pues te va a poner assert y ya te van incluso sugiriendo distintas funciones y afirmaciones. Hay un mont\u00f3n y al final usamos unas pocas. Aqu\u00ed, por ejemplo, os hago un ejemplo, as\u00ed para verlo, pero ahora vamos a ver en el c\u00f3digo, de una funci\u00f3n que se llama removeSpecialCharacter. Y yo lo que espero es que de ese valor de entrada deber\u00eda devolverme valores sin\u2026 Esto tiene\u2026 Ah, mira, qu\u00e9 guay. De los valores estos de acento me deber\u00eda devolverlo sin acento. Entonces, aqu\u00ed como pod\u00e9is ver, hacer equals, devu\u00e9lveme esto. Entonces, yo ya me aseguro con esto que cada vez que se ejecuten los tests, mi funci\u00f3n va a dar esta devoluci\u00f3n. Y ahora despu\u00e9s podemos gastarle putadilla de decirle, pues ahora no te voy a mandar, te voy a mandar n\u00fameros. Y si me da fatal error, ya mi funci\u00f3n no funciona bien. Pues a lo mejor tengo que poner una verificaci\u00f3n de si es un n\u00famero o no. Pero lo importante no solo es que este es el ideal, este es el que, s\u00ed, s\u00ed, me va a dar siempre acentos, pues yo te voy a dar sin acentos, sino tambi\u00e9n tienes que buscar cosas raras, cosas que pueden pasar. Por ejemplo, yo tengo un plan, que vienen de API, por ejemplo, yo me conecto a una API y me devuelven un array, o sea, un JSON normalmente, lo convierto en array y ya de tal. Pero ese JSON, algunas veces, o viene vac\u00edo porque da una respuesta fallida, o a lo mejor me devuelve un valor que no era esperado, Pues todos esos casos normalmente te los puedes inventar aqu\u00ed, \u00bfvale? Los puedes meter. Incluso te puedes inventar cosas que a lo mejor el array venga vac\u00edo, para ver c\u00f3mo se comporta mi funci\u00f3n. Que a lo mejor la clave que yo busco que no est\u00e9. \u00bfQu\u00e9 pasa si no est\u00e1? Por ejemplo, yo me conecto a ARP y me traigo un JSON de productos. Y yo para el producto, por ejemplo, utilizo la clave SCOOP, que es el que me va a comprobar si existe mi tienda online, por ejemplo. Ahora ense\u00f1o un poco el c\u00f3digo ese. Pues, \u00bfqu\u00e9 pasa si el producto viene sin SQ? \u00bfQu\u00e9 va a hacer mi funci\u00f3n? \u00bfSe va a romper o no se va a romper? Por eso es muy importante. Entonces, os insisto mucho, no solo en estos casos ideales, que lo das muy claro y ya te lo da de vuelta, sino buscarle. De hecho, os voy a ense\u00f1ar, de donde sobre todo he sacado muchos test, hay much\u00edsimos, el Plugin y Chef Plugin. normalmente hacemos una funci\u00f3n de test que es testWithErrors o testWithOutErrors. O sea, WithErrors es que si yo le mando datos de entrada inv\u00e1lidos, \u00bfqu\u00e9 me va a hacer mi funci\u00f3n? \u00bfQu\u00e9 deber\u00eda devolverme? Entonces es muy importante porque eso tambi\u00e9n insisto bastante. He hecho un plugin muy sencillito, que lo ten\u00eda aqu\u00ed en WP Training. Esto es parte tambi\u00e9n, aparte de un tutorial que voy a hacer para el blog de WordPress, que ah\u00ed est\u00e1n en proceso de aprobaci\u00f3n, quer\u00eda que estuviera hoy, pero no ha podido ser. As\u00ed que, y la gu\u00eda, vamos a crear los test unitarios directamente en este taller. Quiero decir que me ha costado un poco, porque es verdad que no est\u00e1 muy bien documentado y es un proceso bastante largo. Si segu\u00eds este tutorial, directamente os va a llegar. Entonces, vamos a empezar con nuestro entorno. \u00bfSe ve por aqu\u00ed? \u00bfLo pongo mancho? \u00bfSe ve bien? Vale, bueno. Esto es un editor de c\u00f3digo, yo utilizo cursos, pero bueno, Visual Call, que quer\u00e1is. Podemos coger el enlace este, \u00bfvale? Uy, ya he dado el gracias. Vamos a coger el enlace del repositorio y lo vamos a clonar, \u00bfvale? A ver si tengo clones. lo voy a poner aqu\u00ed en usgalicia app public en plugin lo clono y aqu\u00ed tengo yo mi plugin que le quiero hacer este unitario Como veis aqu\u00ed tengo un par de funciones muy sencillitas, que aqu\u00ed cada uno dir\u00e9is yo lo har\u00eda as\u00ed, al final hice yo aqu\u00ed un replace de los datos de acento e incluso le hice una expresi\u00f3n regular para que me quitara s\u00edmbolos raros, por ejemplo un espacio o un 9 etc\u00e9tera. He hecho tambi\u00e9n una suma, una multiplicaci\u00f3n, etc\u00e9tera. Como veis directamente yo aqu\u00ed asumo que esto es un entero y ahora vamos a buscarle las cosquillas a esa funci\u00f3n para que no se me rompa y por ejemplo temas de Google y todo esto. Yo he hecho aqu\u00ed el tutorial y si lo segu\u00eds pues yo creo que os va a ir muy bien porque b\u00e1sicamente lo que intento es ir paso a paso para que pod\u00e1is instalar los plugins. Quien conozca WPKli, WPKli es WordPress a trav\u00e9s de la l\u00ednea de comandos, normalmente los entornos locales os lo pod\u00e9is instalar, va directo, y yo voy a utilizar el comando WP Scaffold, que es como una serie de comandos que te permite crear algo sobre la base, y el Scaffold se llama Plugin Test, y este es el plugin Nami, vamos a poner nuestro nombre y le vamos a decir que el Continued Integration lo vamos a hacer con Gihas, esos son los tres unitarios que se ejecutan, pues venga, vamos a ejecutar nuestra consola por aqu\u00ed y esto est\u00e1 en el entorno aqu\u00ed tengo vpclean, vpclean 2.12 y mi plugin, bueno, pregunt\u00e1ndome cosillas, si ten\u00eda alguna duda o alguna cosa. Y lo ejecuto. Muy bien, ya el primero. Error en las TBCs de la base de datos. Ah, vale, porque no la he\u2026 Ah, vale, no la ten\u00eda creada. Vale, me da error. esto que me pasa con la 8.2 en local.vp voy a cambiar el PHP ejecuto con mi comando a ver si ahora s\u00ed perfecto y ahora me crea una serie de archivos como veis me crea el workflow de github que lo vamos a tocar me crea el binario el binario lo que hace\u2026 ah bueno se me ha olvidado comentar un poco antes Para poder realizar T unitario hay dos formas, eso se me ha olvidado explicar. Para nosotros hacer los T unitario lo que se hace es que se hace en un WordPress que no tiene nada que ver con la instalaci\u00f3n local que nosotros tenemos. Eso est\u00e1 buscado a posta para que no haya ning\u00fan plugin tercero porque estamos hablando de T unitario y estamos evaluando esa funci\u00f3n. Es un WordPress que est\u00e1 vac\u00edo, que lo instalamos de base y la base de datos incluso la vamos borrando. La idea no es grabar ning\u00fan dato ah\u00ed y lo que hacemos es que la funci\u00f3n de entrada y salida, los datos de entrada, los generamos nosotros manualmente. Os voy a dar varios ejemplos para que os pod\u00e1is ver. Necesitamos tener PHP instalado en nuestro sistema, yo lo tengo instalado, y tener MySQL. ese es para composer me imagino conocer composer y bueno vamos a ejecutarlo con composer que es mucho m\u00e1s f\u00e1cil tambi\u00e9n est\u00e1 la versi\u00f3n de WPM que necesitas dock e instalar en tu guardado yo tambi\u00e9n lo tengo porque para ciertos repositores me hace falta y entonces pues bueno ah\u00ed lo tengo entonces el install sh vale lo que aqu\u00ed viene como esto se ejecuta bueno la vez t\u00fa puedes ejecutarlo las veces que quieras pero realmente no tenga que ser continuamente sigue una vez que se ha instalado bien salvo que no te derrota lo puede ejecutar b\u00e1sicamente lo que hace es que instala el wordpress desde cero entonces vamos a seguir aqu\u00ed los pasos para que ve\u00e1is que realmente son est\u00e1 muy bien descrito vale vamos con composer a traerle dependencias de desarrollador a nuestro plugin nos vamos a traer el php unit vale pero la versi\u00f3n de wordpress y vamos a coger tambi\u00e9n el de joas php polyfiles que b\u00e1sicamente lo que hace es que como php unit depende de la versi\u00f3n php que t\u00fa tengas pues se hizo esta repositoria para que no haya problemas en la versi\u00f3n de php y al final pueda ejecutarse unitario vale pues nada por instalamos y cogemos nuestro terminal y efectivamente estamos aqu\u00ed en la esta y lo ejecutamos nos lo instala en desarrollo y bueno ahora s\u00ed Ah, vale, perd\u00f3n, gracias. Vale, para ejecutar esos T unitarios hay varias librer\u00edas. Ahora hay una que se llama PEST, tambi\u00e9n que se conoce, y lo que hace ese entorno para poder ejecutar los T unitarios. Nosotros utilizamos PHP Unic, \u00bfvale? Y es el m\u00e1s com\u00fan en WordPress. Entonces, se utilizan los T unitarios. Entonces, efectivamente, es una librer\u00eda que te permite hacer las afirmaciones que hac\u00edamos, las da la librer\u00eda. \u00bfVale? S\u00ed, s\u00ed, gracias. As\u00ed que voy muy r\u00e1pido, voy directamente a hacer los test y al final vamos dejando cosas. A ver, cosas de directo. Dice que da error. Vamos a ver. Si me deja\u2026 Si no me conecto a mi m\u00f3vil. a lo mejor por proxy puede ser que tengamos algo\u2026 Vale, era por proxy, el proxy de la Universidad nos permite utilizar Composer. Bueno, ya est\u00e1, vale, me ha instalado aqu\u00ed un mont\u00f3n de\u2026 Lo bueno es que aqu\u00ed te instala la dependencia, bueno, nosotros lo conoces que eso, que instalamos PHP Unit, vale, y las distintas versiones, la versi\u00f3n de WordPress Unit y la de Polyfill que estaba comentando. Os va metiendo archivos que vamos a ir viendo. Otra cosa, cuando nosotros hacemos un plugin y ya cuando hacemos entorno de desarrollo, empezamos a generar archivos que son de desarrollo. Hab\u00e9is visto que el composer, generamos tambi\u00e9n el vendor, el vendor es todas las carpetas, todas las librer\u00edas que nosotros usamos. De hecho, el vendor, hay veces que tiene, depende del plugin, tiene librer\u00edas de desarrollo y algunas librer\u00edas finales que van al cliente. Que no las metes como desarrollo, las metes como finales. Entonces, \u00bfqu\u00e9 pasa? Que tenemos que meter en nuestro plugin directiva para que se guarden cosas en nuestro repositorio y otras cosas para el archivo que vamos a generar del plugin. Por eso, hay dos archivos muy interesantes que se llama gitignore y disignore que tienen pol\u00edticas diferentes disignore es cuando t\u00fa quieres generar un zip de ese plugin os dejaron tambi\u00e9n una charla donde lo explico el zip limpio, sin archivos raros y sin archivos de desarrollo nuestro zip que nosotros generamos del plugin no deber\u00eda tener entornos de desarrollo ni el.git ni cosas de desarrollo como phpunit, XML todo esto Es importante, y aqu\u00ed lo pongo, que estos archivos no est\u00e9n en nuestro zip final. Si est\u00e1 en nuestro repositorio, porque nosotros lo vamos a usar para desarrollar, pero no para el usuario final. Aqu\u00ed, por ejemplo, veis que en el archivo this is not, que es para generar mi zip, que va a ir despu\u00e9s a los usuarios para instal\u00e1rselo, le pongo aqu\u00ed la librer\u00eda de desarrollo para que no me la genere. y en la de kitignore, que son los archivos que no quiero que se me suben a mi repositorio, pues meto el vendor, por ejemplo, y los resultados de cach\u00e9 del phpunit. Pero bueno, eso vamos a entrar. El composer, \u00bfqu\u00e9 he hecho aqu\u00ed? Vamos a verlo. Se me queda esto aqu\u00ed un poco chiquitillo. El composer, \u00bfconoc\u00e9is todos composers? \u00bfHay alguno que no lo conozca? si lo conoc\u00e9is, \u00bfno? Vale, pues como veis, cuando he ejecutado este comando me ha puesto que estas librer\u00edas son de desarrollo y me ha metido el polyfill y el wp-php-unit Lo bueno de Composer es que tambi\u00e9n podemos meter comandos ya hechos porque hay veces que un comando s\u00faper largo nos permite hacer como un alias de comandos para poder ejecutarlo Entonces, aqu\u00ed os pongo un par de comandos que vamos a ejecutar y que vamos a a\u00f1adir yo lo explico para que no vamos a formatear el JSON aqu\u00ed en los comandos es una directiva que se llama Scripts el Composer Test lo que har\u00eda es ejecutarme el PHP Unit pero le voy a meter otros dos uno que es TestDebug bueno, esto es m\u00e1s interno m\u00edo pero bueno, lo quiero poner aqu\u00ed para que se ejecute una cosa muy interesante tambi\u00e9n en los test unitarias que t\u00fa puedes ejecutar el xdebath quien no conozca el xdebath es como que vas parando la ejecuci\u00f3n de tu desarrollo y vas viendo las variables como se van comportando en tu funci\u00f3n entonces es muy interesante cuando es una funci\u00f3n m\u00e1s compleja que le meta el xdebath pero bueno, este es y el test instant esta es la ejecuci\u00f3n de todo nuestro entorno de desarrollo aqu\u00ed en The WordPress como veis es un comando que pone bash ejecuta el bash de installwptest aqu\u00ed en este primer comando lo que dice es la base de datos el usuario la contrase\u00f1a y d\u00f3nde est\u00e1 yo ya se lo dejo a mi composer y as\u00ed lo ejecuto m\u00e1s f\u00e1cilmente porque pongo composer.test.instal y ya me hace todo ese comando no me lo tengo que recordar de hecho lo ten\u00eda guardado en un blog de notas y lo ten\u00eda que decir en contra si est\u00e1 el Composer Script y bueno aqu\u00ed hago una recomendaci\u00f3n m\u00e1s archivos que se me han instalado con este escafor se me ha instalado el phpcs que el phpcs son las normas de coding est\u00e1ndar y aqu\u00ed lo que hace este archivo es decir a esa directiva de coding est\u00e1ndar qu\u00e9 tiene que escanear qu\u00e9 cosas tiene que no escanear qu\u00e9 reglas tiene que usar, bueno, pues aqu\u00ed los tenemos, \u00bfvale? Por ejemplo, muy interesante, cuando me mira los prefijos, no ha gustado, me da a m\u00ed que dentro de 10 minutitos se va a ir m\u00e1s gente, cuando ve\u00e1is c\u00f3digo, el Value My Plugin, \u00bfvale? Aqu\u00ed suelo poner el prefijo de la traducci\u00f3n, \u00bfvale? Entonces me ayuda tambi\u00e9n a que no se me pasen cadenas, mi plugin es multidioma pues no se me pasa en cadena. Entonces todas estas cosillas son directivas de c\u00f3digo est\u00e1ndar. Bueno aqu\u00ed te iba a decir alguna cosa m\u00e1s, el Composer que ya lo hemos visto y el PHP Unit que estas son las directivas de PHP Unit. No me pregunt\u00e9is porque no s\u00e9 el detalle de las distintas versiones de PHP Unit pero hay a partir de una versi\u00f3n, no s\u00e9 cu\u00e1l es, la 8, la 9 que esta directiva deja de funcionar. Y entonces lo que dije, bueno, directamente la quito y mi carpeta de test, para ser m\u00e1s organizada, la voy a meter dentro de una subcarpeta. Porque lo ideal es que en la subcarpeta test pod\u00e1is meter m\u00e1s test. Por ejemplo, PHPStank, que tambi\u00e9n tengo ah\u00ed una, o test unitario, o m\u00e1s test, etc. o incluso agrupar los distintos test unitarios por de WooCommerce, que yo tambi\u00e9n lo hago. Quiero meter uno en Unit y otro de WooCommerce. Bueno, pues aqu\u00ed voy a poner una organizaci\u00f3n que sea Unit. Y voy a moverme el test sample para que ve\u00e1is c\u00f3mo se me ejecuta el test. Entonces voy a decirle, no, mis test est\u00e1n aqu\u00ed en Unit. Aqu\u00ed pone que excluya ciertos archivos como este, ya me lo he cargado, no hace falta. y aqu\u00ed tengo la directiva de phpunic pod\u00e9is profundizar m\u00e1s aqu\u00ed la idea es que por lo menos pod\u00e9is ejecutar los tres unitarios y pod\u00e9is profundizar mucho aqu\u00ed por ejemplo me metes colores bueno aqu\u00ed como quieras que se comporte claro la gracia de esto es que t\u00fa conforme ya coges un poquito ya de m\u00e1s experiencia pues vas teniendo tus propias directivas por la forma que te gusta a ti de codificar, de ejecutar los tests y todo eso. En este archivo est\u00e1n. Y luego hay un archivo tambi\u00e9n muy importante que es Bootstrap. Este es el PHP que se ejecuta antes de montar nuestro WordPress, porque realmente nosotros cuando ejecutamos el PHP Unit se monta el WordPress y ejecuta este PHP. Aqu\u00ed lo que hace es que ya en el Stafol nos ha metido ciertas funciones, ciertos archivos y de hecho no ejecuta el plugin que estamos nosotros montando. Si es WooCommerce, ahora veremos cosas de WooCommerce, podemos aqu\u00ed incluso que meta WooCommerce, que lo instale, porque si no las funciones de WooCommerce van a dar error. Total que aqu\u00ed podemos meter en esta manualiz load plugin, podemos meter dependencias de plane que nosotros veamos. Ahora vamos a ver c\u00f3mo lo modificamos porque claro, yo aqu\u00ed dec\u00eda que \u00edbamos a quitar el prefix, pero tambi\u00e9n voy a usar este c\u00f3digo que tambi\u00e9n ten\u00e9is aqu\u00ed porque despu\u00e9s voy a usar el wp-core-edit que muchas veces en los tres unitarios no est\u00e1 definido. Entonces me meto en vuestra, estas l\u00edneas. \u00bfQu\u00e9 hago en estas l\u00edneas? Pues meto una constante para decirme d\u00f3nde porque muchas veces los datos de entrada los podemos meter en el mismo c\u00f3digo pero muchas veces a lo mejor podemos coger un json de api y lo planteamos en una subcarpeta pues yo me pongo una subcarpeta que se llama unit test data plugin y utilizo esa constante dentro de mis tests y aqu\u00ed tambi\u00e9n otra constante wp core edit que me hace falta cuando vayamos a usar un woocommerce bueno no le da todav\u00eda instalar vamos a instalarlo composer test install y ahora va a ejecutar y guardado vamos a ejecutarlo y aqu\u00ed est\u00e1 ejecutando el binario se est\u00e1 bajando a wordpress lo est\u00e1 instalando veremos que si tenemos WooCommerce se va a instalar tambi\u00e9n WooCommerce en la siguiente y me dice claro, la base de datos WordPress Test, que es la que estoy yo apuntando ya existe pero aqu\u00ed no hay ning\u00fan miedo porque de hecho ah\u00ed no deber\u00edamos guardar nada entonces me est\u00e1 preguntando \u00bfquieres que borre la base de datos? s\u00ed, s\u00ed, t\u00edrale, que me da igual de hecho este binario es importante porque luego cuando lo ejecutemos en GitHub, ver\u00e9is c\u00f3mo se ejecuta en Gija y ya ahora mismo deber\u00eda funcionar vamos a ver si nuestro primer test unitario vale, pues ya lo hemos ejecutado como veis, tenemos aqu\u00ed un OK y nos est\u00e1 diciendo bastante informaci\u00f3n que ha utilizado la PHP Uni la versi\u00f3n 9.6 que no ha llegado ni casi, y ha gastado no s\u00e9 cu\u00e1nto de memoria pero lo m\u00e1s importante es el color que es verde, el amarillo y el rojo cuando nosotros ejecutamos test que vamos ahora programar unos cuantos vamos a ver los test que son las funciones diferentes y las distintas afirmaciones un test puede tener bastantes m\u00e1s afirmaciones es decir cuando yo hago un c\u00f3digo puedo ponerle varias afirmaciones vale que lo vamos a ver entonces aqu\u00ed el verde es lo que dec\u00eda el test driven t\u00fa vas a hacer la entrada poner la salida va ejecutando y va viendo entonces yo muchas veces una cosa tambi\u00e9n porque es m\u00e1s r\u00e1pido esto por ejemplo si yo quiero hacer una funci\u00f3n para un comer y lo hago si no lo hago con test tendr\u00eda que entrar a la parte de usuario para ejecutar esa funci\u00f3n luego tendr\u00eda que ejecutarla que pasa porque he tardado mucho tiempo aqu\u00ed directamente puedo incluso que vamos a ver tambi\u00e9n c\u00f3mo se filtra porque cada vez cada vez que tiene m\u00e1s test puede costar un mont\u00f3n Entonces, puede incluso ejecutar un test que es una clase o puede ejecutar una funci\u00f3n de esa clase, \u00bfvale? Para, digamos, terminar esa funci\u00f3n. Pues venga, la primera que era testSample, que es esta, \u00bfvale? Se ha ejecutado correctamente, \u00bfvale? Como veis, pues era muy sencilla, era muy f\u00e1cil de cumplir. AskertTrue, askertTrue sobre True, \u00bfvale? Pues no hemos hecho mucho, \u00bfvale? Entonces, vamos a hacer una primera funci\u00f3n. voy a dejar los nombres, lo normal es que vay\u00e1is agrupando los tests por grupos funcionales, un poco para organizaros, incluso por grupos funcionales, por tipo de tipolog\u00eda, y al final tengas varios archivos. Ahora ver\u00e9is que os voy a dar ejemplos de cosas que ya he hecho yo reales. Una cosa que hice era que me tra\u00eda de una API un producto y ten\u00eda que crear un producto variable. Me daba un error de que el c\u00f3digo de barra no me lo met\u00eda en una variante de ese producto. Pues hice el test, que era el JSON del producto, y quer\u00eda ver que esa variaci\u00f3n tuviera el barra c\u00f3digo. Despu\u00e9s arregl\u00e9 mi funci\u00f3n y efectivamente los tests me han validado. Pues venga, yo, como he dicho, tenemos unas funciones muy sencillas, multiplicaci\u00f3n, \u00bfvale? Pues venga, vamos a ejecutar un T sobre multiplicar, \u00bfvale? Pues el m\u00e1s sencillo ser\u00eda una entrada que sale perfecta. Yo, por ejemplo, A igual a 10, \u00bfvale? Y B igual a 20. Aqu\u00ed ya me est\u00e1 sugiriendo la IA, \u00bfvale? Me est\u00e1 sugiriendo la suma que A m\u00e1s B sea 30. Entonces yo ejecuto mi test y perfecto, se ha ejecutado correctamente. Pero como la vida no es ideal, imaginaros, este lo dejo porque esta es la ideal. De hecho, lo normal es que podamos hacer funciones sobre, por ejemplo, aqu\u00ed, por ejemplo, Tep Zoom without errors. No, without, no, co\u00f1o. Without errors, \u00bfvale? Aqu\u00ed voy a agrupar las afirmaciones cuando no hay ning\u00fan problema. cuando la entrada es limpia. Imaginaros, pues yo voy a meter tambi\u00e9n\u2026 No, ahora, esto es lo que quiero hacer despu\u00e9s. No, ahora. Voy a poner, por ejemplo, un decimal. Imaginaros, \u00bfno? Yo aqu\u00ed empiezo\u2026 Claro, los test muchas veces, ya tambi\u00e9n, cuando vas teniendo m\u00e1s experiencia, vas viendo d\u00f3nde puedes darle ca\u00f1a a la funci\u00f3n y dices, \u00bfd\u00f3nde voy a ver yo aqu\u00ed el conflicto? Y lo haces. Luego hay veces que te sorprende, porque ves casos que no\u2026 \u00bfVale? Pues aqu\u00ed hacemos otro. Aqu\u00ed la propia AIA me est\u00e1 sugiriendo varios, con negativos, con positivos. \u00bfVale? Vamos a ver qu\u00e9 pasa. Mira, aqu\u00ed, por ejemplo, me ha dado un error. \u00bfPor qu\u00e9, David? En la l\u00ednea 23, \u00bfvale? Esperaba 0,3 y la suma le ha dado esto. Entonces vamos a ver aqu\u00ed en la suma. Aqu\u00ed algo tiene que ver. Por ejemplo, \u00bfves? \u00bfMe dieron qu\u00e9? Ah, vale, vale. Aqu\u00ed quiere decir algo. Vale, pues a lo mejor aqu\u00ed podr\u00eda hacer un number format. Un number format. Format. Dos decimales. \u00bfVale? Y si me da ya como. \u00bfOk? \u00bfVale? Pero esto es la vida ideal. O sea, yo te doy un 2 y un 3 y me va a dar 5. Pero, \u00bfqu\u00e9 pasa a lo normal? el usuario no pone un 2, pone un texto o pone hola, yo que s\u00e9 pues vamos a ver qu\u00e9 pasa con nuestra funci\u00f3n cuando hay problemas \u00bfvale? que esto es lo normal esta es la vida id\u00edlica, pero est\u00e1 aqu\u00ed, vamos a ir a ver vamos a buscarle como dec\u00eda putadilla a nuestra funci\u00f3n imaginaros que yo le estoy dando un texto vamos a ver c\u00f3mo se comporta mi funci\u00f3n me lo estaba diciendo a m\u00ed, \u00bfvale? a ver qu\u00e9 pasa con mi funci\u00f3n deber\u00eda devolver un 30, \u00bfvale? pero no lo va a devolver porque, bueno, nada m\u00e1s que devuelve ah, bueno, pues aqu\u00ed s\u00ed me lo ha cogido bien me ha convertido el 10 en n\u00famero \u00bfvale? o sea que este, por lo pronto ya acabo de verificar que mi funci\u00f3n aunque le meta un string me va a hacer la suma \u00bfvale? pero imaginaros que ahora no, esto no voy a hacerlo aqu\u00ed me pone un texto que no tiene nada que ver con la funci\u00f3n. Aqu\u00ed a lo mejor deber\u00edamos dar, podemos devolver un false, por ejemplo, ya podr\u00edamos inventar un poco qu\u00e9 nos deber\u00eda dar la funci\u00f3n si no\u2026 o imaginar un vac\u00edo, por ejemplo. Vamos a hacer primero un vac\u00edo, por si quer\u00e9is. aqu\u00ed me ha dado dos errores efectivamente, me est\u00e1 diciendo que aqu\u00ed hay un entero y un string en la 49 esa es la funci\u00f3n y en la 41 entonces, \u00bfqu\u00e9 ha pasado aqu\u00ed? que esto era un vac\u00edo y me debe haber dado o aqu\u00ed podemos decidir que deber\u00eda darme en funci\u00f3n, si deber\u00eda dar un false, por ejemplo, y despu\u00e9s yo ejecuto esa funci\u00f3n y veo si es false, le muestro un error al usuario, han metido mal los datos o lo que sea, o aqu\u00ed ya es decisi\u00f3n un poco nuestra, que queremos que se le muestre al cliente, al usuario. Mi primera decisi\u00f3n podr\u00eda ser, por ejemplo, forzar que los n\u00fameros sean enteros o decimales, Entonces yo puedo decir, o pongo aqu\u00ed el a, \u00bfves? Flow as bar, flow as bell, y aqu\u00ed lo que va a hacer es que me va a convertir. El vac\u00edo me da un cero normalmente cuando lo convierto. Entonces aqu\u00ed me va a sumar, a ver, aqu\u00ed 10 y 0 deber\u00eda ser un 10 para que se ejecutara bien la funci\u00f3n, \u00bfvale? Pues yo ejecuto y me lo he ejecutado correctamente. Entonces ya, lo pronto, tal. Vamos a buscarle m\u00e1s cosquillas. Vamos a buscarle que sean textos. Yo aqu\u00ed, bueno, me va a dar error la funci\u00f3n, por supuesto, \u00bfvale? Porque lo que ha hecho es que el texto le ha pasado a cero, \u00bfvale? Entonces, aqu\u00ed, aqu\u00ed ya os digo que depende un poco de nosotros. \u00bfqu\u00e9 queremos que nos devuelva la funci\u00f3n si nos han dado unos datos de entrada incorrectos? Pues podemos decirle que nos d\u00e9 un false, o yo, por ejemplo, con la API lo que suelo hacer es que devuelvo un array con un resultado, me queda muy poco, \u00bfno? Y en el resultado le digo que es ok o false, le pongo un mensaje, le doy m\u00e1s datos, porque al final lo que quiero es que el usuario vea por qu\u00e9 ha cometido el error. Pero bueno, aqu\u00ed como vamos r\u00e1pido, vamos a decir que, por ejemplo, si no es num\u00e9rico, que devuelva un cero. O a lo mejor que devuelva un falso, por lo que sea. Vamos a decir que sea un cero. Entonces, yo aqu\u00ed deber\u00eda esperar, bueno, aqu\u00ed me he dicho que mi test, aqu\u00ed deber\u00eda esperar un cero. pues efectivamente bueno el 41 aqu\u00ed no hab\u00edamos quedado este vale s\u00ed claro esto era vac\u00edo era un string sino el num\u00e9rico este d\u00eda sea un 0 no voy a ser un 10 pues aqu\u00ed directamente entonces como veis yo voy ejecutando mi funci\u00f3n le voy buscando las cosquillas voy buscando cosas raras que pasan y quiero que me lo ejecute vamos a algo m\u00e1s complicadillo en estos \u00faltimos 10 minutos si no te me va diciendo preguntas por ejemplo lo que os dec\u00eda en el ejemplo de una funci\u00f3n que me ejecuta datos datos raros aqu\u00ed lo voy a meter todo junto vale no es lo ideal lo suyo es que lo vaya agrupando en distintas vamos a hacer un test test_special_chart vale y bueno aqu\u00ed me lo coge esto as\u00ed tal cual vamos a ejecutar la vegetal efectivamente se ejecuta bien yo le met\u00ed aqu\u00ed datos raros y tal m\u00e1s funciona bien esto ser\u00eda imaginaros que ahora yo quiero buscar en las cosquillas y quiero hoy quiero ver qu\u00e9 pasa con mi funci\u00f3n si yo le meto espacio, lo normal es que los quite. Voy a ponerle un espacio, voy a ponerle un gui\u00f3n, voy a ponerle un arroba, a ver qu\u00e9 es lo que me devuelve. Lo bueno tambi\u00e9n de los test es que si no se cumpliera, si yo por ejemplo digo que deber\u00eda ser aqu\u00ed un gui\u00f3n, una cosa muy interesante es que te devuelve, fijar aqu\u00ed, lo he esperado, aqu\u00ed te devuelve lo que deber\u00eda esperar a lo que actual estoy generando. Entonces, aqu\u00ed, por ejemplo, mi funci\u00f3n lo que hace es que los espacios y los s\u00edmbolos raros los quita. Con lo cual, aqu\u00ed, esta es la funci\u00f3n que yo deber\u00eda recibir. Y entonces, pues aqu\u00ed, ya se va cumpliendo. Entonces, as\u00ed vamos creando. \u00bfQu\u00e9 pasa? Ahora yo creo una nueva funci\u00f3n, una nueva cosa. Hago alg\u00fan cambio. Y como lo que no queremos es que si yo hago un cambio, luego se rompa otra cosa. Pues lo bueno es que como ya lo he dejado guardado en el c\u00f3digo, cuando yo vaya a generar una nueva funci\u00f3n no me va a romper otras cosas. Quer\u00eda ense\u00f1aros algo m\u00e1s complicado. Por ejemplo, yo tengo alg\u00fan\u2026 Porque como veis, este ejemplo ha sido muy sencillito. vale, es que no inici\u00e9 la sesi\u00f3n no, s\u00ed ah, vale, el or se me ha faltado aqu\u00ed el or aqu\u00ed por ejemplo yo he hecho test un poco m\u00e1s pu\u00f1eterillo por ejemplo, yo aqu\u00ed lo que hago es que uy, que chico vale, yo por ejemplo aqu\u00ed he hecho un test que seg\u00fan un JSON que me d\u00e9 una API, vale quiero que me crea un producto entonces, bueno, aqu\u00ed lo pod\u00e9is ver tranquilamente, luego lo veis pero b\u00e1sicamente yo le mando un JSON de producto, \u00bfvale? y con mi funci\u00f3n que es la que crea ese producto en el WooCommerce y me lo ejecuta yo quiero ver qu\u00e9 es lo que me devuelve, esto lo que hace es que devuelve un array y me devuelve el post ID que genera, como es un como es un WordPress que est\u00e1 vac\u00edo yo no puedo controlar el n\u00famero que me devuelve aqu\u00ed pero si puedo ver que no est\u00e1 vac\u00edo el array que me devuelve que el status es ok y que esto es un entero y aqu\u00ed empiezo ya a hacer cosas, le digo pues venga tr\u00e1eme el producto, m\u00edrame que sea producto simple del scoop que yo te daba mira a ver si efectivamente la funci\u00f3n de ProductSchool es el mismo. Como veis, aqu\u00ed estoy verificando que la importaci\u00f3n del producto se ha hecho correctamente y que mi funci\u00f3n, que es esta, la he ejecutado correctamente. Aqu\u00ed, como veis, incluso miro el precio. Mi funci\u00f3n, por ejemplo, tiene una cosa que es que si me lo traigo de la API, cuando el producto ya existe, no deber\u00eda cambiarme el t\u00edtulo de descripci\u00f3n porque si no entonces machaca pues entonces yo le digo c\u00e1mbiame el t\u00edtulo de descripci\u00f3n me lo invento y luego despu\u00e9s de ejecutar mi funci\u00f3n m\u00edrame que no me hayas cambiado y efectivamente no me la cambia bueno aqu\u00ed hay un mont\u00f3n de cosas por ejemplo mira aqu\u00ed tengo yo with errors le quito el scu y qu\u00e9 pasa mi funci\u00f3n antes de hacer test daba fatal error vale le mandaba un jason con un sin scoom y me da fatal error para no me da error ahora lo que hace es que me devuelve una una un array con un error y un mensaje para que el usuario le diga oye que este est\u00e1 piquet\u00f3n ha dado este producto que m\u00e1s da del rp o lo que sea pues tiene error y efectivamente me devuelve un cero que normalmente cuando no se queda un producto el el poseid suele ser 0 y bueno aqu\u00ed podemos hacer lo que quer\u00e1is os animo, hay un repositorio que est\u00e1 muy bien que es el de plugin check plugin plugin guija que ah\u00ed tenemos infinidad y realmente ah\u00ed si hacemos el flujo de aqu\u00ed est\u00e1 guija aqu\u00ed si hacemos el flujo de programar un check hacer los test y hasta los equipos de trabajo ya m\u00e1s avanzados trabajan as\u00ed. No me ha dado una funci\u00f3n si no me ha hecho el subtest. Si no, no hay. De hecho, aqu\u00ed los pull requests que nosotros hacemos, voy a ense\u00f1ar algunos cerrados, se han tenido que ejecutar los tests unitarios y se llegan\u2026 A ver si hay alguno m\u00edo por aqu\u00ed. Como se meten los de dependados\u2026 aqu\u00ed hay uno m\u00edo, yo hice, no, pero este no lo termin\u00e9, este est\u00e1, veis este por ejemplo no tiene los test, aqu\u00ed est\u00e1 uno, aqu\u00ed hice yo un check, \u00bfvale? y en mi desarrollo yo hac\u00eda el check, aqu\u00ed hac\u00eda el desarrollo que era este check y luego le met\u00ed a los test unitarios y as\u00ed, y como veis, de cara al desarrollo, pues m\u00e1s f\u00e1cil saber que cuando t\u00fa lo ejecutas, O sea, cuando se ejecutan los checks, en este repositorio se ejecutan 27 checks, que est\u00e1n incluso el estilo de c\u00f3digo, los tres unitarios, y los tres unitarios se ejecutan en distintas versiones de PHP, 7.4, 8.8.0, 8.1.2, 8.4, y 8.4 incluso en experimental. ya estamos incluso haciendo check para el PHP 8.4 para cuando este plugin salga ya tener eso previsto. Y al final lo que quiero decir es que cuando t\u00fa vas a hacer ese desarrollo, bueno aqu\u00ed hay una discusi\u00f3n de c\u00f3mo deb\u00eda ser y tal, ah bueno es que esto lo oculta una vez que est\u00e1 terminado. Perd\u00f3n, que me voy muy r\u00e1pido. Cada vez que t\u00fa haces un c\u00f3mic en ese QR, si segu\u00eds la gu\u00eda, podr\u00eda hacerlo tambi\u00e9n en Guija. Nos aseguramos que se ejecuten esos tests autom\u00e1ticamente, porque aqu\u00ed lo hemos ejecutado nosotros local. Pero cuando lo integras con Guija, esos tests se hacen directamente tambi\u00e9n en Guija. Con lo cual, t\u00fa antes de tu nuevo desarrollo incorporarlo a la versi\u00f3n principal, tambi\u00e9n te aseguras de que se hace el test autom\u00e1tico. y aqu\u00ed se hacen como 900 una barbaridad no es lo mismo que yo haga un c\u00f3digo en definitiva, que es lo que yo quer\u00eda al final que vi\u00e9ramos un c\u00f3digo que se ha ejecutado pues se ha ejecutado 900 test como va a ser lo mismo a que yo directamente me queda todav\u00eda 5 minutillos, puedo aprovechar todav\u00eda a ver, mejor \u00bften\u00e9is alguna pregunta? \u00bfv\u00e1is a poner a CST a partir de ahora o no? Como tengo estos 5 minutos voy a decir por ejemplo una dependencia. Si tengo un plugin para hacer WooCommerce, aqu\u00ed os dejo c\u00f3mo ejecutar text para plugin de WooCommerce. Claro, yo al traerme el WordPress tengo que instalar esas dependencias. Aqu\u00ed os dejo el c\u00f3digo que es dentro para incorporar el bash para que se baje el WooCommerce y luego claro en el bootstrap que es el PHP que se ejecutaba antes de que empezara nuestro WordPress tengo que decirle que incorpore WooCommerce porque si no cuando yo vaya a hacer test y meta cuando llegue a test de WooCommerce de estas funciones la funci\u00f3n vcgetproduct me dar\u00eda fatal error pues vamos a hacerlo si yo creo que me da tiempo muy f\u00e1cil nos metemos aqu\u00ed al binario y aqu\u00ed antes de ejecutar las distintas funciones le meto el install wwocommerce que lo voy a ejecutar despu\u00e9s del wordpress ah\u00ed ya tendr\u00eda instalado WooCommerce en mi test que lo voy a ejecutar pero necesito que est\u00e9 activo entonces en el en el bootstrap aqu\u00ed en manually load plugins aqu\u00ed meto mi WooCommerce antes de que se ejecute mi funci\u00f3n entonces con estos dos ajustes ya tengo WooCommerce pero tengo que instalarlo entonces composes test install vale me va a machacar el wordpress me da igual no pasa nada se me va a bajar wu comer y me va a decir si quiero borrar base datos s\u00ed sin problema ya tengo wu comer y ya podr\u00eda incluso ejecutar cosas de wu comer por ejemplo bueno es que estas funciones aqu\u00ed son un poco gen\u00e9ricas porque tienen que tener un Product ID. Aqu\u00ed deber\u00eda, para ejecutar esta funci\u00f3n, en mi funci\u00f3n TestPublic, tres minutillos, ya voy a dar el cierre. Claro, para dar yo mi funci\u00f3n, deber\u00eda crear yo antes un producto, que lo puedes hacer a trav\u00e9s de distintas funciones. Entonces yo podr\u00eda darle Product, VsGueProduct, no. Al final, para que yo pueda ejecutar mi afirmaci\u00f3n sobre este plugin, que va a necesitar un Product Get ID. Antes tengo que crear el producto porque no existe. Lo creo y con esa creaci\u00f3n de ese producto ya puedo hacerle test a lo que me ha devuelto WooCommerce. Entonces, ah\u00ed directamente puedo saber un poco. En definitiva, esto es un principio para que vosotros pod\u00e1is ejecutar test. que realmente os animo y para que empecemos a cambiar el chip desde empezar la funci\u00f3n a empezar a programarla primero hagamos los test de entrada los datos de entrada empecemos a ejecutar los datos de salida y ir programando nuestra funci\u00f3n hasta que el test se haga completamente de manera que cuando ya vaya a hacer yo m\u00e1s cosas eso ya como que me olvido ya de definitiva nada, pues agradeceros por escucharme y espero que lo pong\u00e1is en pr\u00e1ctica desde hoy ya de verdad que a m\u00ed me ha cambiado bastante el desarrollo porque digamos que te preocupa de problemas que t\u00fa a lo mejor te has encontrado y que no te vas a encontrar despu\u00e9s evidentemente puede los datos de entrada pueden cambiar pero t\u00fa lo puedes ir actualiz\u00e1ndolo en tu test muchas gracias yo como ha dicho jes\u00fas pues soy cteo de la agencia cloud y en mi tiempo libre pues soy team red del plugin temps o sea que si hab\u00e9is mandado alg\u00fan alg\u00fan plugin al repositorio de WordPress, al director de WordPress, seguramente lo habr\u00e9is revisado. As\u00ed que muchas gracias a todos. No hab\u00e9is ninguna pregunta, \u00bfeh? No ten\u00e9is\u2026 Ah, mira, hay un par de ellas. R\u00e1pido. Rapidillo. Venga, que nos da tiempo, un minuto. R\u00e1pido. Yo me met\u00ed en programar plugins por un horror de LearnDash y funcionalidades que quer\u00eda manuales. Si no, no acababa ah\u00ed ni de broma. Todo esto es para plugins que vas a subir a WordPress y compartir con otras personas. No, no, para un plugin tuyo propio incluso. Y no es demasiado, porque veo que est\u00e1s haciendo todas las cosas, por ejemplo, de WooCommerce manuales sin frontend, o sea, las haces t\u00fa. S\u00ed, s\u00ed, directamente. Entonces tienes que conocer much\u00edsimo el entorno con el que trabajas y replicar todos los comportamientos de todos los tests que yo har\u00eda con clics. S\u00ed. Bueno, es que ese es el test de integraci\u00f3n. Ese es un test a\u00f1adido. Esto es cuando una funci\u00f3n que hace un proceso t\u00fa quieres hacer test automatizados para esa funci\u00f3n el test que t\u00fa dices t\u00fa de integraci\u00f3n se llama un test avanzado que es m\u00e1s de integraci\u00f3n pero que b\u00e1sicamente t\u00fa al final, los test unitarios cuando t\u00fa tienes muchas funciones al final tienes que ejecutar juntas entonces hay tambi\u00e9n test para ejecutar esas funciones completas que tampoco quer\u00eda entrar mucho pero que hay otro tipo de test tambi\u00e9n recomendado test de integraci\u00f3n Me ha parecido s\u00faper interesante, la verdad. Bueno, yo me voy un poco m\u00e1s atr\u00e1s. Yo no suelo hacer mucho desarrollo, pero estoy empezando ah\u00ed a pelearme un poquito con algunas cosas, tambi\u00e9n por proyectos propios y por luego por cosas que a veces encuentras en cliente y que acabas teniendo que meter mano. Y yo me voy m\u00e1s atr\u00e1s, has dicho, \u00bfqui\u00e9n conoce Composer? Y digo, ah\u00ed yo ya me he perdido. O sea, entiendo de test porque he trabajado en desarrollo y s\u00e9 de qu\u00e9 va la vaina porque tengo compa\u00f1eros testers, pero ah\u00ed me pierdo. \u00bfC\u00f3mo empezar\u00eda alguien que quiere empezar a desarrollar y empezar a meterse en todo esto? Que no sea estar en el notepad. S\u00ed, s\u00ed, s\u00ed. Bueno, Composer PHP, Composer es una forma de instalar, aqu\u00ed sale como un director de orquesta, b\u00e1sicamente es un archivo que t\u00fa guardas en tu plugin, un poco as\u00ed resumido, donde te pone todas las dependencias de tu plugin. Entonces, cuando ya empiezas a hacer plugins m\u00e1s avanzados y que tienen muchas m\u00e1s funcionalidades, tienes dependencias. Y la gracia de la dependencia tambi\u00e9n es que las puedes ir actualizando. Mucho m\u00e1s f\u00e1cilmente que si t\u00fa te bajaras la librer\u00eda y la incorporaras en un subdirectorio de tu plugin. La mejor forma de hacerlo es con Composer. Te lo tienes que instalar en tu ordenador porque al final lo ejecutas en comando. Y bueno, ah\u00ed librer\u00eda lo que t\u00fa quieras. Incluso t\u00fa puedes crear propias librer\u00edas. Y el entorno ese que estabas utilizando, \u00bfqu\u00e9 es? \u00bfCu\u00e1l qu\u00e9 entorno? Porque ah\u00ed yo ya\u2026 Ah, s\u00ed, el cursor. Yo usaba cursor. Esto. S\u00ed, pero esto es cursor. Porque eso he visto, de que te ha empezado ya a recomendar todo la IA directamente, te sacaba las propuestas de tal. Esto es una maravilla. Bueno, pues tienes Visual Code o con Guiz Casco Pailo, que tiene una versi\u00f3n gratuita, que para empezar est\u00e1 muy bien, y te va autosuscribiendo. Como ves, me va suscribiendo, me tengo que\u2026 Al final, los desarrolladores que estamos implementando la IA, en nuestro desarrollo, pues lo que hacemos es pelearnos con la IA, b\u00e1sicamente. Porque t\u00fa, incluso con el chat, que aqu\u00ed no he usado yo el chat porque tampoco era\u2026 Aqu\u00ed le puedes decir, pues h\u00e1zme los test, porque claro, yo quer\u00eda que conociera el concepto, pero t\u00fa le puedes decir, h\u00e1zme los test unitarios para este plugin. Y te lo puede hacer. Y te los crea, te crea los archivos y todo eso. Pero GitHub Copilot, has dicho que es como este extra de IA que le puedes poner. S\u00ed, justo. Y en curso va ya incorporado. Bueno, esto es los ID. \u00bfQu\u00e9? Es que no\u2026 S\u00ed, te digo, est\u00e1 Cursor. Eso. Bueno, est\u00e1 Winsure. Bueno, aqu\u00ed. Ya ver\u00e1s, en el Cafelillo, pues, algunos ser\u00e1n de un\u2026 Este es el mejor ID. No, t\u00fa no, que est\u00e1s usando Visual Code, no tienes ni idea. Total, hay tambi\u00e9n un poco de enfrentamiento en el ID. \u00bfNo? Hay algunos que son de PHP Store. Pero, bueno, b\u00e1sicamente Visual Code. A m\u00ed me gusta, yo, del editor, nos vamos all\u00e1. del editor que ten\u00edamos antes, que era un notepad, a Visual Code fue un cambio muy gordo porque ten\u00edamos el Git incorporado y la terminal. Como hab\u00e9is visto, yo he podido juntar, me he podido clonar, eso fue un cambio totalmente. Y ya Visual Code, como es OpenC\u00f3digo Abierto, han sacado ramificaciones. Cursor es igual que Visual Code, o sea que si sabes manejar Visual Code, puedes manejar Cursor. Y al final lo que hace es que te incorpora la AIA en tu desarrollo. Y te va sugiriendo. Pero al final es un trabajo de pelearte. Porque te empiezas a sugerir cosas. Esto no tiene nada que ver. \u00bfDe qu\u00e9 punto de vista de productividad hay alguna diferencia grande entre el gusto y el gusto? Es gusto. Es gusto. A m\u00ed me gusta m\u00e1s curso porque est\u00e1 m\u00e1s actualizado. Los agentes los meten antes. Y cuando sale Cloud, por ejemplo, ha salido la 4, pues la meten y la incorporan antes. Bueno, el Visual Code tambi\u00e9n es muy avanzado. Est\u00e1 muy bien. Es gusto, ya te digo. Tambi\u00e9n est\u00e1 Winsur. est\u00e1 trade esto ya es como peleas de desarrolladores fricadas as\u00ed que nada pues nada, muchas gracias y cualquier cosilla me ten\u00e9is en la web, echadle un vistacillo a la web de David P\u00e9rez Garca os meto cosillas de os meto cosillas y ah\u00ed ten\u00e9is la charla de hoy la ten\u00e9is aqu\u00ed \u00bfvale? directamente y ah\u00ed seguir los pasos y ustedes tienen que dar el test directamente pues nada, pues muchas gracias<\/p>\n<\/details>\n","protected":false},"excerpt":{"rendered":"<p>Este es el tutorial que vamos a tener en cuenta para la charla de la WordCamp Galicia 2025. Antes, dos conceptos: Configurar tu plugin con Unit Tests Esta gu\u00eda est\u00e1 basada en la realizaci\u00f3n de Tests con PHPUNIT e instalado en el propio repositorio con composer. Es la forma m\u00e1s f\u00e1cil de que los desarrolladores [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4428,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":23,"footnotes":""},"categories":[169,550],"tags":[582],"class_list":["post-4421","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-charlas","category-codigo","tag-wordcamp-galicia"],"_links":{"self":[{"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/posts\/4421","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/comments?post=4421"}],"version-history":[{"count":1,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/posts\/4421\/revisions"}],"predecessor-version":[{"id":5161,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/posts\/4421\/revisions\/5161"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/media\/4428"}],"wp:attachment":[{"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/media?parent=4421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/categories?post=4421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/davidperezgar.com\/es\/wp-json\/wp\/v2\/tags?post=4421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}