Giter Club home page Giter Club logo

atoum-documentation's Introduction

atoum's logo

atoum Package version Build Status Coverage Status Lint Gitter

PHP version atoum version
5.3 -> 5.6 1.x -> 3.x
7.2 -> 8.1 4.X -> 4.1
8.x 4.1 < 4.X (current)

A simple, modern and intuitive unit testing framework for PHP!

Just like SimpleTest or PHPUnit, atoum is a unit testing framework specific to the PHP language. However, it has been designed from the start with the following ideas in mind:

  • Can be implemented rapidly,
  • Simplify test development,
  • Allow for writing reliable, readable, and clear unit tests.

To accomplish that, it massively uses capabilities provided by PHP, to give the developer a whole new way of writing unit tests. Therefore, it can be installed and integrated into an existing project extremely easily, since it is only a single PHAR archive, which is the one and only entry point for the developer. Also, thanks to its fluent interface, it allows for writing unit tests in a fashion close to natural language. It also makes it easier to implement stubbing within tests, thanks to intelligent uses of anonymous functions and closures. atoum natively, and by default, performs the execution of each unit test within a separate PHP process, to warrant isolation. Of course, it can be used seamlessly for continuous integration, and given its design, it can be made to cope with specific needs extremely easily. atoum also accomplishes all of this without affecting performance, since it has been developed to boast a reduced memory footprint while allowing for hastened test execution. It can also generate unit test execution reports in the Xunit format, which makes it compatible with continuous integration tools such as Jenkins. atoum also generates code coverage reports, in order to make it possible to supervise unit tests. Finally, even though it is developed mainly on UNIX, it can also work on Windows.

Why atoum?

  • atoum is really easy to install: clone it from github, download its PHAR or simply use composer,
  • atoum provides a high level of security during test execution by isolating each test method in its own PHP process. Of course, this feature is available out of the box, no need to install any additional extension,
  • atoum runs tests in a parallelized environment making the suite run as fast as possible by taking advantage of today's multi-core CPUs,
  • atoum provides a full-featured set of natural and expressive assertions making tests as readable as possible. Here is an example:
<?php

$this
    ->integer(150)
        ->isGreaterThan(100)
        ->isLowerThanOrEqualTo(200)
;
  • atoum supports a BDD-like syntax with a lot of structural keywords:
<?php

$this
    ->given($testedInstance = new testedClass())
    ->and($testedClass[] = $firstValue = uniqid())
    ->then
        ->sizeof($testedInstance)->isEqualTo(1)
        ->string($testedClass[0])->isEqualTo($firstValue)
;
  • atoum provides a dead simple, yet very powerful, mock engine:
<?php

$this
    ->given($testedInstance = new testedClass())
    ->and($aMock = new \mock\foo\bar()) // here a mock of the class \foo\bar is created dynamically
    ->and($this->calling($aMock)->doOtherThing = true) // each call to doOtherThing() by the instance will return true
    ->and($testedInstance->setDependency($aMock))
    ->then
        ->boolean($testedInstance->doSomething())->isTrue()
        ->mock($aMock)
            ->call('doOtherThing')->withArguments($testedInstance)->once() // Asserts that the doOtherThing() method of $aMock was called once
;
  • atoum provides a clear API to assert on exceptions:
<?php

$this
    ->given($testedInstance = new testedClass())
    ->and($aMock = new \mock\foo\bar()) // here a mock of the class \foo\bar is created dynamically
    ->and($this->calling($aMock)->doOtherThing->throw = $exception = new \exception()) // Call to doOtherThing() will throw an exception
    ->and($testedInstance->setDependency($aMock))
    ->then
        ->exception(function() use ($testedInstance) { $testedInstance->doSomething(); })
            ->isIdenticalTo($exception)
;
  • atoum also lets you mock native PHP functions. Again, this is available out of the box:
<?php

$this
    ->given($this->function->session_start = false)
    ->and($session = new testedClass())
    ->then
        ->exception(function () use ($session) { $session->start(); })
            ->isInstanceOf('project\namespace\exception')
            ->hasMessage('Unable to start session')
        ->function('session_start')->wasCalled()->once()
;
  • atoum is able to produce several reports like TAP, clover, xUnit to be easily integrated with Jenkins or any other continuous integration tool,
  • atoum supports data providers,
  • atoum tests support autorun: just include the atoum runner and launch your test using php path/to/test/file.php,
  • atoum's configuration file is exclusively written in PHP (no XML, YAML or any other format) giving you the best flexibility:
<?php

