Les principes restent identiques aux autres langages
Un seul outil qui domine : PHPUnit
Mise en place :
# composer.json
{
"name": "remi/test-php",
"require": {
"php": ">=5.3.3",
"phpunit/phpunit": "3.7.*"
}
}
Lancement :
myhost$ composer update
myhost$ ./bin/phpunit
# Service/Greeting.php
class Greeting {
function hello($name) {
return "hello " . $name;
}
}
# Tests/Service/GreetingTest.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
/** @test */
function hello() {
$greetings = new Greeting();
$this->assertEquals("hello jonathan", $greetings->hello("jonathan"));
}
}
# Service/Greeting.php
class Greeting {
function hello($inputStream) {
return "hello " . $inputStream->getValue();
}
}
interface InputStream {
function getValue();
}
# Tests/Service/GreetingTests.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
/** @test */
function hello() {
$greeting = new Greeting();
$inputStream = $this->getMock("InputStream");
$inputStream->expects($this->once())
->method("getValue")
->will($this->returnValue("jonathan"));
$this->assertEquals("hello jonathan", $greeting->hello($inputStream));
}
}
# Service/Greeting.php
class Greeting {
function hello($outputStream, $name) {
$outputStream->write("hello " . $name);
}
}
interface OutputStream {
function write($value);
}
# Tests/Service/GreetingTest.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
/** @test */
function hello() {
$greeting = new Greeting();
$outputStream = $this->getMock("OutputStream");
$outputStream->expects($this->once())
->method("write")
->with($this->eq("hello jonathan"));
$greeting->hello($outputStream, "jonathan");
}
}
# composer.json
{
"name": "remi/test-php",
"require": {
"php": ">=5.3.3",
"phpunit/phpunit": "3.7.*",
"mockery/mockery": "0.8.0"
}
}
# Tests/Service/GreetingTest.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
/** @test */
function hello() {
$greeting = new Greeting();
$inputStream = \Mockery::mock('myMockId');
$inputStream->shouldReceive('getValue')
->times(1)
->andReturn("jonathan");
$this->assertEquals("hello jonathan", $greeting->hello($inputStream));
}
}
# composer.json
{
"name": "remi/test-php",
"require": {
"php": ">=5.3.3",
"phpunit/phpunit": "3.7.*",
"hamcrest/hamcrest": "1.1.0"
}
}
# Tests/Service/GreetingTest.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
/** @test */
function hello() {
$greeting = new Greeting();
assertThat($greeting->hello("jonathan"), is("hello jonathan"));
assertThat($greeting->hello("jonathan"), startsWith("hello"));
assertThat($greeting->hello("jonathan"), endsWith("jonathan"));
}
}
# Tests/Service/GreetingTest.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
function setup() {
$this->greeting = new Greeting();
}
/**
* @test
* @dataProvider getPeopleWithGreetings
*/
function hello($name, $message) {
assertThat($this->greeting->hello($name), is($message));
}
function getPeopleWithGreetings() {
return [
["jonathan", "hello jonathan"],
["victor", "hello victor"],
];
}
}
# Service/Greeting.php
class Greeting {
function hello($name) {
if ($name === "remi")
throws new LogicException("hey ! it's me ! silly tool...");
return "hello " . $name;
}
}
# Tests/Service/Greetings.php
class GreetingTest extends \PHPUnit_Framework_TestCase {
/**
* @test
* @expectedException LogicException
* @expectedExceptionMessage hey ! it's me ! silly tool...
*/
function helloToSomeoneAlreadySeen() {
$greeting = new Greeting();
$greetings->hello("remi");
}
}
# Tests/Model/StackTest.php
class StackTest extends PHPUnit_Framework_TestCase {
public function testEmpty() {
$stack = array();
$this->assertEmpty($stack);
return $stack;
}
/** @depends testEmpty */
public function testPush(array $stack) {
array_push($stack, 'foo');
$this->assertEquals('foo', $stack[count($stack)-1]);
$this->assertNotEmpty($stack);
return $stack;
}
Un outil de BDD reconnu : Behat
Mise en place :
# composer.json
{
"name": "remi/test-php",
"require": {
"php": ">=5.3.3",
"behat/behat": "2.4.*@stable"
}
}
Lancement :
myhost$ composer update
myhost$ ./bin/behat
# features/ls.feature
Scenario: List 2 files in a directory
Given I am in a directory "test"
And I have a file named "foo"
And I have a file named "bar"
When I run "ls"
Then I should get:
"""
bar
foo
"""
# features/bootstrap/SystemSteps.php
class SystemSteps extends BehatContext {
/**
* @Given /^I am in a directory "([^"]*)"$/
*/
public function iAmInADirectory($dir) {
if (!file_exists($dir)) {
mkdir($dir);
}
chdir($dir);
}
}
# features/bootstrap/SystemSteps.php
use Behat\Gherkin\Node\PyStringNode;
class SystemSteps extends BehatContext {
/**
* @Then /^I should get:$/
*/
public function iShouldGet(PyStringNode $string) {
// PHPUnit
$this->assertEquals($string->getRaw(), $this->output);
// Hamcrest
assertThat($string->getRaw(), is($this->output));
// Custom
if ($string->getRaw() !== $this->output)
throws new Exception("value is not expected");
}
}
# composer.json
{
"name": "remi/test-php",
"require": {
"php": ">=5.3.3",
"behat/behat": "2.4.*@stable",
"behat/mink": "1.4@stable"
}
}
# features/bootstrap/BrowserSteps.php
class BrowserSteps extends BehatContext {
/**
* @Given /^I visit the page "([^"]*)"$/
*/
public function iVisitThePage($url) {
$driver = new \Behat\Mink\Driver\ZombieDriver();
$this->session = new \Behat\Mink\Session($driver);
$this->session->visit($url);
}
/**
* @Given /^I search for "([^"]*)"$/
*/
public function iSearchFor($query) {
$page = $this->session->getPage();
$page->find("#search > input[type=search]")->setValue($query);
$page->find("#search > input[type=submit]")->press();
}
}