Classi di aiuto

DomQuery

Tester\DomQuery è una classe che estende SimpleXMLElement con una facile ricerca in HTML o XML tramite selettori CSS.

# creazione di DomQuery da una stringa HTML
$dom = Tester\DomQuery::fromHtml('
	<article class="post">
		<h1>Titolo</h1>
		<div class="content">Testo</div>
	</article>
');

# test dell'esistenza di elementi tramite selettori CSS
Assert::true($dom->has('article.post'));
Assert::true($dom->has('h1'));

# ricerca di elementi come array di oggetti DomQuery
$headings = $dom->find('h1');
Assert::same('Titolo', (string) $headings[0]);

# test se l'elemento corrisponde al selettore (dalla versione 2.5.3)
$content = $dom->find('.content')[0];
Assert::true($content->matches('div'));
Assert::false($content->matches('p'));

# ricerca del predecessore più vicino corrispondente al selettore (da 2.5.5)
$article = $content->closest('.post');
Assert::true($article->matches('article'));

FileMock

Tester\FileMock emula file in memoria e facilita così il test del codice che utilizza funzioni come fopen(), file_get_contents(), parse_ini_file() e simili. Esempio di utilizzo:

# Classe testata
class Logger
{
	public function __construct(
		private string $logFile,
	) {
	}

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

# Nuovo file vuoto
$file = Tester\FileMock::create('');

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

# Testiamo il contenuto creato
Assert::same("Login\nLogout\n", file_get_contents($file));

Assert::with()

Non è un'asserzione, ma un aiutante per testare metodi e proprietà private degli oggetti.

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

$ent = new Entity;

Assert::with($ent, function () {
	Assert::true($this->enabled); // resa accessibile la privata $ent->enabled
});

Helpers::purge()

Il metodo purge() crea la directory specificata e, se esiste già, cancella l'intero suo contenuto. È utile per creare una directory temporanea. Ad esempio in tests/bootstrap.php:

@mkdir(__DIR__ . '/tmp');  // @ - la directory potrebbe già esistere

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

Environment::lock()

I test vengono eseguiti in parallelo. A volte, però, abbiamo bisogno che l'esecuzione dei test non si sovrapponga. Tipicamente nei test di database è necessario che un test prepari il contenuto del database e che un altro test non acceda al database durante la sua esecuzione. In questi test usiamo Tester\Environment::lock($name, $dir):

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

Il primo parametro è il nome del lock, il secondo è il percorso della directory per salvare il lock. Il test che ottiene il lock per primo viene eseguito, gli altri test devono attendere il suo completamento.

Environment::bypassFinals()

Classi o metodi contrassegnati come final sono difficili da testare. La chiamata Tester\Environment::bypassFinals() all'inizio del test fa sì che le parole chiave final vengano omesse durante il caricamento del codice.

require __DIR__ . '/bootstrap.php';

Tester\Environment::bypassFinals();

class MyClass extends NormallyFinalClass  // <-- NormallyFinalClass non è più final
{
	// ...
}

Environment::setup()

  • migliora la leggibilità dell'output degli errori (inclusa la colorazione), altrimenti viene visualizzato lo stack trace PHP predefinito
  • abilita il controllo che siano state chiamate asserzioni nel test, altrimenti un test senza asserzioni (ad esempio dimenticate) passa ugualmente
  • quando si usa --coverage avvia automaticamente la raccolta di informazioni sul codice eseguito (descritto più avanti)
  • visualizza lo stato OK o FAILURE alla fine dello script

Environment::setupFunctions()

Crea le funzioni globali test(), testException(), setUp() e tearDown(), in cui è possibile strutturare i test.

test('descrizione del test', function () {
	Assert::same(123, foo());
	Assert::false(bar());
	// ...
});

Environment::VariableRunner

Consente di determinare se il test è stato eseguito direttamente o tramite Tester.

if (getenv(Tester\Environment::VariableRunner)) {
	// eseguito da Tester
} else {
	// eseguito diversamente
}

Environment::VariableThread

Tester esegue i test in parallelo nel numero specificato di thread. Se siamo interessati al numero del thread, lo otteniamo dalla variabile d'ambiente:

echo "Sto eseguendo nel thread numero " . getenv(Tester\Environment::VariableThread);