Php Testing
PHP Testing#
A catastrophic failure is usually the indicator that you should be using automated testing
TDD Test driven development#
- Write a test for a small module of code
- Write the code to pass the test
- Repeat until you have a test for every unit of code
The tests are just an outcome of TDD as a design pattern
Little building blocks
Types of Tests#
Unit Tests#
Verify individual modules of code run correctly
- small
- run quickly
- don’t talk to real things (Don’t talk to API and db)
Long tests means more likely tests will not be run
Integration Tests#
Verifying all individual blocks fit together
- slow
- units of code talk to each other
- talk to real things
Need to refresh test server with decent data
Functional Tests#
Verify application is behaving correctly
- very slow
- Not all tests can be automated
Only write for parts of the website that are mission critical
Testing Tools#
You should always use phpunit
for unit tests
First test: assertTrue(false)
In php: $this->assertTrue(false);
PHP Unit#
It won’t write your tests for you
Tests can be automated
Is flexible in how you organise tests
It isn’t going anywhere
Great for documenting and finding out what code is and what it isn’t
Installing PHPUnit#
- packagist: Repo of PHP packages
- composer: Managing packages for PHP project
composer require phpunit/phpunit
Global state and preserved for entire length of request, so in same scope it persists.
Configuration#
phpunit.xml
:
<phpunit processIsolation="false">
<testsuites>
<testsuite name="Foo">
<directory>tests/unit</directory>
</testsuite>
</testsuites>
</phpunit>
Can organise into test suites
Change test runner#
Change printerFile
and printerClass
because the default test runner is pretty bland
Working with frameworks#
It uses a front controller
method, which sets up stuff.
To write tests for this you need to set up environments
So use the bootstrap
node which tells phpunit to load this file before running tests
Writing a test#
What needs to be tested#
- Every conditional statement needs at least 1 test
- You will need to refactor code for your tests to run - remove conditional dependencies
Mockery makes it easier to make duplicate calls than built in PHPunit mocks
Another good tool is HTML purifier which can be used to strip out unwanted characters
PDO objects have some functionality internally that PHP’s Reflection API doesn’t handle properly so the built-in test double features of PHPUnit can’t create doubles of them
Princliples#
- Every testcase has at least 1 assertion
Explicit is better than implicit, so multiple assertions are probably the best way to go
Acceptance Tests#
Unit tests - inidividual modules of code working in the way you expect, using dependencies and doubles for a consistent state.
Acceptance tests - Ensure individual modules of code are speaking to each other correctly a.k.a integration tests, no need to worry about test doubles.
Data Provider#
Making multiple assertions can be done with the use of a DataProvider
DB Unit Tests#
Thou shalt not use a real database, and create test doubles
Fast running tests that work even if database is not there
On the other hand there are those that advocate using DB_unit
that requires a live database to run tests
A tool that phpunit can use to create database connections
Need to extend from a different test class:
PHPUnit_Extensions_Database_Testcase
2 methods have to be implemented: getConnection()
and getDataSet()
A dataset.xml
is imported but there is a caveat for null
values
If you are using db_unit
you won’t be using mocks
DB Unit will delete everything before adding data from seed files
Unit tests are not supposed to talk to databases or 3rd party, use test doubles as standins.