$script->addDefaultArguments('--test-it', '-ncc');

$runner->addTestsFromDirectory(__DIR__ . '/tests/units/classes');

$testGenerator = new atoum\atoum\test\generator();
$testGenerator
    ->setTestClassesDirectory(__DIR__ . '/tests/units/classes');
    ->setTestClassNamespace('atoum\atoum\tests\units');
    ->setTestedClassesDirectory(__DIR__ . '/classes');
    ->setTestedClassNamespace('atoum\atoum')
    ->setRunnerPath(__DIR__ . '/scripts/runner.php')
;

$runner->setTestGenerator($testGenerator);
  • atoum provides an automatic test template generator,
  • atoum provides a loop mode to easily retrigger failed tests,
  • atoum is full of other interesting features that you will discover over the time.

Prerequisites to use atoum

atoum absolutely requires PHP >= 5.6.0 or later to work. On UNIX, in order to check whether you have the right PHP version, you just need to run the following command in your terminal:

$ php -v | grep -oE 'php 5\.3\.(?:[3-9]|[1-9][0-9])|5\.[4-6]\.[0-9]+|[5-8]\.[0-9]+\.[0-9]+'

If PHP 5.6.x or equivalent gets displayed, then you have the right PHP version installed. Should you want to use atoum using its PHAR archive, you also need PHP to be able to access the phar module, which is normally available by default. On UNIX, in order to check whether you have this module or not, you just need to run the following command in your terminal:

$ php -m | grep -i phar

If Phar or equivalent gets displayed, then the module is properly installed. Generating reports in the Xunit format requires the xml module. On UNIX, in order to check whether you have this module or not, you just need to run the following command in your terminal:

$ php -m | grep -i xml

If Xml or equivalent gets displayed, then the module is properly installed. Should you wish to monitor the coverage rate of your code by the unit tests, the Xdebug 2.3 module will be required. On UNIX, in order to check whether you have this module or not, you just need to run the following command in your terminal:

$ php -v | grep -oi 'xdebug'

If Xdebug or equivalent gets displayed, then the module is properly installed.

A unit testing framework that can be made operational in 5 minutes!

Step 1: Install atoum

You just have to download its PHAR archive and store it where you wish, for example under /path/to/project/tests/atoum.phar. This PHAR archive contains the latest development version to pass the totality of atoum's unit tests. atoum's source code is also available via the GitHub repository. To check if atoum works correctly with your configuration, you can execute all its unit tests. To do that, you just need to run the following command in your terminal:

$ php atoum.phar --test-it

Step 2: Write your tests

Using your preferred text editor, create the file path/to/project/tests/units/helloWorld.php and add the following code:

<?php

namespace vendor\project\tests\units;

require_once 'path/to/atoum.phar';

include_once 'path/to/project/classes/helloWorld.php';

use atoum\atoum;
use vendor\project;

class helloWorld extends atoum\test
{
    public function testSay()
    {
        $helloWorld = new project\helloWorld();

        $this->string($helloWorld->say())->isEqualTo('Hello World!');
    }
}

Step 3: Run your test with the command line

Launch your terminal and run the following command:

$ php path/to/test/file[enter]

You should get the following result or something equivalent:

> atoum version XXX by Frédéric Hardy.
Error: Unattended exception: Tested class 'vendor\project\helloWorld' does not exist for test class 'vendor\project\tests\units\helloWorld'

Step 4: Write the class corresponding to your test

Using again your preferred text editor, create the file path/to/project/classes/helloWorld.php and add the following code:

<?php

namespace vendor\project;

class helloWorld
{
    public function say()
    {
        return 'Hello World!';
    }
}

Step 5: Run your test once more

In the same terminal, run the following command once again:

$ php path/to/test/file[enter]

You should get the following result, or something equivalent:

> atoum version 288 by Frédéric Hardy.
> Run vendor\project\tests\units\helloWorld...
[S___________________________________________________________][1/1]
=> Test duration: 0.00 second.
=> Memory usage: 0.25 Mb.
> Total test duration: 0.00 second.
> Total test memory usage: 0.25 Mb.
> Code coverage value: 100.00%
> Running duration: 0.08 second.
> Success (1 test, 1 method, 2 assertions, 0 error, 0 exception)!

Step 6: Complete your tests and restart the cycle from Step 3

<?php

namespace vendor\project\tests\units;

require_once 'path/to/atoum.phar';

include_once 'path/to/project/classes/helloWorld.php';

use atoum\atoum;
use vendor\project;

