📜 ⬆️ ⬇️

PHPUnit. Part 03 Writing Tests for PHPUnit

Translator's Preface
This article continues the series of translations of the official PHPUnit documentation into Russian.
Part 1 , Part 2

Example 4.1 demonstrates how PHPUnit can be used to test operations with PHP arrays. This example shows the basic conventions and steps inherent in PHPUnit tests:
Example 4.1: Testing PHP array operations using PHPUnit
<?php<br>
require_once 'PHPUnit/Framework.php' ;<br>
<br>
class StackTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testPushAndPop()<br>
{<br>
$stack = array();<br>
$ this ->assertEquals(0, count($stack));<br>
<br> array_push($stack, 'foo' );<br>
$ this ->assertEquals( 'foo' , $stack[count($stack)-1]);<br>
$ this ->assertEquals(1, count($stack));<br>
<br> $ this ->assertEquals( 'foo' , array_pop($stack));<br>
$ this ->assertEquals(0, count($stack));<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .


“Write the test regardless of whether you want to print the value through the print function or
debug expression. " Martin Fowler

Test dependencies


“Unit tests are usually written to help the developer find and correct errors, perform code refactoring, and facilitate the documentation of modules.
To achieve these goals, tests ideally should cover all possible paths in the program.
Usually one test covers one specific path in a single function or method.
However, the test method may not necessarily be an encapsulated, independent entity.
Often there are no obvious dependencies between tests that are hidden in the implementation of test scenarios. ”
Adrian Kuhn et. al.
PHPUnit supports declaring explicit dependencies between tests.
Such dependencies do not determine in what sequence tests should be performed,
however, they allow you to return an instance of the test environment (fixture) and transfer it to another test; the source (producer) transmits to the receiver (consumer).
Example 4.2 shows how to use the @depends annotation to describe dependencies between tests.

Example 4.2: Using @depends annotation to describe dependencies
<?php<br>
class StackTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testEmpty()<br>
{<br>
$stack = array();<br>
$ this ->assertTrue(empty($stack));<br>
<br>
return $stack;<br>
}<br>
<br>
/** <br>
* @depends testEmpty <br>
*/ <br>
public function testPush(array $stack)<br>
{<br>
array_push($stack, 'foo' );<br>
$ this ->assertEquals( 'foo' , $stack[count($stack)-1]);<br>
$ this ->assertFalse(empty($stack));<br>
<br>
return $stack;<br>
}<br>
<br>
/** <br>
* @depends testPush <br>
*/ <br>
public function testPop(array $stack)<br>
{<br>
$ this ->assertEquals( 'foo' , array_pop($stack));<br>
$ this ->assertTrue(empty($stack));<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .

In this example, the first test, testEmpty() , creates an empty array and sets the statement that the array is empty. After this, the test returns the fixture environment as a result.
The second test, testPush() , depends on testEmpty() and receives the result of the testEmpty() operation as an argument. Finally, testPop() depends on testPush() .
We want our attention to be focused on important reports of test failures, this will allow finding defects as quickly as possible.
For this reason, PHPUnit skips the execution of dependent tests if the Source (main test) has ended with an error. Improved defect detection is achieved by using dependencies between tests, as shown in Example 4.3.
')
Example 4.3: Using dependencies between tests
<?php<br>
class DependencyFailureTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testOne()<br>
{<br>
$ this ->assertTrue(FALSE);<br>
}<br>
<br>
/** <br>
* @depends testOne <br> */ <br>
public function testTwo()<br> {<br>
}<br>}<br>?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .
 phpunit --verbose DependencyFailureTest
 PHPUnit 3.4.2 by Sebastian Bergmann.

 DependencyFailureTest
 FS

 Time: 0 seconds

 There was 1 failure:

 1) testOne (DependencyFailureTest)
 Failed asserting that <boolean: false> is true.
 /home/sb/DependencyFailureTest.php:6

 There was 1 skipped test:

 1) testTwo (DependencyFailureTest)
 This test depends on "DependencyFailureTest :: testOne" to pass.

 FAILURES!
 Tests: 2, Assertions: 1, Failures: 1, Skipped: 1.

A test may have several @depends annotations.
PHPUnit does not change the sequence in which tests are run,
You must be sure that the dependencies are completed before the test runs.

Data Sources (Data Providers)


The test method can work with arbitrary arguments.
Arguments are passed using the data source method ( provider() , see Example 4.4).
The data source method must be defined using the @dataProvider annotation.
The data source method must be public and must return an array of arrays or an object that supports the Iterator interface, which returns an array at each iteration.
For each array that is part of the collection, a test method will be called. As an argument, an array of values ​​will be passed to the method.

