php tests tips

20

Click here to load reader

Upload: damiansromek

Post on 17-May-2015

3.835 views

Category:

Technology


1 download

DESCRIPTION

Few

TRANSCRIPT

Page 1: Php tests tips

PHP Tests tips How not to shoot yourself in the foot?

Damian Sromekdamiansromek.pl

2012-06

Page 2: Php tests tips

Agenda

● What's about those tests?● What are the tests about?● What to do and not to do?

Page 3: Php tests tips

Test types

1. Acceptance (end-to-end)Test as if end user would use the whole system/feature.

2. IntegrationTest how different parts of system work together - eg. couple of classes or your class using some web service

3. UnitTest single unit (eg. class). Mock all dependencies, eg. web service, file system.

Page 4: Php tests tips

Tests will save you time & troubles

1. Prove you've done your work2. Help you check much faster if you're work is

done3. Protect you from breaking things - regresion4. Help you make better code design - easier to

maintain5. Let you apply changes with less worries -

refactoring will improve things without breaking anything

Page 5: Php tests tips

How to be happy about tests?

1. If you're new to testing try with writing tests after writing the code

2. Once you're confident about testing try to write tests before the code - TDD

3. Start with acceptance tests, than integration and unit tests when your functionality is implemented

4. Run tests often - after every change and before any commit

5. Use continuous integration server

Page 6: Php tests tips

You will regret you've got a lot of tests if you:

1. make them complex and hard to read2. duplicate the test code3. do not use descriptive fail messages4. do not run them often - eg. you don't have

continuous integration server 5. do not make them run fast

Page 7: Php tests tips

Behavioral tests

Draft - Behat Feature: Log in and use the application In order to use the application As a user I need to log in using my smart card

@javascriptScenario: Log in with inactive smart card Given I am inactive smart card user Given I am on "http://localhost/somethign.cool.php" When I log in Then I should see log in error message

Page 8: Php tests tips

What's good test like?

1. Finds as much bugs as possible2. Tells you what the software can do and how

to use it3. Is easy to maintain4. Independent from other tests and repeatable

Page 9: Php tests tips

How to start testing?

1. Write acceptance test for functionality you're implementing - it should cover main story flow

2. Make the test show meaningful fail message3. Implement functionality so the test is passing4. Add tests covering more story flows5. Improve functionality code so all tests are

passing again6. Refactor (also tests)7. Enjoy!

Page 10: Php tests tips

How to start even better?

1. "Wait" for a bug2. Write a test confirming/reproducing that bug3. Fix the code using the test you've got4. Enjoy!

Page 11: Php tests tips

TDD flow

Repeat this process1. Write test2. Make test failure message descriptive and

easy to understand3. Make the test pass - implement feature

you've write the test for4. Refactor

Page 12: Php tests tips

Do not - test something irrelevant<?php // SHOULD TEST PLUGIN BUT IS TESTING DATABASE MODEL AND NOTHING MORE class Plugin_Smooth_Streaming_BoundariesTest extends TestCase_Plugin{ ... public function testLowerBoundary() { $settings = Xstream_Loader::getModelHelper("SettingHelper"); $lowerLimit = $settings->setSetting('plugin_boundaries', 'lower_limit',1.0); $this->assertEquals(1.0, $settings->getSetting('plugin_boundaries', 'lower_limit')->value); } ... }

Page 13: Php tests tips

Do not - test too much at once<?php// TRY NOT TO MAKE MORE THAN 2-3 ASSERTIONS IN ONE TESTclass ResponseSetTest extends PHPUnit_Framework_TestCase

