Nette Documentation Preview

syntax
TestCase
********

.[perex]
In einfachen Tests können Assertions aufeinander folgen. Manchmal ist es jedoch vorteilhafter, Assertions in einer Testklasse zu verpacken und sie so zu strukturieren.

Die Klasse muss von `Tester\TestCase` erben und wird vereinfacht als **testcase** bezeichnet. Die Klasse muss Testmethoden enthalten, die mit `test` beginnen. Diese Methoden werden als Tests ausgeführt:

```php
use Tester\Assert;

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

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

# Ausführung der Testmethoden
(new RectangleTest)->run();
```

Ein so geschriebener Test kann weiter um Methoden `setUp()` und `tearDown()` erweitert werden. Sie werden vor bzw. nach jeder Testmethode aufgerufen:

```php
use Tester\Assert;

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

	public function tearDown()
	{
		# Aufräumen
	}

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

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

# Ausführung der Testmethoden
(new NextTest)->run();

/*


Reihenfolge der Methodenaufrufe
-------------------------------
setUp()
testOne()
tearDown()

setUp()
testTwo()
tearDown()
*/
```

Wenn in der `setUp()`- oder `tearDown()`-Phase ein Fehler auftritt, schlägt der Test insgesamt fehl. Wenn in der Testmethode ein Fehler auftritt, wird die Methode `tearDown()` dennoch ausgeführt, jedoch mit unterdrückten Fehlern darin.

Wir empfehlen, am Anfang des Tests die Annotation [@testCase |test-annotations#testCase] zu schreiben. Dann führt der Kommandozeilen-Teststarter die einzelnen Methoden des Testcases in separaten Prozessen und parallel in mehreren Threads aus. Dies kann den gesamten Testprozess erheblich beschleunigen.

/--php
<?php
/** @testCase */
\--


Annotationen von Methoden
=========================

Für Testmethoden stehen uns mehrere Annotationen zur Verfügung, die uns das Testen erleichtern. Wir schreiben sie zur Testmethode.


@throws .[filter]
-----------------
Ist äquivalent zur Verwendung von `Assert::exception()` innerhalb der Testmethode. Die Schreibweise ist jedoch übersichtlicher:

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


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


@dataProvider .[filter]
-----------------------
Wenn wir eine Testmethode mehrfach, aber mit unterschiedlichen Parametern ausführen möchten, ist diese Annotation nützlich. (Nicht zu verwechseln mit der gleichnamigen Annotation für [Dateien |test-annotations#dataProvider].)

Dahinter geben wir den Namen der Methode an, die die Argumente für die Testmethode zurückgibt. Die Methode muss ein Array oder Traversable zurückgeben. Ein einfaches Beispiel:

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


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

Die zweite Variante der Annotation **@dataProvider** akzeptiert als Parameter den Pfad zu einer INI-Datei (relativ zur Testdatei). Die Methode wird so oft aufgerufen, wie es Abschnitte in der INI-Datei gibt. Datei `loop-args.ini`:

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

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

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

und die Methode, die die INI-Datei verwendet:

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

Ähnlich können wir anstelle einer INI-Datei auf ein PHP-Skript verweisen. Dieses muss ein Array oder Traversable zurückgeben. Datei `loop-args.php`:

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

TestCase

In einfachen Tests können Assertions aufeinander folgen. Manchmal ist es jedoch vorteilhafter, Assertions in einer Testklasse zu verpacken und sie so zu strukturieren.

Die Klasse muss von Tester\TestCase erben und wird vereinfacht als testcase bezeichnet. Die Klasse muss Testmethoden enthalten, die mit test beginnen. Diese Methoden werden als Tests ausgeführt:

use Tester\Assert;

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

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

# Ausführung der Testmethoden
(new RectangleTest)->run();

Ein so geschriebener Test kann weiter um Methoden setUp() und tearDown() erweitert werden. Sie werden vor bzw. nach jeder Testmethode aufgerufen:

use Tester\Assert;

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

	public function tearDown()
	{
		# Aufräumen
	}

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

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

# Ausführung der Testmethoden
(new NextTest)->run();

/*


Reihenfolge der Methodenaufrufe
-------------------------------
setUp()
testOne()
tearDown()

setUp()
testTwo()
tearDown()
*/

Wenn in der setUp()- oder tearDown()-Phase ein Fehler auftritt, schlägt der Test insgesamt fehl. Wenn in der Testmethode ein Fehler auftritt, wird die Methode tearDown() dennoch ausgeführt, jedoch mit unterdrückten Fehlern darin.

Wir empfehlen, am Anfang des Tests die Annotation @testCase zu schreiben. Dann führt der Kommandozeilen-Teststarter die einzelnen Methoden des Testcases in separaten Prozessen und parallel in mehreren Threads aus. Dies kann den gesamten Testprozess erheblich beschleunigen.

<?php
/** @testCase */

Annotationen von Methoden

Für Testmethoden stehen uns mehrere Annotationen zur Verfügung, die uns das Testen erleichtern. Wir schreiben sie zur Testmethode.

@throws

Ist äquivalent zur Verwendung von Assert::exception() innerhalb der Testmethode. Die Schreibweise ist jedoch übersichtlicher:

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


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

@dataProvider

Wenn wir eine Testmethode mehrfach, aber mit unterschiedlichen Parametern ausführen möchten, ist diese Annotation nützlich. (Nicht zu verwechseln mit der gleichnamigen Annotation für Dateien.)

Dahinter geben wir den Namen der Methode an, die die Argumente für die Testmethode zurückgibt. Die Methode muss ein Array oder Traversable zurückgeben. Ein einfaches Beispiel:

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


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

Die zweite Variante der Annotation @dataProvider akzeptiert als Parameter den Pfad zu einer INI-Datei (relativ zur Testdatei). Die Methode wird so oft aufgerufen, wie es Abschnitte in der INI-Datei gibt. Datei loop-args.ini:

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

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

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

und die Methode, die die INI-Datei verwendet:

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

Ähnlich können wir anstelle einer INI-Datei auf ein PHP-Skript verweisen. Dieses muss ein Array oder Traversable zurückgeben. Datei loop-args.php:

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