Unlock The Mystery
of PHPUnit
Brian Johnson
What is a unit test?
In computer programming, unit testing is a software testing method by
which individual units of source code, sets of one or more computer program
modules together with associated control data, usage procedures, and
operating procedures, are tested to determine whether they are fit for use.
https://en.wikipedia.org/wiki/Unit_testing
What is PHPUnit?
PHPUnit is a programmer-oriented testing framework for PHP.
It is an instance of the xUnit architecture for unit testing frameworks.
https://phpunit.de/
Setup/Install
$ composer require --dev phpunit/phpunit
Using version ^7.3 for phpunit/phpunit
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 27 installs, 0 updates, 0 removals
- Installing sebastian/version (2.0.1): Loading from cache
- Installing sebastian/resource-operations (1.0.0): Loading
from cache
...
$ vendor/bin/phpunit
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
Usage: phpunit [options] UnitTest [UnitTest.php]
phpunit [options] <directory>
Alternative:
composer.json:
{
"require-dev": {
"phpunit/phpunit": "^7.3"
},
"scripts": {
"test": "phpunit test"
}
}
$ composer test
A Basic Test Example
Implement a Cheerleader
Cheerleader functions:
•gimmeAn - will accept a character as an argument; will
return same character, and append character to an
ever-growing string
•whatsThatSpell - will return the stored string built by
repeated calls to gimmeAn with an ! appended to the
end
•doTheSplits - will throw an exception
<?php
namespace WavePHPCheer;
use PHPUnitFrameworkTestCase;
class CheerleaderTest extends TestCase
{
}
CheerleaderTest.php:
> phpunit test
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
W 1 / 1 (100%)
Time: 20 ms, Memory: 4.00MB
There was 1 warning:
1) Warning
No tests found in class "WavePHPCheerCheerleaderTest".
WARNINGS!
Tests: 1, Assertions: 0, Warnings: 1.
Script phpunit test handling the test event returned with error code 1
$ composer test
public function testGimmeAnG()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('G'),
$this->equalTo('G'));
}
CheerleaderTest.php:
•gimmeAn - will accept a character as an argument; will
return same character, and append character to an ever-
growing string
/**
* @test
*/
public function gimmeAnO()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('O'),
$this->equalTo('O'));
}
CheerleaderTest.php:
/**
* @test
*/
public function testWhatsThatSpell()
{
$cheerleader = new Cheerleader();
$cheerleader->gimmeAn('G');
$cheerleader->gimmeAn('O');
$this->assertThat($cheerleader->whatsThatSpell(),
$this->equalTo('GO!'));
}
CheerleaderTest.php:
<?php
namespace WavePHPCheer;
use PHPUnitFrameworkTestCase;
class CheerleaderTest extends TestCase
{
public function testGimmeAnG()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('G'),
$this->equalTo('G'));
}
/**
* @test
*/
public function gimmeAnO()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('O'),
$this->equalTo('O'));
}
/**
* @test
*/
public function testWhatsThatSpell()
{
$cheerleader = new Cheerleader();
$cheerleader->gimmeAn('G');
$cheerleader->gimmeAn('O');
$this->assertThat($cheerleader->whatsThatSpell(),
$this->equalTo('GO!'));
}
}
$ composer test
> phpunit test
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
EEE 3 / 3 (100%)
Time: 18 ms, Memory: 4.00MB
There were 3 errors:
1) WavePHPCheerCheerleaderTest::testGimmeAnG
Error: Class 'WavePHPCheerCheerleader' not found
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:11
2) WavePHPCheerCheerleaderTest::gimmeAnO
Error: Class 'WavePHPCheerCheerleader' not found
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:21
3) WavePHPCheerCheerleaderTest::testWhatsThatSpell
Error: Class 'WavePHPCheerCheerleader' not found
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:31
ERRORS!
Tests: 3, Assertions: 0, Errors: 3.
Script phpunit test handling the test event returned with error code 2
<?php
namespace WavePHPCheer;
class Cheerleader
{
public function gimmeAn($letter)
{
}
}
Cheerleader.php:
$ composer test
> phpunit test
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
FFE 3 / 3 (100%)
Time: 19 ms, Memory: 4.00MB
There was 1 error:
1) WavePHPCheerCheerleaderTest::testWhatsThatSpell
Error: Call to undefined method WavePHPCheerCheerleader::whatsThatSpell()
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:34
--
There were 2 failures:
1) WavePHPCheerCheerleaderTest::testGimmeAnG
Failed asserting that null matches expected 'G'.
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:13
2) WavePHPCheerCheerleaderTest::gimmeAnO
Failed asserting that null matches expected 'O'.
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:23
ERRORS!
Tests: 3, Assertions: 2, Errors: 1, Failures: 2.
Script phpunit test handling the test event returned with error code 2
<?php
namespace WavePHPCheer;
class Cheerleader
{
private $word = '';
public function gimmeAn($letter)
{
$this->word .= $letter;
return $letter;
}
public function whatsThatSpell()
{
return $this->word . '!';
}
}
• gimmeAn - will accept a character
as an argument; will return same
character, and append character to
an ever-growing string
• whatsThatSpell - will return the
stored string built by repeated calls
to gimmeAn with an ! appended to
the end
$ composer test
> phpunit test
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
... 3 / 3 (100%)
Time: 19 ms, Memory: 4.00MB
OK (3 tests, 3 assertions)
<?php
namespace WavePHPCheer;
use PHPUnitFrameworkTestCase;
class CheerleaderTest extends TestCase
{
public function testGimmeAnG()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('G'),
$this->equalTo('G'));
}
/**
* @test
*/
public function gimmeAnO()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('O'),
$this->equalTo('O'));
}
/**
* @test
*/
public function testWhatsThatSpell()
{
$cheerleader = new Cheerleader();
$cheerleader->gimmeAn('G');
$cheerleader->gimmeAn('O');
$this->assertThat($cheerleader->whatsThatSpell(),
$this->equalTo('GO!'));
}
}
$ composer test
> phpunit test
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
... 3 / 3 (100%)
Time: 19 ms, Memory: 4.00MB
OK (3 tests, 3 assertions)
A Basic Test Example
Implement a Cheerleader
Cheerleader functions:
•gimmeAn - will accept a character as an argument; will
return same character, and append character to an
ever-growing string
•whatsThatSpell - will return the stored string built by
repeated calls to gimmeAn with an ! appended to the
end
•doTheSplits - will throw an exception
/**
* @expectedException WavePHPCheerLackOfFlexibilityException
*/
public function testTheSplits()
{
$cheerleader = new Cheerleader();
$cheerleader->doTheSplits();
}
CheerleaderTest.php:
<?php
namespace WavePHPCheer;
use Exception;
class LackOfFlexibilityException extends Exception { }
LackOfFlexibilityException.php:
public function doTheSplits()
{
throw new LackOfFlexibilityException("I can't do that!");
}
Cheerleader.php:
$ composer test -- --debug
> phpunit test '--debug'
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended
Test 'WavePHPCheerCheerleaderTest::testTheSplits' started
Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended
Time: 20 ms, Memory: 4.00MB
OK (4 tests, 4 assertions)
use InvalidArgumentException;
...
public function testGimmeAnInvalidArg()
{
$cheerleader = new Cheerleader();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
'WavePHPCheerCheerleader::gimmeAn may only '
. 'accept a single char arg');
$this->expectExceptionCode(619);
$cheerleader->gimmeAn("This is not a single character");
}
CheerleaderTest.php:
use InvalidArgumentException;
...
public function gimmeAn($letter)
{
if (!is_string($letter) || 1 != mb_strlen($letter)) {
throw new InvalidArgumentException(__METHOD__
. ' may only accept a single char arg', 619);
}
$this->word .= $letter;
return $letter;
}
Cheerleader.php:
$ composer test -- --debug
> phpunit test '--debug'
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended
Test 'WavePHPCheerCheerleaderTest::testTheSplits' started
Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended
Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' ended
Time: 21 ms, Memory: 4.00MB
OK (5 tests, 7 assertions)
MOCKS!
The practice of replacing an object with a test double
that verifies expectations, for instance asserting that a
method has been called, is referred to as mocking.
<?php
namespace WavePHPCheer;
class Pompom
{
public function shake()
{
// return true if shake successful
return true;
}
}
Pompom.php:
private $pompom;
...
public function __construct(Pompom $pompom = null)
{
if (empty($pompom)) {
$pompom = new Pompom();
}
$this->setPompom($pompom);
}
Cheerleader.php:
public function setPompom(Pompom $pompom)
{
$this->pompom = $pompom;
}
...
public function whatsThatSpell()
{
$this->pompom->shake();
return $this->word . '!';
}
Cheerleader.php:
getMockBuilder($type)
createMock($type)
How do I make a mock?
The createMock($type) method immediately returns a test double object for
the specified type (interface or class). The creation of this test double is
performed using best practice defaults. The __construct() and __clone()
methods of the original class are not executed) and the arguments passed to
a method of the test double will not be cloned. If these defaults are not what
you need then you can use the getMockBuilder($type) method to customize
the test double generation using a fluent interface.
public function testPomShake()
{
$mockPom = $this->createMock(Pompom::class);
$mockPom->expects($this->once())
->method('shake');
$cheerleader = new Cheerleader($mockPom);
$cheerleader->whatsThatSpell();
}
CheerleaderTest.php:
public function testPomShakeFail()
{
$mockPom = $this->createMock(Pompom::class);
$mockPom->expects($this->once())
->method('shake')
->willReturn(false);
$this->expectException(PomShakeFailException::class);
$cheerleader = new Cheerleader($mockPom);
$cheerleader->whatsThatSpell();
}
CheerleaderTest.php:
public function whatsThatSpell()
{
if (!$this->pompom->shake()) {
throw new PomShakeFailException();
}
return $this->word . '!';
}
Cheerleader.php:
$ composer test -- --debug
> phpunit test '--debug'
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended
Test 'WavePHPCheerCheerleaderTest::testTheSplits' started
Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended
Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' ended
Test 'WavePHPCheerCheerleaderTest::testPomShake' started
Test 'WavePHPCheerCheerleaderTest::testPomShake' ended
Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' started
Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' ended
Time: 23 ms, Memory: 4.00MB
There was 1 error:
1) WavePHPCheerCheerleaderTest::testPomShake
WavePHPCheerPomShakeFailException:
/Volumes/git/wavephp_phpunit/src/Cheerleader.php:33
/Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:64
ERRORS!
Tests: 7, Assertions: 9, Errors: 1.
Script phpunit test handling the test event returned with error code 2
$ composer test -- --debug
public function whatsThatSpell()
{
if (!$this->pompom->shake()) {
throw new PomShakeFailException();
}
return $this->word . '!';
}
Cheerleader.php:
public function testPomShake()
{
$mockPom = $this->createMock(Pompom
$mockPom->expects($this->once())
->method('shake');
$cheerleader = new Cheerleader($mockP
$cheerleader->whatsThatSpell();
}
CheerleaderTest.php:
public function testPomShake()
{
$mockPom = $this->createMock(Pompom::class);
$mockPom->expects($this->once())
->method('shake')
->willReturn(true);
$cheerleader = new Cheerleader($mockPom);
$cheerleader->whatsThatSpell();
}
CheerleaderTest.php:
$ composer test -- --debug
> phpunit test '--debug'
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started
Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started
Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended
Test 'WavePHPCheerCheerleaderTest::testTheSplits' started
Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended
Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' ended
Test 'WavePHPCheerCheerleaderTest::testPomShake' started
Test 'WavePHPCheerCheerleaderTest::testPomShake' ended
Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' started
Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' ended
Time: 25 ms, Memory: 4.00MB
OK (7 tests, 10 assertions)
Data Providers
A test method can accept arbitrary arguments. These
arguments are to be provided by a data provider
method.
public function testGimmeAnG()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('G'),
$this->equalTo('G'));
}
/**
* @test
*/
public function gimmeAnO()
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn('O'),
$this->equalTo('O'));
}
CheerleaderTest.php:
/**
* @dataProvider gimmeAnProvider
*/
public function testGimmeAn($parameter, $expectedResponse)
{
$cheerleader = new Cheerleader();
$this->assertThat($cheerleader->gimmeAn($parameter),
$this->equalTo($expectedResponse));
}
CheerleaderTest.php:
public function gimmeAnProvider()
{
return [
['G', 'G'],
['O', 'O']
];
}
CheerleaderTest.php:
A data provider method must be public and either return an array of
arrays or an object that implements the Iterator interface and yields an
array for each iteration step. For each array that is part of the collection
the test method will be called with the contents of the array as its
arguments.
$ composer test -- --debug
> phpunit test '--debug'
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
<snip>
Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #0 ('G', 'G')' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #0 ('G', 'G')' ended
Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #1 ('O', 'O')' started
Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #1 ('O', 'O')' ended
Time: 24 ms, Memory: 4.00MB
OK (9 tests, 12 assertions)
Testing PHP Errors
By default, PHPUnit converts PHP errors,
warnings, and notices that are triggered during
the execution of a test to an exception.
use PHPUnitFrameworkErrorError;
use PHPUnitFrameworkErrorNotice;
...
public function testExpectedPHPError()
{
$this->expectException(Error::class);
}
public function testExpectedPHPNotice()
$this->expectException(Notice::class);
}
Code Coverage
$ composer test -- --coverage-html coverage --whitelist src
So much more...
•online doc: https://phpunit.de/
•command line options
•test filtering, test coverage options, logging, set php.ini
vals, and more...
•config file (phpunit.xml)
•assertions
•annotations
Brian Johnson
@TheOtherBrianJ
@peakphp | peakphp.org
paylease.com
https://joind.in/talk/2b86d