class helloWorld extends atoum\test
{
    public function test__construct()
    {
        $helloWorld = new project\helloWorld();

        $this
            ->string($helloWorld->say())->isEqualTo('Hello!')
            ->string($helloWorld->say($name = 'Frédéric Hardy'))->isEqualTo('Hello ' . $name . '!')
        ;
    }
}

To go further

atoum's documentation is still being written. Any help to improve it will be appreciated. However, if you want to further explore immediately atoum's possibilities, we recommend:

  • Running in your terminal, either the command php atoum.phar -h, or the command php scripts/runner.php -h,
  • Exploring the contents of the configurations directory in atoum's source, as it contains configuration file samples,
  • Exploring the contents of the tests/unit/classes directory in atoum's source, as it contains all of the unit tests,
  • Read the (french) conference slides about it, available online,
  • Read the (french) wiki,
  • Join the discussion channel,
  • Ask questions by e-mail at the address support[AT]atoum(DOT)org.

Troubleshooting

atoum's PHAR archive seems to not be working

In this case, the first thing you will want to do is confirm whether you have the latest version of the archive. You just need to download it again. If it still doesn't work, run the following command in a terminal window:

$ php -n atoum.phar -v

If you get atoum's version number, then the problem is coming from your PHP configuration. In most cases, the cause would be within extensions, that might be incompatible with the PHAR format, or that would prevent executing PHAR archives as a security measure. The ioncube extension for instance seems incompatible with PHAR archives, and you must, therefore, deactivate it if you are using it, by commenting the following line out of your php.ini, by prefixing it with the ; character:

zend_extension = /path/to/ioncube_loader*.*

The suhosin extension prevents executing PHAR archives, therefore its default configuration must be modified in order to be able to use atoum, by adding the following line in your php.ini file:

suhosin.executor.include.whitelist="phar"

Finally, if running atoum causes the screen to display characters looking like ???%, this would be because the detect_unicode directive inside your php.ini file is set to 1. To fix the problem, you just need to set it to 0 by editing your php.ini file or by running atoum with the following command:

$ php -d detect_unicode=0 atoum.phar [options]

If these three operations do not allow atoum to work, we suggest you send an e-mail to the address support[AT]atoum(DOT)org, describing in detail your configuration and your problem. You can also ask for help from the atoum development staff on the discussion channel of the atoum repository..

Error: Constant __COMPILER_HALT_OFFSET__ already defined /path/to/atoum.phar

This error comes from the fact the atoum PHAR archive is included in more than one place within your code using include or require. To fix this problem, you just need to include the archive by using only include_once or require_once, in order to ensure it is not included several times.

APC seems not work with atoum

APC is a free, open, and robust framework for caching and optimizing PHP intermediate code distributed under the form of a PHP extension. When testing classes that use APC, you may get some failure message showing that apc_fetch function is unable to retrieve a value. As all PHP extension, APC has some configuration options to enable it:

  • apc.enabled whether to enable or disable APC,
  • apc.enable_cli, whether to enable or disable APC for PHP CLI.

In order to use APC with atoum, you have to set apc.enabled and apc.enable_cli to 1, otherwise, it won't be enabled for the PHP CLI version, which is used by atoum.

Getting segfault when mocking objects

When using atoum and mocking objects, you will sometime get segfaults coming from PHP. These segfaults are caused by XDebug in version less than 2.1.0 which has problem handling reflection in some cases. To check the current version of XDebug, you can run php -v. To fix this issue, you have to update XDebug to the latest stable version. If you can't update XDebug on your system, you can still disable the extension to avoid getting segfaults. To be sure that XDebug has been successfully updated or disabled, you can run php -v. When you are done updating or disabling XDebug, run php atoum.phar --test-it to be sure that all the segfaults have gone and that atoum is working.


Roadmap

Looking for a roadmap?

Credits

atoum has been created by Frédéric Hardy. It is now led by a strong community of contributors. You can find them in the committer list or in the Contributors team.

License

atoum is released under the BSD-3-Clause License. See the bundled LICENSE file for details.

atoum-documentation's People

Contributors

adrienbrault avatar agallou avatar blanchonvincent avatar blueclock avatar bolbo avatar cedcannes avatar edas avatar ephys avatar fernandez-fabien avatar fvilpoix avatar geraldcroes avatar grummfy avatar guiled avatar hywan avatar jubianchi avatar mageekguy avatar marmotz avatar mikaelrandy avatar oliboy50 avatar pascalchevrel avatar raldochea avatar romain avatar sadortun avatar saumya1906 avatar shulard avatar stephpy avatar tut-tuuut avatar tyx avatar vdechenaux avatar xavierleune avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

