5th of February 2015
Table of contents
● Why● Install● Atoum in figure● Assertions● Syntax● Features● Config● Reporting● Extensions● Feedback
5th of February 2015
Atoum221 classes tests1750 methods26168 assertions
PHPUnit293 classes tests1329 methods2039 assertions
atoum in figure
5th of February 2015
Syntax
<?php
namespace estvoyage\statsd\tests\units\probe;
require __DIR__ . '/../../runner.php';
use …;
class timer extends atoum\test{ function testValueGoesInto() {
// … }}
5th of February 2015
Syntax
function testValueGoesInto(){ $this ->object($this->testedInstance->bucketIs($bucket)) ->isTestedInstance ->string('a')->isEqualTo('a') ->integer(1)->isEqualTo(1) ->integer(0)->isZero() ->array(array())->isEmpty() ;}
5th of February 2015
Syntax
public function testException(){ $this ->object($this->newTestedInstance)->isInstanceOf('\Skeleton\Skeleton') ->exception(function() { $this->testedInstance->implodeArray(true); }) ->isInstanceOf('\Exception') ->hasMessage('Must be an array') ->hasCode(42) ;}
5th of February 2015
Syntax with sugar
class timer extends atoum\test{ function testValueGoesInto() { $this ->given( $client = new statsd\client, $bucket = new metric\bucket(uniqid()) ) ->if($this->newTestedInstance($client)) ->then ->object($this->testedInstance->bucketIs($bucket)) ->isTestedInstance ; }}
5th of February 2015
Syntax mock
$this ->if($generator = new testedClass()) //… ->and($testClassesDirectoryPath = new \mock\atoum\fs\path('/a/b/c')) ->and($this->calling($testClassesDirectoryPath)->exists = true) ->and($this->calling($testClassesDirectoryPath)->getRealPath = $testClassesDirectoryPath)
->and($testedClassPath = new \mock\atoum\fs\path('/x/y/z/f.php')) ->and($this->calling($testedClassPath)->putContents = $testedClassPath)
->and($testClassPath = new \mock\atoum\fs\path('/a/b/c/d/e/f.php')) ->and($this->calling($testClassPath)->getRealParentDirectoryPath = new \mock\atoum\fs\path('/a/b/c/d/e')) ->and($this->calling($testClassPath)->getRealPath = $testClassPath) ->and($this->calling($testClassPath)->putContents = $testClassPath) //…
5th of February 2015
Syntax mock
//… ->and($this->calling($pathFactory)->build = function($path) use ($testClassesDirectoryPath, $testClassPath, $testedClassPath) { switch ($path) { case (string) $testClassesDirectoryPath . DIRECTORY_SEPARATOR: return $testClassesDirectoryPath; case (string) $testClassPath: return $testClassPath; default: return $testedClassPath; } }) ->then ->object($generator->generate((string) $testClassPath))->isIdenticalTo($generator) ->mock($templateParser) ->call('parseFile') ->withArguments( $generator->getTemplatesDirectory() . DIRECTORY_SEPARATOR . 'testClass.php' )->once();
5th of February 2015
Syntax mock PHP functions
function testValueGoesInto(){ $this ->given( $client = new statsd\client, $bucket = new metric\bucket(uniqid()), $this->function->microtime[1] = $start = 1418733215.0566, $this->function->microtime[2] = $stop = 1418733220.6586 ) ->if( $this->newTestedInstance($client) ) ->then ->object($this->testedInstance->bucketIs($bucket))->isTestedInstance ->mock($client)->call('valueGoesInto') ->withArguments(metric\value::timing(($stop * 10000) - ($start * 10000)), $bucket) ->once ;}
5th of February 2015
Loop TDD
● Write test● Go to console● Write command or hit ↑● Hit “enter”● See test fail● Write code● Go to console● Hit enter● See test pass
● Write test● Go to console● Write command or hit ↑● Hit “enter”● See test fail● Write code● Go to console● Write command or hit ↑● Hit enter● See test pass
5th of February 2015
Config
<?php
use \mageekguy\atoum;
$a = new atoum\reports\asynchronous\xunit;$a->addWriter(new atoum\writers\file('/tmp/nn'));$runner->addReport($a);
$report = $script->addDefaultReport();
$coverageField = new atoum\report\fields\runner\coverage\html('atoum', '/tmp/report');$coverageField->setRootUrl('file:///tmp/report/index.html');$report->addField($coverageField);
5th of February 2015
Config
<?php//TEST GENERATOR SETUP
$testGenerator = new atoum\test\generator();
// Please replace in next line "/path/to/your/tests/units/classes/directory" by your unit test's directory.$testGenerator->setTestClassesDirectory('path/to/your/tests/units/classes/directory');
// Please replace in next line "your\project\namespace\tests\units" by your unit test's namespace.$testGenerator->setTestClassNamespace('your\project\namespace\tests\units');
// Please replace in next line "/path/to/your/classes/directory" by your classes directory.$testGenerator->setTestedClassesDirectory('path/to/your/classes/directory');
// Please replace in next line "your\project\namespace" by your project namespace.$testGenerator->setTestedClassNamespace('your\project\namespace');
// Please replace in next line "path/to/your/tests/units/runner.php" by path to your unit test's runner.$testGenerator->setRunnerPath('path/to/your/tests/units/runner.php');
$script->getRunner()->setTestGenerator($testGenerator);
5th of February 2015
Visibility
class foo{ protected function bar() { return $this; }
protected function baz($arg) { return $arg; }}
5th of February 2015
Visibility
public function testBar(){ $this ->if($sut = new \foo()) ->then ->object($this->invoke($sut)->bar())->isIdenticalTo($sut) ;}
public function testBaz(){ $this ->if($sut = new \foo()) ->and($arg = uniqid()) ->then ->variable($this->invoke($sut)->baz($arg))->isEqualTo($arg) ;}
5th of February 2015
Json-schema
class foo extends atoum\test{ public function testIsJson() { $this ->given($string = '{"foo": "bar"}') ->then ->json($string) ; }
public function testValidatesSchema() { $this ->given($string = '["foo", "bar"]') ->then ->json($string)->validates('{"title": "test", "type": "array"}') ->json($string)->validates('/path/to/json.schema') ; }}
5th of February 2015
Ruler
./vendor/bin/atoum -d tests --filter 'not ("unSuperTagAuNiveauDeLaMethode1" in tags)'
./vendor/bin/atoum -d tests --filter 'method = "testMethod1'
./vendor/bin/atoum -d tests --filter 'method in ["testMethod1"]'
./vendor/bin/atoum -d tests --filter 'class = "mageekguy\atoum\ruler\tests\units\testClass1'
./vendor/bin/atoum -d tests --filter 'namespace = "mageekguy\atoum\ruler\tests\units'
./vendor/bin/atoum -d tests --filter 'testedclass = "mageekguy\atoum\ruler\testClass1'
./vendor/bin/atoum -d tests --filter 'testedclassnamespace = "mageekguy\atoum\ruler'
5th of February 2015
Praspel
$this->sample($this->realdom->boundinteger(7, 13)->or->boundinteger(42, 153));
$data = $this->realdom->regex('/[\w\-_]+(\.[\w\-\_]+)*@\w\.(net|org)/');$this->string($this->sample($data)) ->contains(…)->…;
//Date$data = $this->realdom->date( 'd/m H:i', $this->realdom->boundinteger( $this->realdom->timestamp('yesterday'), $this->realdom->timestamp('next Monday') ));
foreach($this->sampleMany($data, 10) as $date) var_dump($date);
5th of February 2015
BDD
public function should_format_underscore_separated_method_name(){ $this ->given($formatter = new testedClass()) ->then ->invoking->format(__FUNCTION__)->on($formatter) ->shouldReturn('should format underscore separated method name') ;}
public function shouldFormatCamelCaseMethodName(){ $this ->given($formatter = new testedClass()) ->then ->invoking->format(__FUNCTION__)->on($formatter) ->shouldReturn('should format camel case method name') ;}
5th of February 2015
BDD$ vendor/bin/atoum -d specs> jubianchi\example\formatter... ✔ should format underscore separated method name
✘ should format underscore separated method name 256: Tested class 'jubianchi\example\formatter' does not exist for test class 'jubianchi\example\specs\formatter' File: /atoum-bdd-extension/formatter.php
✘ should format mixed method name 256: Tested class 'jubianchi\example\formatter' does not exist for test class 'jubianchi\example\specs\formatter' File: /atoum-bdd-extension/formatter.php
Failure (1 spec, 3/3 examples, 0 void example, 0 skipped example, 0 uncompleted example, 0 failure, 3 errors, 0 exception)!
5th of February 2015
autotoum
autotoum -d -w src,tests/units/subset,tests/units/otherSubset -- -d
tests/units
5th of February 2015
Praspel
<?php
class Filesystem { const SIZE = 1024; /** * @invariant _usage: boundinteger(0, static::SIZE); */ protected $_usage = 0;
/** * @invariant _map: array([to class('File')], 0..0xffff); */ protected $_map = array(); /** * @ensures \result: this->_usage; */ public function getUsage ( ) { /* ... */ }
/** * @requires file: class('File') and * index: 0..0xffff or void; * @behavior full { * @description 'The filesystem is full.'; * @requires \pred('$this->getUsage() + $file->getSize() * > static::SIZE'); * @ensures \none; * @throwable AllocationException e with * file->isAttached(): false and * e->getFilesystem(): this; * } * @default { * @ensures file->isAttached(): true and * \result: boolean(); * } */ public function store ( File $file, $index = null ) { /* ... */ }}
5th of February 2015
Sources
● https://github.com/atoum/atoum● https://github.com/vonglasow/atoum-skeleton● http://thenounproject.com/
Credits photos: ● Luis Prado from the Noun Project● Darren Barone from the Noun Project● useiconic.com from the Noun Project● iconsmind.com from the Noun Project● SuperAtic LABS from the Noun Project● Julia Stoffer from the Noun Project● CommitStrip.com● Alexander Pretschner
5th of February 2015
Join the community !(in Paris)
Social networks :● Follow us on Twitter : https://twitter.com/steamlearn● Like us on Facebook : https://www.facebook.com/steamlearn
SteamLearn is an Inovia initiative : inovia.fr
You wish to be in the audience ? Join the meetup group! http://www.meetup.com/Steam-Learn/
Top Related