Introduction
For our basic usage introduction, we will be testing httpbin.org
interface. If you have not yet installed Athena, refer to Athena project page.
Project Setup
To start using Athena, we'll need to setup a directory, where we will save our tests into.
myteam-tests/
├── HttpBinTest.php
├── Report
├── phpunit.xml
└── athena.json
athena.json
is where Athena reads the configuration from. In this case we will contain only the necessary information for a simple API test run.
Report/
directory is where the HTML report, generated by Athena, will be output.
The report
One of our goals is to debug what actions were performed by the HTTP Client. We don't need too much detail, but enough to understand what happened, specially in case something goes wrong.
{
"report" : {
"format" : "html",
"outputDirectory" : "./Report"
}
}
Setting up a report is fairly easy, you just have to define the report.format
, and report.outputDirectory
. We will make use of our ./Report
directory to keep things nice and tidy.
The Listeners
In order to have the Report working, we need to register Athena listeners, this can be done through phpunit.xml
.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<listeners>
<listener class="\Athena\Event\Adapter\PhpUnitAdapter">
<arguments>
<object class="\Athena\Event\Dispatcher\DispatcherLocator"/>
</arguments>
</listener>
</listeners>
<testsuites>
<testsuite name="api">
<directory>./</directory>
</testsuite>
</testsuites>
</phpunit>
Writing a Test
namespace Tests;
use Athena\Test\AthenaAPITestCase;
class HttpBinTest extends AthenaAPITestCase
{
public function testIpEndpoint_PerformGetRequest_ShouldContainOrigin()
{
}
}
At the first glance, it looks fairly standard: A namespace, a parent class and a big self-explanatory method name.
The Namespace
One of the caveats of writing a test in Athena, is the namespace. It should—always—start with—Tests\
.
Internally Athena will map Tests\
to your testing directory.
This behaviour gives you freedom to choose how you organise the directory, where you store your tests.
The Parent Class
Another close look to the code will make our parent class, AthenaAPITestCase
stand-out, and you'll ask yourself what it does, if you didn't, you have now. When building our tests we should—always—include Athena's test cases.
Each type of test is wrapped with a Athena class of it's own, as you can imagine, this introduces custom behaviour when needed. I won't cover here all the types, as the focus is our Browser test case. After completing the guide, I recommend you giving them a—quick—look.
The Method Name Convention
Adopting conventions, in most situations, is a good idea. This keeps things consistent, making it easier to read.
We follow the MethodName_StateUnderTest_ExpectedBehavior
convention. If you are interested in knowing more about it, refer to the Coding Standards page.
Food for though: If you have however spent a lifetime using a different convention, you can always use your own. At the end of the day, it doesn't matter, consistency for the reader is the key. Is what we strive for. Easy and understandable tests.
Performing HTTP Calls
Athena brings a client for HTTP calls, which can be accessed through Athena::api()
. This client provides a fluent interface for not only performing these calls, but also to perform assertions on the response given by the server.
namespace Tests;
use Athena\Athena;
use Athena\Test\AthenaAPITestCase;
class HttpBinTest extends AthenaAPITestCase
{
public function testIpEndpoint_PerformGetRequest_ShouldContainOrigin()
{
$result = Athena::api()
->get('http://httpbin.org/ip')
->then()
->assertThat()
->responseIsJson()
->statusCodeIs(200)
->retrieve()
->fromJson();
$this->assertArrayHasKey('origin', $result);
}
}
The good thing about this fluent interface, is that it's self-explanatory what we want to retrieve and what assertions we are performing.
Execute The Test
Athena runs it's tests through the command line interface, so we'll need to navigate inside Athena's project directory, to access it's executable.
$ athena php api
...
usage: athena php api <tests-directory> <config-file> [<options>...] [(<phpunit-options>|<paratest-options>)...]
<tests-directory> This directory will be mounted inside the docker container. PHPUnit will be executed inside this directory
<config-file> Athena config file, with proxy configurations, grid options, etc
--parallel=<number> Specify the number of jobs to be ran in parallel. In case this options is specified, Paratest will be ran, instead of PHPUnit
--php-version=<version> Switch between available PHP versions. E.g. --php-version=7.0
--override-athena-dependencies Override PHP plugin dependencies with the ones found inside the tests directory
--restore-athena-dependencies Restore PHP plugin original dependencies
Writing athena php api
and hitting enter, will show you the basic usage, on the requirements to run a browser test case. Most likely by now you already know the next steps.
$ athena php api ../myteam-tests ../myteam-tests/athena.json
Once you run that command, if it is your first time running athena, you'll most likely see a lot of input. This is athena setting up it's docker images.
When it's all completed, or you are running the command a second time, after having everything installed, you should see the following:
...
PHPUnit 5.1.7 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 753 ms, Memory: 3.75Mb
OK (1 test, 1 assertion)
Reading The Report
In our configuration file, we've specified Report/
as our output directory for the report file, so that where we will be looking for it.
Open report.html
in your browser, and you should see nice HTML report containing all the steps we took, together with HTTP conversation for each one.
Configure a Proxy
When athena php api
is run, it will try to automatically link with a running Proxy Server (athena proxy start
).
In case --skip-proxy
exists, the link will not be performed.
For performing a link with another running container, you can optionally specify --link-proxy=<container_name>
.
Parallel Tests
$ athena php api my-tests/ my-tests/athena.json --parallel=<number> [<paratest-options>...]
$ athena php api my-tests/ my-tests/athena.json --parallel=2
All Available Options
$ athena php api my-tests/ my-tests/athena.json --parallel --help
...
Usage:
paratest [options] [--] [<path>]
Arguments:
path The path to a directory or file containing tests. (default: current directory)
Options:
-p, --processes=PROCESSES The number of test processes to run. [default: 5]
-f, --functional Run methods instead of suites in separate processes.
--no-test-tokens Disable TEST_TOKEN environment variables. (default: variable is set)
-h, --help Display this help message.
--coverage-clover=COVERAGE-CLOVER Generate code coverage report in Clover XML format.
--coverage-html=COVERAGE-HTML Generate code coverage report in HTML format.
--coverage-php=COVERAGE-PHP Serialize PHP_CodeCoverage object to file.
-m, --max-batch-size=MAX-BATCH-SIZE Max batch size (only for functional mode). [default: 0]
--filter=FILTER Filter (only for functional mode).
--whitelist=WHITELIST Directory to add to the coverage whitelist.
--phpunit=PHPUNIT The PHPUnit binary to execute. (default: vendor/bin/phpunit)
--runner=RUNNER Runner or WrapperRunner. (default: Runner)
--bootstrap=BOOTSTRAP The bootstrap file to be used by PHPUnit.
-c, --configuration=CONFIGURATION The PHPUnit configuration file to use.
-g, --group=GROUP Only runs tests from the specified group(s).
--exclude-group=EXCLUDE-GROUP Don't run tests from the specified group(s).
--stop-on-failure Don't start any more processes after a failure.
--log-junit=LOG-JUNIT Log test execution in JUnit XML format to file.
--colors Displays a colored bar as a test result.
--testsuite[=TESTSUITE] Filter which testsuite to run
--path=PATH An alias for the path argument.
Once the option --parallel is set, under hood paratest will replace phpunit.
Final Thoughts
If you are reading this tutorial is either because you want to use it or you are curious about it. Let—that—guide you into our community, make this project grow, make it better, iterate over it several times and share your ideas and your knowledge, so that you, us, who use this project benefit from it.