atoum-documentation's Issues

English as default language?

Currently, the default language is french.
I think that a better strategy is to define english as default language, because currently, all english traffic is lost according to google analytics.
And it may be interesting to use the HTTP header accept-language to serve the best language to the user, but i'm not sure that it's technically possible.

More details about mock

Hello,
I find the mock example a bit confusing. So adding a bit more explain could be cool.

From this page : http://docs.atoum.org/fr/chapitre2.html#call

    $mock = new \mock\MyFirstClass;

    $this
    ->object(new MySecondClass($mock))

    ->mock($mock)
    ->call('myMethod')
    ->once()
    ;

I will change it to something like that

    $mock = new \mock\MyFirstClass;
   $object = new MySecondClass($mock)
$object->methodThatCallMyMethod(); // this will call myMethod on $mock
    $this
    ->object($object)
    ->mock($mock)
    ->call('myMethod')
    ->once()
    ;

shuntParentClassCalls documentation

According to the current (french) documentation, it is not clear to know if we have to call shuntParentClassCalls each time we create a mock or not. Here a surprising example for me:

//2 classes to test
class A {
    public function __construct() {
        trigger_error("Error A");
    }
}

class B {
    public function __construct() {
        trigger_error("Error B");
    }
}
...
//Now for the test, we want to mock classes above, but without calling constructor
public function test_shunt() {
        //We need to shunt constructor call
        $this->mockGenerator->shuntParentClassCalls();
        new \mock\A;
        //Don't needed again
        new \mock\A;
        //... but for a new class (I guess?), it is needed again
        $this->mockGenerator->shuntParentClassCalls();
        new \mock\B;
        //don't need...
        new \mock\B;
        //don't need...
        new \mock\A;
}

I guess that the mock generator work differently according to the class to mock, but IMHO it is not clear according to the documentation... or if it is not a feature, it is a bug :)

Thanks for your work!

extension asserter : missing documentation

There is no documentation on the extension asserter.

It could be use like this :

$this->extension('json')->isLoaded();

That will trigger an error if the json extension is not loaded.

We can achieve the same with the @extensions tag and the --fail-if-skipped-methods.

Is the extension asserter deprecated ? should it be documented ? // ping @atoum/all

key api crowdin

Hello,
I think it could be intresting to check how to remove the translation key from the config file of crowdin. Because when we push the documentation it's always @marmotz that push it to crowdin...

Document array contents assertions

It seems this syntax is not documented:

$a = [
    'foo' => 42,
    'bar' => '1337' 
];

$this
    ->array($a)
        ->integer['foo']->isEqualTo(42)
        ->string['bar']->isEqualTo('1337')
;

constant asserter : missing documentation

there is no documentation for the constant asserter.

it has an isEqualTo (and equalTo) method :

And seems to be used like this :

$this->constant(GLOB_NOSORT)->isEqualTo(4);

I don't really see the use case here. There is no check on wether it's a constant or not. So why not using the string/float/asserters ?

Is it just for the sematic ? (should we reflect that on the documentation ?) // ping @atoum/all

$this->testedClass & co : add it to documentation

As asked on irc :
$this>testedClass nor $this->newTestedInstance(); are documented. But they are realy usefull. So if anyone have some extra details on it it could be add on this ticket and after we can werite a bit on it.

thanks

Simplify the doc releasing process to get more contribution

Hy there,
As a new atoum user, I felt so happy to read that awesome doc...
Thanks so much to all contributors.

And I wanted to give my little contribution by changing some line of doc and make a PR... but the process was a bit weird to me. And I gave up.

How many contributions already lost like that ?

I can't tell. But I can propose a way that seems to me more simple to handle, share, and publish the doc.

The basic idea

The idea is to offer Github users the ability to make PR on atoum doc only with their favorite browser through marvelous Github's services and manly Github pages.

Changes that imply

It involves changes that you should accept before I spent time on a PR:

  • changing markup language from skril to markdown (that are quite similar)
  • having a small ruby stack on any server you'd like to host the doc pages for test purpose or when working without access to internet. Indeed, github offer to any of us to host it, so it's not necessary if you have Internet access.

Please tell me if you will approve this kind of change before I start to work on any PR.

Cheers

Assertions without parenthesis

Section title missing in cookbook

Since I have adding some top layer in cookbook, there is missing title (zend famwork symfony, etc ... ) they are not visible any more.

Migration to ReadTheDocs.org

