Estoy desarrollando un complemento con TDD y una cosa que no puedo probar son ... ganchos.
Quiero decir, OK, puedo probar la devolución de llamada de gancho, pero ¿cómo podría probar si un gancho realmente se dispara (ganchos personalizados y ganchos predeterminados de WordPress)? Supongo que algunas burlas ayudarán, pero simplemente no puedo entender lo que me estoy perdiendo.
Instalé el conjunto de pruebas con WP-CLI. Según esta respuesta , el init
gancho debería activarse, pero ... no lo hace; Además, el código funciona dentro de WordPress.
Según tengo entendido, el bootstrap se carga al final, por lo que tiene sentido no activar init, por lo que la pregunta que queda es: ¿cómo diablos debería probar si se activan los ganchos?
¡Gracias!
El archivo de arranque se ve así:
$_tests_dir = getenv('WP_TESTS_DIR');
if ( !$_tests_dir ) $_tests_dir = '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';
function _manually_load_plugin() {
require dirname( __FILE__ ) . '/../includes/RegisterCustomPostType.php';
}
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
require $_tests_dir . '/includes/bootstrap.php';
el archivo probado se ve así:
class RegisterCustomPostType {
function __construct()
{
add_action( 'init', array( $this, 'register_post_type' ) );
}
public function register_post_type()
{
register_post_type( 'foo' );
}
}
Y la prueba en sí:
class CustomPostTypes extends WP_UnitTestCase {
function test_custom_post_type_creation()
{
$this->assertTrue( post_type_exists( 'foo' ) );
}
}
¡Gracias!
fuente
phpunit
, ¿puede ver pruebas fallidas o pasadas? ¿Instalastebin/install-wp-tests.sh
?RegisterCustomPostType::__construct()
nunca se llama cuando se carga el complemento para las pruebas. También es posible que esté siendo afectado por el error # 29827 ; quizás intente actualizar su versión del conjunto de pruebas unitarias de WP.bin/install-wp-tests.sh
(que no uso wp-CLI) @JD: RegisterCustomPostType :: __ construct se llama (acaba de añadir unadie()
declaración y PHPUnit se detiene allí)did_action()
para verificar si las acciones se dispararon.init
enlace).Respuestas:
Prueba aislada
Al desarrollar un complemento, la mejor manera de probarlo es sin cargar el entorno de WordPress.
Si escribe código que se puede probar fácilmente sin WordPress, su código se vuelve mejor .
Todos los componentes que se prueban por unidad deben probarse de forma aislada : cuando prueba una clase, solo tiene que probar esa clase específica, suponiendo que el resto del código esté funcionando perfectamente.
Esta es la razón por la cual las pruebas unitarias se denominan "unidad".
Como beneficio adicional, sin cargar el núcleo, su prueba se ejecutará mucho más rápido.
Evitar ganchos en constructor
Un consejo que puedo darle es evitar poner ganchos en los constructores. Esa es una de las cosas que hará que su código sea comprobable de forma aislada.
Veamos el código de prueba en OP:
Y supongamos que esta prueba falla . ¿Quién es el culpable ?
¿Cómo se puede mejorar?
Supongamos que su código de clase es:
(Nota: me referiré a esta versión de la clase para el resto de la respuesta)
La forma en que escribí esta clase le permite crear instancias de la clase sin llamar
add_action
.En la clase anterior hay 2 cosas para ser probadas:
init
realmente llamaadd_action
pasarle argumentos apropiadosregister_post_type
realmente llama a laregister_post_type
funciónNo dije que debe verificar si el tipo de publicación existe: si agrega la acción adecuada y si llama
register_post_type
, debe existir el tipo de publicación personalizada : si no existe, es un problema de WordPress.Recuerde: cuando prueba su complemento, debe probar su código, no el código de WordPress. En sus pruebas, debe asumir que WordPress (al igual que cualquier otra biblioteca externa que use) funciona bien. Ese es el significado de la prueba unitaria .
Pero ... en la práctica?
Si WordPress no está cargado, si intenta llamar a los métodos de clase anteriores, obtendrá un error fatal, por lo que debe burlarse de las funciones.
El método "manual"
Claro que puede escribir su biblioteca de burla o burlarse "manualmente" de cada método. Es posible. Te diré cómo hacerlo, pero luego te mostraré un método más fácil.
Si WordPress no se carga mientras se ejecutan las pruebas, significa que puede redefinir sus funciones, por ejemplo,
add_action
oregister_post_type
.Supongamos que tiene un archivo, cargado desde su archivo bootstrap, donde tiene:
Reescribí las funciones para simplemente agregar un elemento a una matriz global cada vez que se llaman.
Ahora debe crear (si aún no tiene uno) su propia clase de caso de prueba base que se extienda
PHPUnit_Framework_TestCase
: eso le permite configurar fácilmente sus pruebas.Puede ser algo como:
De esta manera, antes de cada prueba, el contador global se reinicia.
Y ahora su código de prueba (me refiero a la clase reescrita que publiqué anteriormente):
Debes tener en cuenta:
Bonito ... pero es una PITA!
Sí, si tiene que burlarse manualmente de todas las funciones de WordPress, es realmente un dolor. Algunos consejos generales que puedo dar es usar la menor cantidad posible de funciones de WP: no es necesario reescribir WordPress, sino funciones abstractas de WP que se usan en clases personalizadas, de modo que se puedan burlar y probar fácilmente.
Por ejemplo, con respecto al ejemplo anterior, puede escribir una clase que registre tipos de publicaciones, invocando
register_post_type
'init' con argumentos dados. Con esta abstracción, aún necesita probar esa clase, pero en otros lugares de su código que registran tipos de publicaciones, puede hacer uso de esa clase, burlándose de ella en las pruebas (suponiendo que funcione).Lo increíble es que, si escribe una clase que resuma el registro de CPT, puede crear un repositorio separado para él, y gracias a las herramientas modernas como Composer, incrustarlo en todos los proyectos donde lo necesite: probar una vez, usar en todas partes . Y si alguna vez encuentra un error en él, puede solucionarlo en un solo lugar y con un simple
composer update
todos los proyectos donde se utiliza también se solucionan.Por segunda vez: escribir código que se pueda probar de forma aislada significa escribir un código mejor.
Pero tarde o temprano necesito usar las funciones de WP en alguna parte ...
Por supuesto. Nunca debes actuar en paralelo al núcleo, no tiene sentido. Puede escribir clases que envuelvan las funciones de WP, pero esas clases también deben probarse. El método "manual" descrito anteriormente puede usarse para tareas muy simples, pero cuando una clase contiene muchas funciones de WP puede ser una molestia.
Afortunadamente, allí hay buenas personas que escriben cosas buenas. 10up , una de las mayores agencias de WP, mantiene una gran biblioteca para las personas que desean probar los complementos de la manera correcta. Es
WP_Mock
.Le permite burlarse de las funciones de WP y los ganchos . Suponiendo que haya cargado en sus pruebas (vea el archivo readme del repositorio), la misma prueba que escribí anteriormente se convierte en:
Simple, ¿no es así? Esta respuesta no es un tutorial para
WP_Mock
, así que lea el archivo readme del repositorio para obtener más información, pero el ejemplo anterior debería ser bastante claro, creo.Además, no necesita escribir ninguna burla
add_action
oregister_post_type
usted mismo, ni mantener ninguna variable global.¿Y las clases de WP?
WP también tiene algunas clases, y si WordPress no se carga cuando ejecuta pruebas, debe burlarse de ellas.
Eso es mucho más fácil que burlarse de funciones, PHPUnit tiene un sistema integrado para burlarse de objetos, pero aquí quiero sugerirle burla . Es una biblioteca muy poderosa y muy fácil de usar. Además, es una dependencia de
WP_Mock
, por lo que si lo tiene, también tiene burla.¿Pero que pasa
WP_UnitTestCase
?El conjunto de pruebas de WordPress se creó para probar el núcleo de WordPress , y si desea contribuir al núcleo es fundamental, pero usarlo para complementos solo hace que la prueba no sea aislada.
Eche un vistazo al mundo de WP: hay muchos frameworks PHP modernos y CMS por ahí y ninguno de ellos sugiere probar plugins / módulos / extensiones (o como se llamen) usando el código de marco.
Si echa de menos las fábricas, una característica útil de la suite, debe saber que hay cosas increíbles allí.
Gotchas y desventajas
Hay un caso en el que falta el flujo de trabajo que sugerí aquí: pruebas de bases de datos personalizadas .
De hecho, si utiliza tablas de WordPress y funciones estándar para escribir allí (al nivel más bajo
$wpdb
métodos) que no será necesario en realidad datos de escritura o de prueba si los datos es en realidad la base de datos, sólo asegúrese de que los métodos adecuados se llaman con argumentos adecuados.Sin embargo, puede escribir complementos con tablas y funciones personalizadas que crean consultas para escribir allí, y probar si esas consultas funcionan es su responsabilidad.
En esos casos, el conjunto de pruebas de WordPress puede ayudarlo mucho, y puede ser necesario cargar WordPress en algunos casos para ejecutar funciones como
dbDelta
.(No hay necesidad de decir que use una base de datos diferente para las pruebas, ¿no es así?)
Afortunadamente, PHPUnit le permite organizar sus pruebas en "suites" que se pueden ejecutar por separado, por lo que puede escribir una suite para pruebas de bases de datos personalizadas donde cargue el entorno de WordPress (o parte de él) dejando todo el resto de sus pruebas sin WordPress .
Solo asegúrese de escribir clases que resuman tantas operaciones de base de datos como sea posible, de manera que todas las demás clases de complementos las utilicen, de modo que utilizando simulacros pueda probar adecuadamente la mayoría de las clases sin tener que lidiar con la base de datos.
Por tercera vez, escribir código fácilmente comprobable de forma aislada significa escribir un código mejor.
fuente