Example 4.4: Using a data source
<?php<br>
class DataTest extends PHPUnit_Framework_TestCase<br>
{<br>
/** <br>
* @dataProvider provider <br>
*/ <br>
public function testAdd($a, $b, $c)<br>
{<br>
$ this ->assertEquals($c, $a + $b);<br>
}<br>
<br>
public function provider()<br>
{<br>
return array(<br>
array(0, 0, 0),<br>
array(0, 1, 1),<br>
array(1, 0, 1),<br>
array(1, 1, 3)<br>
);<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .

 phpunit DataTest
 PHPUnit 3.4.2 by Sebastian Bergmann.

 ... f

 Time: 0 seconds

 There was 1 failure:

 1) testAdd (DataTest) with data (1, 1, 3)
 Failed asserting that <integer: 2> matches expected value <integer: 3>.
 /home/sb/DataTest.php:21

 FAILURES!
 Tests: 4, Assertions: 4, Failures: 1.

Note


If the test method is simultaneously passed parameters from a data source ( @dataProvider ) and one or several tests that are defined as dependent ( @depends ), then the data source is used first and only then other tests.

Exception Testing


Example 4.5 demonstrates how to use @expectedException annotation for testing.
exceptions that are thrown inside the test code.

Example 4.5: Using @expectedException annotation
<?php<br>
require_once 'PHPUnit/Framework.php' ;<br>
<br>
class ExceptionTest extends PHPUnit_Framework_TestCase<br>
{<br>
/** <br>
* @expectedException InvalidArgumentException <br>
*/ <br>
public function testException()<br>
{<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .

 phpunit ExceptionTest
 PHPUnit 3.4.2 by Sebastian Bergmann.

 F

 Time: 0 seconds

 There was 1 failure:

 1) testException (ExceptionTest)
 Expected exception InvalidArgumentException

 FAILURES!
 Tests: 1, Assertions: 1, Failures: 1.

The setExpectedException() method is another way to indicate that an exception is thrown in the test method, see Example 4.6.

Example 4.6: Test method expected to throw an exception
<?php<br>
require_once 'PHPUnit/Framework.php' ;<br>
<br>
class ExceptionTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testException()<br>
{<br>
$ this ->setExpectedException( 'InvalidArgumentException' );<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .

 phpunit ExceptionTest
 PHPUnit 3.4.2 by Sebastian Bergmann.

 F

 Time: 0 seconds

 There was 1 failure:

 1) testException (ExceptionTest)
 Expected exception InvalidArgumentException

 FAILURES!
 Tests: 1, Assertions: 1, Failures: 1.

Table 4.1 provides methods for testing exceptions.

Table 4.1 (text version). Methods for testing exceptions
void setExpectedException(string $exceptionName)
- Setting the name of the expected exception - $exceptionName .
String getExpectedException()
- Getting the name of the expected exception.

To test exceptions, you can use the approach shown in Example 4.7.

Example 4.7: An alternative approach to testing exceptions
<?php<br>
require_once 'PHPUnit/Framework.php' ;<br>
<br>
class ExceptionTest extends PHPUnit_Framework_TestCase {<br>
public function testException() {<br>
try {<br>
// ... Code that is expected to raise an exception ... <br>
}<br>
<br>
catch (InvalidArgumentException $expected) {<br>
return ;<br>
}<br>
<br>
$ this ->fail( 'An expected exception has not been raised.' );<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .



The code shown in Example 4.7 is expected to throw an exception. If this does not happen, the fail() method will be called, (see
(see Table 22.2 ), which will interrupt the test and signal an error.
If an exception is generated, the catch block will work and the test will end successfully.

PHP error testing


By default, PHP errors, warnings, and notifications that appear during testing are converted to exceptions by PHPUnit. Using this feature, you can, for example, set up a mechanism to wait for a similar exception to appear in the test, see Example 4.8.

Example 4.8: Using @expectedException to wait for a PHP error
<?php<br>
class ExpectedErrorTest extends PHPUnit_Framework_TestCase<br>
{<br>
/** <br>
* @expectedException PHPUnit_Framework_Error <br>
*/ <br>
public function testFailingInclude()<br>
{<br>
include 'not_existing_file.php' ;<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .

 phpunit ExpectedErrorTest
 PHPUnit 3.4.2 by Sebastian Bergmann.

 .

 Time: 0 seconds

 OK (1 test, 1 assertion)

PHPUnit_Framework_Error_Notice and PHPUnit_Framework_Error_Warning
represent PHP notifications and warnings.


Continued:
Part 4

Source: https://habr.com/ru/post/89175/


All Articles