API Testing with
CodeCeption
What is this?
"Codeception collects and shares best practices and solutions for testing PHP web applications. With a flexible set of included modules tests are easy to write, easy to use and easy to maintain. Codeception encourages developers and QA engineers to concentrate on testing and not on building test suite."
What is more then PHPUnit?
- User Centric Tests
- Browser Testing
- Framework Testing
- Unit and Integration Testing
- Behavior Driven Development
- AspectMock
- API Testing
Features


Structure

User Centric Test
Codeception provides high-level domain language for tests. Tests are represented as a set of user's actions.
$I->amOnPage('/'); ⇒ I am on page '/'
$I->click('Enter'); ⇒ I click 'Enter'
$I->see('Welcome'); ⇒ I see 'Welcome'Browser Testing
Tests can be executed using Firefox, Chrome, PhantomJS or Cloud Testing services with Selenium WebDriver. Browser can be emulated with HTTP-requests through CURL with PhpBrowser.
$I->amOnPage('/login');
$I->fillField('username', 'davert');
$I->fillField('password', 'qwerty');
$I->click('LOGIN');
$I->see('Welcome, Davert!');Framework Testing
Tests can be executed inside a PHP framework. This way web application can be executed without web server to running faster and accessing application internals. Silex, Symfony, Laravel, Zend, Yii, Phalcon are supported.
modules:
enabled:
- Silex:
app: 'app/bootstrap.php'
<?php
$app = require __DIR__.'/path/to/app.php';
$app['debug'] = true;
unset($app['exception_handler']);
return $app; // optionallyBehavior Driven Development
BDD is aimed to establish one language between development, QA, and business teams. Codeception can execute feature files written in Gherkin format as tests.
Feature: checkout process
In order to buy products
As a customer
I want to be able to buy several products
Scenario:
Given I have product with $600 price in my cart
And I have product with $1000 price
When I go to checkout process
Then I should see that total number of products is 2
And my order amount is $1600Unit and Integration Testing
Codeception is built on top of PHPUnit and is able to execute its tests. Integration tests can be improved with commands for database interactions.
<?php
class UserTest extends \Codeception\Test\Unit
{
public function testValidation()
{
$user = User::create();
$user->username = null;
$this->assertFalse($user->validate(['username']));
}
}
....AspectMock mocking framework
With the power of Aspect Oriented programming and the awesome Go-AOP library, AspectMock allows you to stub and mock practically anything in your PHP code!
$ar = test::double('ActiveRecord', ['save' => null]);
$user = new User;
$user->name = 'davert';
$user->save(); // passes to ActiveRecord->save() and does not insert any SQL.
$ar->verifyInvoked('save'); // true
--------------
namespace demo;
test::func('demo', 'time', 'now');
$this->assertEquals('now', time());
API Testing
Codeception simplifies REST and SOAP testing. There are flexible commands to test structure and data of JSON and XML responses. Testing can be done over HTTP or inside a framework.
$I->haveHttpHeader('X-Requested-With', 'Codeception');
$I->sendGET('test-headers.php');
$I->seeResponseCodeIs(200);
$I->seeResponseContainsJson(array('name' => 'john'));
$I->seeResponseJsonMatchesJsonPath('$.store.book[*].author');
...
$I->deleteHeader('X-Requested-With');
$I->sendPOST('some-other-page.php');First steps: install and generate
// install
composer require "codeception/codeception" --dev
// create test project path with helpers
codecept bootstrap
// generate first test
codecept generate:cest acceptance First
// acceptance.suite.yml:
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost
- \Helper\Acceptance
// first test
<?php
class FirstCest
{
public function frontpageWorks(AcceptanceTester $I)
{
$I->amOnPage('/');
$I->see('Home');
}
}
Run it
Generate API test

REST Testing
// api.suite.yml
actor: ApiTester
modules:
enabled:
- REST:
url: http://serviceapp/api/v1/
depends: PhpBrowser
part: Json
// generate test
codecept generate:cept api CreateUser
// write a test
<?php
$I = new ApiTester($scenario);
$I->wantTo('create a user via API');
$I->amHttpAuthenticated('service_user', '123456');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST('/users', ['name' => 'davert', 'email' => 'davert@codeception.com']);
$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
$I->seeResponseIsJson();
$I->seeResponseContains('{"result":"ok"}');
$I->seeResponseContainsJson(['result' => 'ok']);
$I->seeResponseJsonMatchesJsonPath('$[0].user.login');
$I->seeResponseJsonMatchesXpath('//user/login');
Acceptance Testing
$I = new FunctionalTester($scenario);
$I->wantTo('create wiki page');
$I->amOnPage('/');
$I->click('Pages');
$I->click('New');
$I->wait(3); // wait for 3 secs
$I->see('New Page');
$I->submitForm('form#new_page', array('title' => 'Tree of Life Movie Review','body' => "Next time don't let Hollywood create art-house!"));
$I->see('page created'); // notice generated
$I->see('Tree of Life Movie Review','h1'); // head of page of is our title
$I->seeInCurrentUrl('pages/tree-of-life-movie-review'); // slug is generated
$I->seeInDatabase('pages', array('title' => 'Tree of Life Movie Review')); // data is stored in databaseSOAP Testing
// soap.suite.yml
actor: ApiTester
modules:
enabled:
- SOAP:
depends: PhpBrowser
endpoint: http://serviceapp/api/v1/
<?php
$I->haveSoapHeader('Auth', array('username' => 'Miles', 'password' => '123456'));
<soap:Header>
<Auth>
<username>Miles</username>
<password>123456</password>
</Auth>
</soap:Header>
<?php
$I->sendSoapRequest('CreateUser', '<name>Miles Davis</name><email>miles@davis.com</email>');
<soap:Body>
<ns:CreateUser>
<name>Miles Davis</name>
<email>miles@davis.com</email>
</ns:CreateUser>
</soap:Body>
<?php
$I->seeSoapResponseEquals('<?xml version="1.0"<error>500</error>');
$I->seeSoapResponseIncludes('<result>1</result>');
$I->seeSoapResponseContainsStructure('<user><name></name><email></email>');
$I->seeSoapResponseContainsXPath('//result/user/name[@id=1]');
<?php
use \Codeception\Util\Xml;
$I = new ApiTester($scenario);
$I->wantTo('create user');
$I->haveSoapHeader('Session', array('token' => '123456'));
$I->sendSoapRequest('CreateUser', Xml::build()
->user->email->val('miles@davis.com'));
$I->seeSoapResponseIncludes(Xml::build()
->result->val('Ok')
->user->attr('id', 1)
);
<?php
namespace Helper;
class Api extends \Codeception\Module {
public function seeResponseIsValidOnSchema($schema)
{
$response = $this->getModule('SOAP')->response;
$this->assertTrue($response->schemaValidate($schema));
}
}Köszönöm a figyelmet!
http://codeception.com/
API tesztelés Codeception-ben
By Zoltán Virág
API tesztelés Codeception-ben
- 97