phpunit: from zero to hero

36
PHPUNIT From Zero to Hero

Upload: jeremy-cook

Post on 17-May-2015

11.419 views

Category:

Technology


8 download

DESCRIPTION

Slides from talk given at Guelph PHP on February 29th 2012 introducing PHPUnit.

TRANSCRIPT

Page 1: PHPUnit: from zero to hero

PHPUNIT

From Zero to Hero

Page 2: PHPUnit: from zero to hero

WHAT IS UNIT TESTING…

and why is it a Good Thing™?

Page 3: PHPUnit: from zero to hero

“In computer programming, unit testing is a

method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application.” Wikipedia

WHAT IS UNIT TESTING?

Page 4: PHPUnit: from zero to hero

You have a piece of code that everyone is too

terrified to touch. You’re too scared to refactor or change a piece

of code because you can’t predict the impact it will have on your application.

Releases are a complete nightmare. You’ve had to work late or through a weekend

to track down a bug.

HAVE ANY OF THESE EVER APPLIED TO

YOU?

Page 5: PHPUnit: from zero to hero

WRITING TESTS IS HARD, WRITING GOOD TESTS IS EVEN

HARDER…

Page 6: PHPUnit: from zero to hero

A study conducted by Microsoft and IBM showed

writing tests can add 15%-35% to development time but reduce the number of bugs by 40%-90%!

Writing code that is easily testable encourages best practices, such as SOLID principles.

Having a set of unit tests can help you make sure your deployments are painless rather than painful

None of us want to be stuck at work all weekend trying to work out why a code change has broken the whole application.

…BUT WORTHWHILE

Page 7: PHPUnit: from zero to hero

WHAT IS PHPUNIT?

Page 8: PHPUnit: from zero to hero

PHPUnit is a unit testing framework written in

PHP, created by Sebastian Bergman. Part of the xUnit family of testing frameworks. While there are other unit testing frameworks

for PHP (such as SimpleTest or Atoum) PHPUnit has become the de facto standard.

Major frameworks, such as Zend, Symfony and Cake, and many other PHP projects such as Doctrine have test suites written with PHPUnit.

INTRODUCTION TO PHPUNIT

Page 9: PHPUnit: from zero to hero

INSTALLING PHPUNIT

Page 10: PHPUnit: from zero to hero

Minimum requirement is PHP 5.2.7 but 5.3.X is

recommended. If you want code coverage analysis (you do!)

you need to install the PECL xDebug extension.

Best installed via the PEAR installer so you need to have run the pear installation.

REQUIREMENTS

Page 11: PHPUnit: from zero to hero

If installing via PEAR you need two commands

to get up and running:

Full installation instructions (including other optional PHPUnit modules) can be found at http://www.phpunit.de/manual/3.6/en/installation.html

INSTALLING VIA PEAR

Page 12: PHPUnit: from zero to hero

WRITING TESTS

Page 13: PHPUnit: from zero to hero

The general aim is to make sure every

possible path through your code is exercised at least once in a test.

This means you need to write tests that exercise error conditions too.

Rule of thumb: one test method per expected outcome per method tested.

Have descriptive test method names. Name the test class after the class being

tested.

TEST WRITING BEST PRACTICES

Page 14: PHPUnit: from zero to hero

Simply add ‘require_once PHPUnit/Autoload.php’ to each test file. A PHPUnit test is a class that (usually) extends

PHPUnit_Framework_TestCase. The class name should end with the word ‘Test’, e.g. ‘FooBarTest’. Each test class should be in its own file named after the class,

e.g. ‘FooBarTest.php’. Each test method name must begin with the word ‘test’, e.g.

‘testSomethingWorks’ or have an @test annotation. Test methods must be public. The class must contain one or more methods that perform tests

or the test case will fail. A test method must contain one or more assertions, be marked

as incomplete or skipped.

TEST BASICS

Page 15: PHPUnit: from zero to hero

A fixture in a test is something (usually an object) that

you want to test. Also known as System Under Test (SUT). PHPUnit will set up fixtures for you if you add protected

methods setUp and optionally tearDown in your test class. You provide code to create/destroy fixtures in these

methods. These methods are called before and after each test

method so that each test runs on fresh fixtures. setUpBeforeClass and tearDownAfterClass are also

available. These are run once at the beginning and end of the test class.

TEST FIXTURES

Page 16: PHPUnit: from zero to hero

Assertions are used to test expected

behaviour from your SUT. PHPUnit provides many different assertions for

all sorts of needs, e.g. assertEquals, assertEmpty, assertTrue, assertType, etc.

You can also test output using expectOutputString.

More complicated assertions can be constructed using assertThat.

For a test to pass all assertions must evaluate to true.

WRITING ASSERTIONS

Page 17: PHPUnit: from zero to hero

PHPUnit supports annotations to give

instructions to the test method being executed.

Annotations are included in block comments before the method and always begin with an ‘@’.

Examples: @depends, @expectedException, @dataProvider.

Full details on supported annotations at http://www.phpunit.de/manual/3.6/en/appendixes.annotations.html

ANNOTATIONS

Page 18: PHPUnit: from zero to hero

A data provider is a method that returns an

array of values to use in a test. PHPUnit will call the related test method once

