TestCase

У простих тестах твердження можуть слідувати одне за одним. Але іноді корисно укласти твердження в тестовий клас і структурувати їх таким чином.

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

use Tester\Assert;

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

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

# Run testing methods
(new RectangleTest)->run();

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

use Tester\Assert;

class NextTest extends Tester\TestCase
{
	public function setUp()
	{
		# Preparation
	}

	public function tearDown()
	{
		# Clean-up
	}

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

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

# Run testing methods
(new NextTest)->run();

/*


Method Calls Order
------------------
setUp()
testOne()
tearDown()

setUp()
testTwo()
tearDown()
*/

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

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

<?php
/** @testCase */

Анотування методів

Існує кілька анотацій, які допоможуть нам у тестуванні методів. Ми пишемо їх у напрямку методу тестування.

@throws

Це таке саме використання Assert::exception() всередині методу тестування. Але позначення більш читабельне:

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


/**
 * @throws LogicException Неправильний порядок аргументів
 */
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)
{
	// ...
}

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

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