Clases auxiliares

DomQuery

Tester\DomQuery es una clase que extiende SimpleXMLElement con una fácil búsqueda en HTML o XML mediante selectores CSS.

# creación de DomQuery a partir de una cadena HTML
$dom = Tester\DomQuery::fromHtml('
	<article class="post">
		<h1>Title</h1>
		<div class="content">Text</div>
	</article>
');

# prueba de existencia de elementos mediante selectores CSS
Assert::true($dom->has('article.post'));
Assert::true($dom->has('h1'));

# encontrar elementos como un array de objetos DomQuery
$headings = $dom->find('h1');
Assert::same('Title', (string) $headings[0]);

# prueba si un elemento coincide con un selector (desde la versión 2.5.3)
$content = $dom->find('.content')[0];
Assert::true($content->matches('div'));
Assert::false($content->matches('p'));

# encontrar el ancestro más cercano que coincida con el selector (desde 2.5.5)
$article = $content->closest('.post');
Assert::true($article->matches('article'));

FileMock

Tester\FileMock emula archivos en memoria y facilita así la prueba de código que utiliza funciones como fopen(), file_get_contents(), parse_ini_file() y similares. Ejemplo de uso:

# Clase probada
class Logger
{
	public function __construct(
		private string $logFile,
	) {
	}

	public function log(string $message): void
	{
		file_put_contents($this->logFile, $message . "\n", FILE_APPEND);
	}
}

# Nuevo archivo vacío
$file = Tester\FileMock::create('');

$logger = new Logger($file);
$logger->log('Login');
$logger->log('Logout');

# Probamos el contenido creado
Assert::same("Login\nLogout\n", file_get_contents($file));

Assert::with()

No es una aserción, sino un ayudante para probar métodos y propiedades privadas de objetos.

class Entity
{
	private $enabled;
	// ...
}

$ent = new Entity;

Assert::with($ent, function () {
	Assert::true($this->enabled); // $ent->enabled privada accesible
});

Helpers::purge()

El método purge() crea el directorio especificado y, si ya existe, elimina todo su contenido. Es útil para crear un directorio temporal. Por ejemplo, en tests/bootstrap.php:

@mkdir(__DIR__ . '/tmp');  # @ - el directorio ya puede existir

define('TempDir', __DIR__ . '/tmp/' . getmypid());
Tester\Helpers::purge(TempDir);

Environment::lock()

Las pruebas se ejecutan en paralelo. Sin embargo, a veces necesitamos que la ejecución de las pruebas no se superponga. Típicamente, en las pruebas de base de datos es necesario que una prueba prepare el contenido de la base de datos y que otra prueba no acceda a la base de datos durante su ejecución. En estas pruebas usamos Tester\Environment::lock($name, $dir):

Tester\Environment::lock('database', __DIR__ . '/tmp');

El primer parámetro es el nombre del bloqueo, el segundo es la ruta al directorio para guardar el bloqueo. La prueba que obtiene el bloqueo primero se ejecuta, las demás pruebas deben esperar a que termine.

Environment::bypassFinals()

Las clases o métodos marcados como final son difíciles de probar. La llamada a Tester\Environment::bypassFinals() al principio de la prueba hace que las palabras clave final se omitan durante la carga del código.

require __DIR__ . '/bootstrap.php';

Tester\Environment::bypassFinals();

class MyClass extends NormallyFinalClass  # <-- NormallyFinalClass ya no es final
{
	// ...
}

Environment::setup()

  • mejora la legibilidad de la salida de errores (incluida la coloración), de lo contrario se muestra el stack trace predeterminado de PHP
  • activa la comprobación de que se llamaron aserciones en la prueba, de lo contrario, una prueba sin aserciones (por ejemplo, olvidadas) también pasará
  • al usar --coverage, inicia automáticamente la recopilación de información sobre el código ejecutado (descrito más adelante)
  • imprime el estado OK o FAILURE al final del script

Environment::setupFunctions()

Crea las funciones globales test(), testException(), setUp() y tearDown(), en las que puedes estructurar las pruebas.

test('descripción de la prueba', function () {
	Assert::same(123, foo());
	Assert::false(bar());
	// ...
});

Environment::VariableRunner

Permite averiguar si la prueba se ejecutó directamente o mediante Tester.

if (getenv(Tester\Environment::VariableRunner)) {
	# ejecutado por Tester
} else {
	# ejecutado de otra manera
}

Environment::VariableThread

Tester ejecuta las pruebas en paralelo en el número especificado de hilos. Si nos interesa el número del hilo, lo averiguamos a partir de la variable de entorno:

echo "Ejecutando en el hilo número " . getenv(Tester\Environment::VariableThread);