TestCase

У простих тестах assertion можуть слідувати одна за одною. Іноді, однак, вигідніше запакувати assertion у тестовий клас і таким чином їх структурувати.

Клас має бути нащадком Tester\TestCase, і спрощено ми говоримо про нього як про testcase. Клас повинен містити тестові методи, що починаються на test. Ці методи будуть запущені як тести:

use Tester\Assert;

class RectangleTest extends Tester\TestCase
{
	public function testOne()
	{
		Assert::same(/* ... */);
	}

	public function testTwo()
	{
		Assert::match(/* ... */);
	}
}

# Запуск тестових методів
(new RectangleTest)->run();

Так написаний тест можна далі доповнити методами setUp() та tearDown(). Вони викликаються перед, відповідно, після кожного тестового методу:

use Tester\Assert;

class NextTest extends Tester\TestCase
{
	public function setUp()
	{
		# Підготовка
	}

	public function tearDown()
	{
		# Прибирання
	}

	public function testOne()
	{
		Assert::same(/* ... */);
	}

	public function testTwo()
	{
		Assert::match(/* ... */);
	}
}

# Запуск тестових методів
(new NextTest)->run();

/*


Порядок виклику методів
-----------------------
setUp()
testOne()
tearDown()

setUp()
testTwo()
tearDown()
*/

Якщо виникає помилка на етапі setUp() або tearDown(), тест загалом зазнає невдачі. Якщо виникає помилка в тестовому методі, незважаючи на це, метод tearDown() запуститься, однак з придушенням помилок у ньому.

Рекомендуємо на початок тесту написати анотацію @testCase, тоді запускач тестів з командного рядка запускатиме окремі методи testcase в самостійних процесах і паралельно в кількох потоках. Це може значно прискорити весь процес тестування.

<?php
/** @testCase */

Анотації методів

Для тестових методів у нас є кілька анотацій, які полегшать нам тестування. Записуємо їх до тестового методу.

@throws

Є еквівалентом використання Assert::exception() всередині тестового методу. Запис, однак, зрозуміліший:

/**
 * @throws RuntimeException
 */
public function testOne()
{
	// ...
}


/**
 * @throws LogicException  Wrong argument order
 */
public function testTwo()
{
	// ...
}

@dataProvider

Якщо ми хочемо запустити тестовий метод кілька разів, але з різними параметрами, ця анотація буде корисною. (Не плутайте з однойменною анотацією для файлів.)

За нею вкажемо назву методу, який повертає аргументи для тестового методу. Метод повинен повернути масив або Traversable. Простий приклад:

public function getLoopArgs()
{
	return [
		[1, 2, 3],
		[4, 5, 6],
		[7, 8, 9],
	];
}


/**
 * @dataProvider getLoopArgs
 */
public function testLoop($a, $b, $c)
{
	// ...
}

Другий варіант анотації @dataProvider приймає як параметр шлях до INI-файлу (відносно файлу з тестом). Метод викликається стільки разів, скільки секцій у INI-файлі. Файл loop-args.ini:

[one]
a=1
b=2
c=3

[two]
a=4
b=5
c=6

[three]
a=7
b=8
c=9

і метод, який використовує INI-файл:

/**
 * @dataProvider loop-args.ini
 */
public function testLoop($a, $b, $c)
{
	// ...
}

Аналогічно, замість INI-файлу ми можемо посилатися на PHP-скрипт. Він повинен повернути масив або Traversable. Файл loop-args.php:

return [
	['a' => 1, 'b' => 2, 'c' => 3],
	['a' => 4, 'b' => 5, 'c' => 6],
	['a' => 7, 'b' => 8, 'c' => 9],
];