{

...

public function testAddItems()

{

$responseSet = new Xs_Monitor_Response_Set('test');

$this->assertEquals(Xs_Monitor_Interface::STATE_WARNING, $responseSet->getStateAsInteger());

$responseSet->addResponse(new Xs_Monitor_Response('service 1', Xs_Monitor_Interface::STATE_OK, 'detail of service 1'));

$this->assertEquals(Xs_Monitor_Interface::STATE_OK, $responseSet->getStateAsInteger());

$this->assertNotEquals('detail of service 1', $responseSet->getDetails());

$responseSet->addResponse(new Xs_Monitor_Response('service 2', 3, 'detail of service 2'));

$this->assertEquals(3, $responseSet->getStateAsInteger());

$this->assertEquals('UNKNOWN', $responseSet->getState());

$this->assertEquals('detail of service 2', $responseSet->getDetails());

$responseSet

->addResponse(new Xs_Monitor_Response('service 3', Xs_Monitor_Interface::STATE_WARNING, 'detail of service 3'));

$this->assertEquals(Xs_Monitor_Interface::STATE_WARNING, $responseSet->getStateAsInteger());

$this->assertEquals('detail of service 3', $responseSet->getDetails());

$responseSet

->addResponse(new Xs_Monitor_Response('service 4', Xs_Monitor_Interface::STATE_CRITICAL, 'detail of service 4'));

$this->assertEquals(Xs_Monitor_Interface::STATE_CRITICAL, $responseSet->getStateAsInteger());

$this->assertEquals('detail of service 4', $responseSet->getDetails());

$responseSet

->addResponse(new Xs_Monitor_Response('service 5', Xs_Monitor_Interface::STATE_CRITICAL, 'detail of service 5'));

$this->assertEquals(Xs_Monitor_Interface::STATE_CRITICAL, $responseSet->getStateAsInteger());

$this->assertEquals('detail of service 4', $responseSet->getDetails());

$responseSet

->addResponse(new Xs_Monitor_Response('service 6', Xs_Monitor_Interface::STATE_WARNING, 'detail of service 6'));

$this->assertEquals(Xs_Monitor_Interface::STATE_CRITICAL, $responseSet->getStateAsInteger());

$this->assertEquals('detail of service 4', $responseSet->getDetails());

return $responseSet;

}

Page 14: Php tests tips

Do - use meaningful test name

Test name should be descriptive even if it has very long name.Try to avoid test names like "testAdd" etc.Better would be something like "testAddWillPutNewItemIntoContainer" or "testAddWillThrowExceptionIfContainerIsFull" /** * @test */

public function add() { ...

Page 15: Php tests tips

Do - use data providers<?php

namespace Xs\Test\Unit;

class StringTest extends TestCase

{

/** * @param string $heystack * @param string $needle * @param boolean $expected * * @dataProvider endsWithDataProvider */

public function testEndsWith($heystack, $needle, $expected)

{

$this->assertEquals($expected, \Xs\String::endsWith($heystack, $needle));

}

public function endsWithDataProvider()

{ return array( array('asdf', 'f', true), array('asdf', 'df', true), array('asdf', 'asdf', true), array('asdf', 'd', false), array('asdf', 'xf', false), array('asdf', 'asd', false), ); }

}

Page 16: Php tests tips

Do - test one unit in unit test

Unit test should NOT:1. Test more than one unit/class2. Touch database, filesystem,

API/WebService etc. - you should mock all "externals"

3. Execute very fast - matter of 10th of second

Page 17: Php tests tips

Do - make tests easy to read and understandclass Acceptance_Product_ProductListTest extends Test_TestCase{ public function testReturnsErrorAboutNoProductsUserCanBuyWhenHeHasNoProductsRelatedToMedia() { $this->user() ->logIn() ->withoutProducts(array( $this->svodProductId, $this->premiumSvodProductId )) ->withoutOrderedMedia($this->mediaId); $this->shop()->respondsJsonAboutNoProductsAvailable($this->mediaId);

}

Page 18: Php tests tips

Do - make tests easy to read and understand (2)

Draftclass SortingTest extends \Xs\CanalDigital\Test\Stb\Adb\TestCase

{

/** * @test */

public function mediaListWithoutFixedSortingCanBeSortedByPressingRedButton()

{

$this->user()

->onPage($this->stbApp()->page('sort_fixed'));

$initialAppState = $this->stbApp()->getState('maincovers');

$this->user()->pressedButton(Key::BUTTON_RED); $appStateAfterPressingRedButton = $this->stbApp()->getState('maincovers'); // TODO: better way of comparing items sorting $this->assertNotEquals( $initialAppState, $appStateAfterPressingRedButton, 'Pressing red button should change page sorting' );

}

Page 19: Php tests tips

Summary

1. Use TDD2. Unit tests should test what you've written /

proper unit and nothing more3. Do not test too much in one test4. Make your tests easy to maintain - proper

naming etc.5. Try to use data provider to test a lot of

different cases without code duplication

Page 20: Php tests tips

Thank you

@see Test Driven Development@see PHPUnit@see Behavioral Driven Development@see Behat @see Growing Object-Oriented Software, Guided by Tests@see www.jenkins-ci.org