PHPSerbia 2017
Michael Bodnarchuk
BEYOND TESTING
Hi, I am Michael @davert
and I have stickers!
Codeception
http://codeception.com
Testing
Better way to do it
Ideal Test
DON'T DO IT THIS WAY
move to configuration
use traits
IMPLEMENT YOUR OWN ASSERTIONS
custom assertions make code more readable
SIMPLIFY IT!

How to Write Unit / Integration Test
Unit vs Integration Tests
Questions to be Asked
Testing Levels
Know Pros and Cons
Stability to Changes | Wide Coverage | Invest into Infrastructure | Speed of Development |
Stability of Execution | Detailed Coverage | Invest into Architecture | Speed of Execution |
Specification
Detail
TDD Process
Every app can be tested!
What is Hard to Test
Beyond Testing
what they never tell you about testing
Data Management
for integration / functional / acceptance
Accessing Database
Data Isolation Strategies
Defining Test Data With
FACTORY_MUFFIN IN REAL LIFE
$fm->define(User::class)->setDefinitions([
'name' => Faker::name(),
'email' => Faker::email(),
'body' => Faker::text(),
// generate a profile and return its Id
'profile_id' => 'factory|Profile'
);
Testing APIs
REST APIs
How To Test JSON Responses
GET /tickets/3
{� "ticket": {� "id": 3,� "from": "web",� "description": "Lorem ipsum...",� "priority": "important",� "priority_value": 1,� "report": {� "user_agent": "Mozilla...",� "url": "/tasks", � "window": "1280x525",� "resolution": "1600x1200"� },� "reporter_info": {� "name": "davert",� "email": "davert@codeception.com",� }� "created_at": "2016-08-21T20:16:37Z",� "updated_at": "2016-09-11T15:13:47Z" � }�}
How we test in Codeception: Data Inclusion
$I->wantTo('get a ticket by its id');
$I->sendGET('/api/tickets/3');
$I->seeResponseCodeIs(HttpCode::OK); // 200
$I->seeResponseIsJson();
// check data in response
$I->seeResponseContainsJson([
'ticket' =>
'id' => 3,
'from' => 'web'
'report' => [
'url' => '/tasks'
]]);
How we test in Codeception: Structure Inclusion
// check the structure of response
$I->seeResponseMatchesJsonType([
'ticket' => [
'id' => 'integer',
'description' => 'string|null',
'priority' => 'string',
'created_at' => 'string:date',
'reporter_info' => [
'email' => 'string:email'
]]]);
How we test in Codeception: Schema Check
$I->sendGET('/api/tickets/3');
// use custom helper
$I->seeResponseMatchesSwaggerSchema('ticket');
Mocking APIs
WEB UI Testing
why it is important for developers
How Developers can Improve Acceptance Testing
HINT: add locator classes or data-attributes to HTML elements
Choose The Right Tool
Atomic Acceptance Tests with Data Management
Feature: CRUD for Post
Scenario:
When I create a post
And I open a post
And I edit a post
Then I see it has changed
Then I delete a post
Feature: CRUD for Post
Scenario: create a post
Scenario: view post
Scenario: edit a post
Scenario: delete a post
POST is created via API for each test which requires it
One Post for everything :(
Parallel Testing
one day tests started to be slow
PARALLEL TESTING
SET IT UP
HOW TO RUN PARALLEL TESTS WITH DOCKER
What’s inside the container?
#!/bin/sh
echo "Starting Services...."
service elasticsearch start > /dev/null 2>&1
service nginx start > /dev/null 2>&1
service php5-fpm start > /dev/null 2>&1
service mysql start > /dev/null 2>&1
phantomjs --webdriver=4444 > /dev/null 2>&1 &
mailcatcher -f > /dev/null 2>&1 &
echo "Running tests"
cd /project/$1 # switch to application
codecept run $2 # run tests from specific suite
docker run -it -v $WORKSPACE:/project app ./runtests.sh $SUITE
Conclusions
Constantly improve code by refactoring!
It is safe to do this with tests.
TIME FOR QUESTIONS!