for each set of data, passing the values as arguments to the method.

Set using the @dataProvider annotation. Allows you to easily add extra values to test

with. Also makes tests shorter and more concise by

keeping values to test with out of test methods.

DATA PROVIDERS

Page 19: PHPUnit: from zero to hero

You can tell PHPUnit that a test should expect an

exception. This can be done in two ways:

Through the method setExpectedException($exception, $message = ‘’, $code = null)

Through @expectedException, @expectedExceptionMessage, @expectedExceptionCode annotations.

PHP errors such as warnings are converted into exceptions by PHPUnit. These can also be tested for.

TESTING EXCEPTIONS

Page 20: PHPUnit: from zero to hero

MOCK OBJECTS

One of the most powerful features of PHPUnit.

Page 21: PHPUnit: from zero to hero

Allows you to replace a dependency of your SUT with

an object that has predefined behaviour. The mock object becomes part of the test. If the

methods defined are not called as expected the test fails.

Proper use of mock objects allow you to make sure you’re only testing the SUT and not other code.

Helps to ensure that if a test fails it’s in the SUT, not a dependency.

However, you need to be using Dependency Injection to use mock objects.

WTF IS A MOCK OBJECT?

Page 22: PHPUnit: from zero to hero

PHPUnit creates a mock by sub-classing the

original object. Once you have a mock object you can define

what methods you expect to be called on it, with what arguments and what the mock should do.

MOCK OBJECT BASICS

Page 23: PHPUnit: from zero to hero

Mock objects allow you to test concrete

methods of abstract classes with getMockForAbstractClass.

You can create a mock object representing a SOAP web service using getMockFromWsdl.

PHPUnit has experimental support for mocking out file system calls using the package vfsStream.

More information at http://www.phpunit.de/manual/3.6/en/test-doubles.html.

OTHER MOCK OBJECT USES

Page 24: PHPUnit: from zero to hero

RUNNING TESTS

Page 25: PHPUnit: from zero to hero

Tests are normally run from the command line with

the phpunit command. Just typing phpunit will get a ‘help’ output. Passing the name of the test will run just that test. You can also pass a path to a directory to run all tests

in it or the name of a test file to run tests in that file. PHPUnit prints a ‘.’ for each test passed, ‘F’ for a

failure, ‘E’ for an error, ‘I’ for incomplete or ‘S’ for skipped.

More information is also printed for anything other than a pass.

COMMAND LINE RUNNER

Page 26: PHPUnit: from zero to hero

SAMPLE COMMAND LINE OUTPUT

Page 27: PHPUnit: from zero to hero

Many IDE’s such as Zend Studio include

PHPUnit integration. This enables you to write and run tests from within the IDE.

Running tests can be integrated into continuous integration servers such as Jenkins.

In this case your full test suite can be run automatically with each edit to your code.

Any test failure will mean the build fails.

OTHER WAYS TO RUN TESTS

Page 28: PHPUnit: from zero to hero

CODE COVERAGE ANALYSIS…

or how to make sure you’re not feeling a false sense of security.

Page 29: PHPUnit: from zero to hero

Code coverage tells you how much of your code is

covered by tests. PHPUnit can generate code coverage reports in a

number of formats including HTML but… You must have installed xDebug. (pecl install

xdebug) Helps to avoid a false sense of security. Code coverage threshold percentage can be added

to continuous integration builds. Add code coverage by passing the –coverage-xxx

option, eg. phpunit –coverage-html ./reports ./

WTF IS CODE COVERAGE?

Page 30: PHPUnit: from zero to hero

PHPUNIT TEST EXTENSIONS

Writing tests for different situations.

Page 31: PHPUnit: from zero to hero

PHPUnit supports a number of extensions that

allow you to write specialised tests. These include working with databases,

Selenium, and running profiling with XHProf. Full details at http://

www.phpunit.de/manual/3.6/en/installation.html.

INTRO TO EXTENSIONS

Page 32: PHPUnit: from zero to hero

TESTING WITH DATABASES

To do this install the DbUnit extension, eg. ‘pear install phpunit/DbUnit’

However, where possible avoid tests using a database by using mock objects.

Test case must extend ‘PHPUnit_Extensions_Database_TestCase’.

Defines two extra methods that you must implement: getConnection and getDataSet.

You need to provide a schema with tables for PHPUnit to use.

getConnection must return a PDO instance for PHPUnit to use.

getDataSet returns data to populate database tables with.

PHPUnit truncates tables before each test run and inserts data. This means each test runs with a fresh set of predictable data.

Page 33: PHPUnit: from zero to hero

PHPUNIT CONFIG

Page 34: PHPUnit: from zero to hero

Options can be passed to PHPUnit through the command

line but it also supports adding an XML config file. This can include a number of options such as where to

find test cases and which directories to include for code coverage analysis.

To use this just create the file and name it phpunit.xml, adding it to the root of your tests directory.

Especially useful when running tests as part of a CI build. Full details at

http://www.phpunit.de/manual/3.6/en/appendixes.configuration.html

ADDING A CONFIG FILE

Page 35: PHPUnit: from zero to hero

LET’S WRITE SOME TESTS!

Page 36: PHPUnit: from zero to hero

QUESTIONS?