Migration in progress.

You can see the result on http://atoum.readthedocs.org

TODO

  • translate from skriv to reST
  • configure ReadTheDocs for automatic html build for fr and en
  • fix the pdf build (it doesn't work for now)
  • create a custom html template (maybe later)
  • configure ReadTheDocs to be accessible by docs.atoum.org

Impossible to send translated file to crowdin

crowdin-cli upload translations

Warning: Skip /source/en/index.rst' Warning: Skip/source/en/cookbook.rst'
Warning: Skip /source/en/extensions.rst' Warning: Skip/source/en/contribute.rst'
Warning: Skip /source/en/getting_started.rst' Warning: Skip/source/en/written_help.rst'
Warning: Skip /source/en/asserters.rst' Warning: Skip/source/en/asserters/exception.inc.rst'
Warning: Skip /source/en/asserters/dateTime.inc.rst' Warning: Skip/source/en/asserters/boolean.inc.rst'
Warning: Skip /source/en/asserters/castToString.inc.rst' Warning: Skip/source/en/asserters/mock.inc.rst'
Warning: Skip /source/en/asserters/output.inc.rst' Warning: Skip/source/en/asserters/sizeOf.inc.rst'
Warning: Skip /source/en/asserters/utf8String.inc.rst' Warning: Skip/source/en/asserters/stream.inc.rst'
Warning: Skip /source/en/asserters/class.inc.rst' Warning: Skip/source/en/asserters/afterDestructionOf.inc.rst'
Warning: Skip /source/en/asserters/variable.inc.rst' Warning: Skip/source/en/asserters/float.inc.rst'
Warning: Skip /source/en/asserters/dateInterval.inc.rst' Warning: Skip/source/en/asserters/mysqlDateTime.inc.rst'
Warning: Skip /source/en/asserters/array.inc.rst' Warning: Skip/source/en/asserters/integer.inc.rst'
Warning: Skip /source/en/asserters/error.inc.rst' Warning: Skip/source/en/asserters/string.inc.rst'
Warning: Skip /source/en/asserters/hash.inc.rst' Warning: Skip/source/en/asserters/object.inc.rst'
Warning: Skip /source/en/quotes.rst' Warning: Skip/source/en/launch_test.rst'
Warning: Skip /source/en/option_cli.rst' Warning: Skip/source/en/ide.rst'
Warning: Skip `/source/en/having_fun_with_atoum.rst'

Adding switch between each language

Hi,
on the documentation it could be very interesting to have a link to change the language (in the bottom or the header).

But because the tempalte of the documentation is not in this repository, it's hard to say, change it here or there and make a pull request. So I prefer to let this issue open like this.

short syntax for assertions

See atoum/atoum#384

<?php

namespace tests\units;

use atoum;

class stdClass extends atoum
{
    public function testFoo()
    {
        $this
            ->variable('foo')->{'=='}('foo')
            ->variable('foo')->{'!='}('bar')

            ->object($this->newInstance)->{'=='}($this->newInstance)
            ->object($this->newInstance)->{'!='}(new \exception)
            ->object($this->newTestedInstance)->{'==='}($this->testedInstance)
            ->object($this->newTestedInstance)->{'!=='}($this->newTestedInstance)

            ->integer(rand(0, 10))->{'<'}(11)
            ->integer(rand(0, 10))->{'<='}(10)
            ->integer(rand(0, 10))->{'>'}(-1)
            ->integer(rand(0, 10))->{'>='}(0)
        ;
    }
}

how to translate? How to add page/... => how to contribute

It will be very usefull if we have a guide that guide how to contribute to this documentation.
With the readme, we know how to build the doc, but not how to contribute to it :

  • how(process/stuff to respect/....) to add new page/info/...?
  • how(process/stuff to respect/....) to add new language?
  • how(process/stuff to respect/....) to maintain other language that french (the reference)?

Split cookbooks

The cookbook : http://docs.atoum.org/fr/latest/cookbook.html

I'm wondering if it will not be better to split the cookbooks in multiple file or parts. We' have, right now: * stuff about using it with a some tools (behat, continous integration, ...)

  • stuff about using it with some frameworks
  • some receipt like testing singleton
  • some other stuff like optimising PHP

The two last for, me must stay in cookbook at the moment, but the other should be externalized.

[mock] Complete documentation for mock methods

Apparently this is missing

How to define differents return regarding the number of call

$this->calling($mock)->methode[1] = 'value for first call';
$this->calling($mock)->methode[2] = 'Value for second call';

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.