Unlock The Mystery Of PHPUnit (Wave PHP 2018)

  • 1.
    Unlock The Mystery ofPHPUnit Brian Johnson
  • 2.
    What is aunit test? In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use. https://en.wikipedia.org/wiki/Unit_testing
  • 3.
    What is PHPUnit? PHPUnitis a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. https://phpunit.de/
  • 4.
    Setup/Install $ composer require--dev phpunit/phpunit Using version ^7.3 for phpunit/phpunit ./composer.json has been created Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 27 installs, 0 updates, 0 removals - Installing sebastian/version (2.0.1): Loading from cache - Installing sebastian/resource-operations (1.0.0): Loading from cache ...
  • 5.
    $ vendor/bin/phpunit PHPUnit 7.3.5by Sebastian Bergmann and contributors. Usage: phpunit [options] UnitTest [UnitTest.php] phpunit [options] <directory>
  • 6.
  • 7.
    A Basic TestExample Implement a Cheerleader Cheerleader functions: •gimmeAn - will accept a character as an argument; will return same character, and append character to an ever-growing string •whatsThatSpell - will return the stored string built by repeated calls to gimmeAn with an ! appended to the end •doTheSplits - will throw an exception
  • 8.
    <?php namespace WavePHPCheer; use PHPUnitFrameworkTestCase; classCheerleaderTest extends TestCase { } CheerleaderTest.php:
  • 9.
    > phpunit test PHPUnit7.3.5 by Sebastian Bergmann and contributors. W 1 / 1 (100%) Time: 20 ms, Memory: 4.00MB There was 1 warning: 1) Warning No tests found in class "WavePHPCheerCheerleaderTest". WARNINGS! Tests: 1, Assertions: 0, Warnings: 1. Script phpunit test handling the test event returned with error code 1 $ composer test
  • 10.
    public function testGimmeAnG() { $cheerleader= new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('G'), $this->equalTo('G')); } CheerleaderTest.php: •gimmeAn - will accept a character as an argument; will return same character, and append character to an ever- growing string
  • 11.
    /** * @test */ public functiongimmeAnO() { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('O'), $this->equalTo('O')); } CheerleaderTest.php:
  • 12.
    /** * @test */ public functiontestWhatsThatSpell() { $cheerleader = new Cheerleader(); $cheerleader->gimmeAn('G'); $cheerleader->gimmeAn('O'); $this->assertThat($cheerleader->whatsThatSpell(), $this->equalTo('GO!')); } CheerleaderTest.php:
  • 13.
    <?php namespace WavePHPCheer; use PHPUnitFrameworkTestCase; classCheerleaderTest extends TestCase { public function testGimmeAnG() { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('G'), $this->equalTo('G')); } /** * @test */ public function gimmeAnO() { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('O'), $this->equalTo('O')); } /** * @test */ public function testWhatsThatSpell() { $cheerleader = new Cheerleader(); $cheerleader->gimmeAn('G'); $cheerleader->gimmeAn('O'); $this->assertThat($cheerleader->whatsThatSpell(), $this->equalTo('GO!')); } }
  • 14.
    $ composer test >phpunit test PHPUnit 7.3.5 by Sebastian Bergmann and contributors. EEE 3 / 3 (100%) Time: 18 ms, Memory: 4.00MB There were 3 errors: 1) WavePHPCheerCheerleaderTest::testGimmeAnG Error: Class 'WavePHPCheerCheerleader' not found /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:11 2) WavePHPCheerCheerleaderTest::gimmeAnO Error: Class 'WavePHPCheerCheerleader' not found /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:21 3) WavePHPCheerCheerleaderTest::testWhatsThatSpell Error: Class 'WavePHPCheerCheerleader' not found /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:31 ERRORS! Tests: 3, Assertions: 0, Errors: 3. Script phpunit test handling the test event returned with error code 2
  • 15.
    <?php namespace WavePHPCheer; class Cheerleader { publicfunction gimmeAn($letter) { } } Cheerleader.php:
  • 16.
    $ composer test >phpunit test PHPUnit 7.3.5 by Sebastian Bergmann and contributors. FFE 3 / 3 (100%) Time: 19 ms, Memory: 4.00MB There was 1 error: 1) WavePHPCheerCheerleaderTest::testWhatsThatSpell Error: Call to undefined method WavePHPCheerCheerleader::whatsThatSpell() /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:34 -- There were 2 failures: 1) WavePHPCheerCheerleaderTest::testGimmeAnG Failed asserting that null matches expected 'G'. /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:13 2) WavePHPCheerCheerleaderTest::gimmeAnO Failed asserting that null matches expected 'O'. /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:23 ERRORS! Tests: 3, Assertions: 2, Errors: 1, Failures: 2. Script phpunit test handling the test event returned with error code 2
  • 17.
    <?php namespace WavePHPCheer; class Cheerleader { private$word = ''; public function gimmeAn($letter) { $this->word .= $letter; return $letter; } public function whatsThatSpell() { return $this->word . '!'; } } • gimmeAn - will accept a character as an argument; will return same character, and append character to an ever-growing string • whatsThatSpell - will return the stored string built by repeated calls to gimmeAn with an ! appended to the end
  • 18.
    $ composer test >phpunit test PHPUnit 7.3.5 by Sebastian Bergmann and contributors. ... 3 / 3 (100%) Time: 19 ms, Memory: 4.00MB OK (3 tests, 3 assertions)
  • 19.
    <?php namespace WavePHPCheer; use PHPUnitFrameworkTestCase; classCheerleaderTest extends TestCase { public function testGimmeAnG() { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('G'), $this->equalTo('G')); } /** * @test */ public function gimmeAnO() { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('O'), $this->equalTo('O')); } /** * @test */ public function testWhatsThatSpell() { $cheerleader = new Cheerleader(); $cheerleader->gimmeAn('G'); $cheerleader->gimmeAn('O'); $this->assertThat($cheerleader->whatsThatSpell(), $this->equalTo('GO!')); } } $ composer test > phpunit test PHPUnit 7.3.5 by Sebastian Bergmann and contributors. ... 3 / 3 (100%) Time: 19 ms, Memory: 4.00MB OK (3 tests, 3 assertions)
  • 20.
    A Basic TestExample Implement a Cheerleader Cheerleader functions: •gimmeAn - will accept a character as an argument; will return same character, and append character to an ever-growing string •whatsThatSpell - will return the stored string built by repeated calls to gimmeAn with an ! appended to the end •doTheSplits - will throw an exception
  • 21.
    /** * @expectedException WavePHPCheerLackOfFlexibilityException */ publicfunction testTheSplits() { $cheerleader = new Cheerleader(); $cheerleader->doTheSplits(); } CheerleaderTest.php:
  • 22.
    <?php namespace WavePHPCheer; use Exception; classLackOfFlexibilityException extends Exception { } LackOfFlexibilityException.php:
  • 23.
    public function doTheSplits() { thrownew LackOfFlexibilityException("I can't do that!"); } Cheerleader.php:
  • 24.
    $ composer test-- --debug > phpunit test '--debug' PHPUnit 7.3.5 by Sebastian Bergmann and contributors. Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended Test 'WavePHPCheerCheerleaderTest::testTheSplits' started Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended Time: 20 ms, Memory: 4.00MB OK (4 tests, 4 assertions)
  • 25.
    use InvalidArgumentException; ... public functiontestGimmeAnInvalidArg() { $cheerleader = new Cheerleader(); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( 'WavePHPCheerCheerleader::gimmeAn may only ' . 'accept a single char arg'); $this->expectExceptionCode(619); $cheerleader->gimmeAn("This is not a single character"); } CheerleaderTest.php:
  • 26.
    use InvalidArgumentException; ... public functiongimmeAn($letter) { if (!is_string($letter) || 1 != mb_strlen($letter)) { throw new InvalidArgumentException(__METHOD__ . ' may only accept a single char arg', 619); } $this->word .= $letter; return $letter; } Cheerleader.php:
  • 27.
    $ composer test-- --debug > phpunit test '--debug' PHPUnit 7.3.5 by Sebastian Bergmann and contributors. Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended Test 'WavePHPCheerCheerleaderTest::testTheSplits' started Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' ended Time: 21 ms, Memory: 4.00MB OK (5 tests, 7 assertions)
  • 28.
    MOCKS! The practice ofreplacing an object with a test double that verifies expectations, for instance asserting that a method has been called, is referred to as mocking.
  • 29.
    <?php namespace WavePHPCheer; class Pompom { publicfunction shake() { // return true if shake successful return true; } } Pompom.php:
  • 30.
    private $pompom; ... public function__construct(Pompom $pompom = null) { if (empty($pompom)) { $pompom = new Pompom(); } $this->setPompom($pompom); } Cheerleader.php:
  • 31.
    public function setPompom(Pompom$pompom) { $this->pompom = $pompom; } ... public function whatsThatSpell() { $this->pompom->shake(); return $this->word . '!'; } Cheerleader.php:
  • 32.
    getMockBuilder($type) createMock($type) How do Imake a mock? The createMock($type) method immediately returns a test double object for the specified type (interface or class). The creation of this test double is performed using best practice defaults. The __construct() and __clone() methods of the original class are not executed) and the arguments passed to a method of the test double will not be cloned. If these defaults are not what you need then you can use the getMockBuilder($type) method to customize the test double generation using a fluent interface.
  • 33.
    public function testPomShake() { $mockPom= $this->createMock(Pompom::class); $mockPom->expects($this->once()) ->method('shake'); $cheerleader = new Cheerleader($mockPom); $cheerleader->whatsThatSpell(); } CheerleaderTest.php:
  • 34.
    public function testPomShakeFail() { $mockPom= $this->createMock(Pompom::class); $mockPom->expects($this->once()) ->method('shake') ->willReturn(false); $this->expectException(PomShakeFailException::class); $cheerleader = new Cheerleader($mockPom); $cheerleader->whatsThatSpell(); } CheerleaderTest.php:
  • 35.
    public function whatsThatSpell() { if(!$this->pompom->shake()) { throw new PomShakeFailException(); } return $this->word . '!'; } Cheerleader.php:
  • 36.
    $ composer test-- --debug > phpunit test '--debug' PHPUnit 7.3.5 by Sebastian Bergmann and contributors. Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended Test 'WavePHPCheerCheerleaderTest::testTheSplits' started Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' ended Test 'WavePHPCheerCheerleaderTest::testPomShake' started Test 'WavePHPCheerCheerleaderTest::testPomShake' ended Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' started Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' ended Time: 23 ms, Memory: 4.00MB There was 1 error: 1) WavePHPCheerCheerleaderTest::testPomShake WavePHPCheerPomShakeFailException: /Volumes/git/wavephp_phpunit/src/Cheerleader.php:33 /Volumes/git/wavephp_phpunit/test/CheerleaderTest.php:64 ERRORS! Tests: 7, Assertions: 9, Errors: 1. Script phpunit test handling the test event returned with error code 2 $ composer test -- --debug
  • 37.
    public function whatsThatSpell() { if(!$this->pompom->shake()) { throw new PomShakeFailException(); } return $this->word . '!'; } Cheerleader.php: public function testPomShake() { $mockPom = $this->createMock(Pompom $mockPom->expects($this->once()) ->method('shake'); $cheerleader = new Cheerleader($mockP $cheerleader->whatsThatSpell(); } CheerleaderTest.php:
  • 38.
    public function testPomShake() { $mockPom= $this->createMock(Pompom::class); $mockPom->expects($this->once()) ->method('shake') ->willReturn(true); $cheerleader = new Cheerleader($mockPom); $cheerleader->whatsThatSpell(); } CheerleaderTest.php:
  • 39.
    $ composer test-- --debug > phpunit test '--debug' PHPUnit 7.3.5 by Sebastian Bergmann and contributors. Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnG' ended Test 'WavePHPCheerCheerleaderTest::gimmeAnO' started Test 'WavePHPCheerCheerleaderTest::gimmeAnO' ended Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' started Test 'WavePHPCheerCheerleaderTest::testWhatsThatSpell' ended Test 'WavePHPCheerCheerleaderTest::testTheSplits' started Test 'WavePHPCheerCheerleaderTest::testTheSplits' ended Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' started Test 'WavePHPCheerCheerleaderTest::testGimmeAnInvalidArg' ended Test 'WavePHPCheerCheerleaderTest::testPomShake' started Test 'WavePHPCheerCheerleaderTest::testPomShake' ended Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' started Test 'WavePHPCheerCheerleaderTest::testPomShakeFail' ended Time: 25 ms, Memory: 4.00MB OK (7 tests, 10 assertions)
  • 40.
    Data Providers A testmethod can accept arbitrary arguments. These arguments are to be provided by a data provider method.
  • 41.
    public function testGimmeAnG() { $cheerleader= new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('G'), $this->equalTo('G')); } /** * @test */ public function gimmeAnO() { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn('O'), $this->equalTo('O')); } CheerleaderTest.php:
  • 42.
    /** * @dataProvider gimmeAnProvider */ publicfunction testGimmeAn($parameter, $expectedResponse) { $cheerleader = new Cheerleader(); $this->assertThat($cheerleader->gimmeAn($parameter), $this->equalTo($expectedResponse)); } CheerleaderTest.php:
  • 43.
    public function gimmeAnProvider() { return[ ['G', 'G'], ['O', 'O'] ]; } CheerleaderTest.php: A data provider method must be public and either return an array of arrays or an object that implements the Iterator interface and yields an array for each iteration step. For each array that is part of the collection the test method will be called with the contents of the array as its arguments.
  • 44.
    $ composer test-- --debug > phpunit test '--debug' PHPUnit 7.3.5 by Sebastian Bergmann and contributors. <snip> Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #0 ('G', 'G')' started Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #0 ('G', 'G')' ended Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #1 ('O', 'O')' started Test 'WavePHPCheerCheerleaderTest::testGimmeAn with data set #1 ('O', 'O')' ended Time: 24 ms, Memory: 4.00MB OK (9 tests, 12 assertions)
  • 45.
    Testing PHP Errors Bydefault, PHPUnit converts PHP errors, warnings, and notices that are triggered during the execution of a test to an exception.
  • 46.
    use PHPUnitFrameworkErrorError; use PHPUnitFrameworkErrorNotice; ... publicfunction testExpectedPHPError() { $this->expectException(Error::class); } public function testExpectedPHPNotice() $this->expectException(Notice::class); }
  • 47.
  • 48.
    $ composer test-- --coverage-html coverage --whitelist src
  • 50.
    So much more... •onlinedoc: https://phpunit.de/ •command line options •test filtering, test coverage options, logging, set php.ini vals, and more... •config file (phpunit.xml) •assertions •annotations
  • 51.
    Brian Johnson @TheOtherBrianJ @peakphp |peakphp.org paylease.com https://joind.in/talk/2b86d