- 1. Introducción e instalación
- 2. Tests de aceptación con PhpBrowser
- 3. Tests de aceptación con WebDriver y PhantomJS
- 4. Tests de aceptación con WebDriver y Selenium
- 5. WPBrowser
- 6. Tests unitarios
Hasta ahora, en las entradas anteriores habíamos visto qué son los tests de aceptación y cómo hacerlos con codeception. Este último post lo voy a dedicar a Tests unitarios.
Los tests unitarios consisten en probar una pequeña parte de código de manera aislada, y comprobar que su funcionamiento es correcto. Su objetivo es probar una y solo una cosa por cada test, de aquí la gran importancia de aplicar principios SOLID para que tu código sea fácilmente testeable.
Si tenemos métodos con muchas líneas de código, será muy difícil si no imposible testearlos. Con métodos pequeños y con responsabilidad única, será mucho más fácil realizar tests unitarios.
El objetivo de estos tests es comprobar pequeñas partes de código de manera independiente. Poniendo un simil muy sencillo, si tuvieras que testear el sistema de suspensión de un coche, tendrías que realizar tests unitarios de la rueda por un lado y el amortiguador por otro, nunca de manera conjunta.
Codeception utiliza PHPUnit para ejecutar los tests unitarios. El procedimiento para generar una batería de tests es muy similar a lo que vimos en el caso de los tests de aceptación en entradas anteriores.
Para crear un test usaremos el comando generate:test del siguiente modo:
codecept generate:test unit Example
Donde:
- codecept es php vendor/bin/codecept
- generate:test es el comando para generar codeception tests (también puedes utilizar g:test)
- unit es la suite sobre la que vamos a generar los tests
- Example es la clase que nos va a generar (a la que añadirá el sujifo Test)
Podrás observar que ha creado dentro de la carpeta codeception/tests/unit/ una clase llamada ExampleTest.php, con el siguiente contenido:
<?php
class ExampleTest extends \Codeception\Test\Unit {
/**
* @var \UnitTester
*/
protected $tester;
protected function _before() {
}
protected function _after() {
}
// tests
public function testSomeFeature() {
}
}
En esta clase:
- Todos los métodos públicos con el prefijo test son tests, que se ejecutarán de manera estanca
- El método _before se ejecuta antes de cada test (equivalente al setUp en PHPUnit)
- El método _after se ejecuta después de cada test (equivalente al tearDown en PHPUnit)
Para lanzarlos, podremos hacerlo en lote:
codecept run unit
O de manera independiente, si queremos lanzar sólo una clase:
codecept run unit ExampleTest
Aserciones y ejemplos
Las aserciones son declaraciones que te permiten probar suposiciones sobre tu desarrollo. Es decir, que si tienes un método que suma dos números, la aserción comprobará que si $a = 2 y $b = 3 da como resultado esperado 5.
Hay muchos tipos de aserciones, entre las más destacadas se encuentran:
- $this->assertEquals() Comprueba que lo que devuelve un método es igual a lo que indiquemos como valor esperado
- $this->assertContains() Comprueba que lo que devuelve un método contiene una parte de lo que indicamos como valor esperado
- $this->assertFalse() Comprueba que una condición no se cumple
- $this->assertTrue() Comprueba que una condición se cumple
Hay muchas más aserciones, los test unitarios en Codeception están basados en PHPUnit, por lo que puedes encontrar más información en la documentación oficial.
Para entenderlo mejor con un ejemplo, vamos a imaginar que tenemos una clase Math, que tiene 3 métodos: add, subtract, multiply:
<?php
class Math {
public function add( $a, $b ) {
return $a + $b;
}
public function subtract( $a, $b ) {
return $a - $b;
}
public function multiply( $a, $b ) {
return $a * $b;
}
}
Y a continuación, en el test que hemos creado antes (ExampleTest) vamos a generar tests unitarios sobre estos métodos:
<?php
use Myplugin\Math;
class ExampleTest extends \Codeception\Test\Unit {
/**
* @var \UnitTester
*/
protected $tester;
protected $math;
protected function _before() {
$this->math = new Math();
}
protected function _after() {
}
// tests
public function testAdd() {
$this->assertEquals( 5, $this->math->add( 2, 3 ) );
}
public function testSubtract() {
$this->assertEquals( 2, $this->math->subtract( 8, 6 ) );
}
public function testMultiply() {
$this->assertTrue( 12 === $this->math->multiply( 4, 3 ) );
}
}
Como se puede observar:
- Incluimos (Use) la clase Math que es la que queremos testear
- Creamos una propiedad $math, donde instanciaremos nuestra clase
- Instanciamos nuestra clase Math en el método _before, que como vimos anteriormente, se ejecuta antes de cada test
- En el primer test comprobamos el método de suma, y utilizamos la aserción assertEquals, donde como primer parámetro establecemos el valor esperado (5), y en el segundo hacemos uso del método add de la clase Math, pasándole como párametros los valores 2 y 3
- En el segundo test comprobamos el método de resta. Utilizamos la misma aserción que antes, en esta ocasión comprobamos que esperamos un 2, si al método subtract le pasamos los valores 8 y 6
- En el tercer test comprobamos el método de multiplicación. En esta ocasión vamos a utilizar la aserción assertTrue, que simplemente comprueba que la condición sea verdadera. Para este ejemplo, nuestra condición es que si al método multiply le pasamos los valores 4 y 3, esperamos que sea igual a 12
Si lanzamos los tests, obtendremos una salida como esta:
Dentro de un método de los que hemos visto podemos tener varias aserciones sin problema, es decir, que 2+2 es 4, que 4+3 es 7, que 5+4 es 9… y la aproximación puede hacerse de diferentes formas: comprobar contra un valor esperado, que una condición es verdadera, que una condición es falsa, etc…
Este ejemplo es muy básico, pero creo que sirve para que se entiendan bien los tests unitarios. Y dando un paso más, sirve también para entender su importancia: Imaginad que el día de mañana os veis en la situación de refactorizar la clase Math, o añadir alguna cosa que os hayan pedido… después de la refactorización los tests deberían seguir funcionando igual, lo que te asegura que ante cambios en el código, no se ha roto nada y todo sigue funcionando como se espera.
Hasta aquí la serie de entradas sobre Codeception para WordPress. Espero que te hayan gustado y que comiences a introducir en el ciclo de vida del desarrollo los tests como parte fundamental del mismo.