automated tests - facts and myths

61
Automated tests Facts and myths / Wojciech Sznapka @sznapka

Upload: wojciech-sznapka

Post on 19-May-2015

342 views

Category:

Technology


0 download

DESCRIPTION

The discussion on automated tests is hot topic. The approach has same number of advocates and skeptics. More and more tools eases testing, but also introduces a fundamental question: what, when and how to test? Practise and experience let's answer those questions or guide in the right direction. In this talk usage examples of unit, functional and behavioral tests will be shown. Importance of properly handling dependencies and mocking them will be discussed as well. But most of important part will be hints on how to write code, that could be tested automaticaly. Slides are available in interactive mode here: http://tdd.sznapka.pl/

TRANSCRIPT

Page 1: Automated tests - facts and myths

Automated testsFacts and myths

/ Wojciech Sznapka @sznapka

Page 2: Automated tests - facts and myths

Cześć

Page 3: Automated tests - facts and myths

An introductionI work in software industry for about 9 yearsCare a lot about robust and testable architecturesLoves software craftsmanship, sophisticated architectures, Big Dataand ice hockey

Page 4: Automated tests - facts and myths

Test DrivenDevelopment

What is this?

Page 5: Automated tests - facts and myths

Add a test

Page 6: Automated tests - facts and myths

Write an implementation

Page 7: Automated tests - facts and myths

Refactor code

Page 8: Automated tests - facts and myths

Repeat!

Page 9: Automated tests - facts and myths

What'simportant here?

Page 10: Automated tests - facts and myths

... to have tests

Page 11: Automated tests - facts and myths

You won’t go to hell if you’llwrite a test after declaring an

interface or prototyping aclass ...

Page 12: Automated tests - facts and myths

... but you’ll surely end up inhell, if there won’t be a test

coverage

Page 13: Automated tests - facts and myths

Myths aboutautomated tests

Page 14: Automated tests - facts and myths

Boss doesn't payfor automated tests

Page 15: Automated tests - facts and myths

It's a myth!A 2005 study found that using TDD meant writingmore tests and, in turn, programmers who wrote

more tests tended to be more productiveby American Scientists

Page 16: Automated tests - facts and myths

But this ain't that hard ...class RomanConverter{ protected $conversions = [ 1000 => 'M', 900 => 'CM', 500 => 'D', 400 => 'CD', 100 => 'C', 90 => 'XC', 50 => 'L', 40 => 'XL', 10 => 'X', 9 => 'IX', 5 => 'V', 4 => 'IV', 1 => 'I'];

public function convert($inArabic) { if (!is_numeric($inArabic)) { throw new \InvalidArgumentException('I convert numerics'); } if ($inArabic <= 0) { return ''; } list ($arabic, $roman) = $this->conversionFactorFor($inArabic);

return $roman . $this->convert($inArabic - $arabic); }

protected function conversionFactorFor($inArabic) { foreach ($this->conversions as $arabic => $roman) { if ($arabic <= $inArabic) { return [$arabic, $roman]; } } }}

Page 17: Automated tests - facts and myths

... start from obvious thingsclass RomanConverterTest extends PHPUnit_Framework_TestCase{ public function testEmpty() { $this->assertEquals('', (new RomanConverter)->convert('')); }}

Page 18: Automated tests - facts and myths

... provide some meat ...class RomanConverterTest extends PHPUnit_Framework_TestCase{ /** @dataProvider provideTestData */ public function testConversions($arabic, $roman) { $converter = new RomanConverter(); $this->assertEquals($roman, $converter->convert($arabic)); }

public function provideTestData() { return array[ [3497, 'MMMCDXCVII'], [1, 'I'], [2, 'II'], [6, 'VI'], [9, 'IX'], [40, 'XL'], [45, 'XLV'], [90, 'XC'], [100, 'C'], [400, 'CD'] ]; }}

Page 19: Automated tests - facts and myths

... test edge casesclass RomanConverterTest extends PHPUnit_Framework_TestCase{ /** @expectedException \InvalidArgumentException */ public function testEmpty() { (new RomanConverter)->convert('wtf I am passing here')); }}

Page 20: Automated tests - facts and myths

Help yourself with tests generationphpunit-skelgen --test RomanConverter

Page 21: Automated tests - facts and myths

... or using Symfony'sXSolveUnitSkelgenBundle

./app/console xsolve:skelgen:test Acme/ExampleBundle/Service/.

./app/console xsolve:skelgen:test Acme/*/Controller/*

Page 22: Automated tests - facts and myths

We are buildingtoo complicated

systemfor an automated tests

Page 23: Automated tests - facts and myths

TDD forces you to writecleaner code

Page 24: Automated tests - facts and myths

It's easier to test smaller unitsof code

Page 25: Automated tests - facts and myths

so you write smaller classeswhich are less coupledand that makes your system more stableand open for an extension in the future

Page 26: Automated tests - facts and myths

Your Object Oriented designbecomes S.O.L.I.D. compilant

and this is awesome!

Page 27: Automated tests - facts and myths

You will of course tacklecostly dependencies

Page 28: Automated tests - facts and myths

Use PHPUnit's mockframework or Mockery

Page 29: Automated tests - facts and myths

Fake it till you make itclass MockedTest extends PHPUnit_Framework_TestCase{ public function testNonExistingValueObjects() { $configuration = \Mockery::mock('\ConfigurationValueObject', [ 'getUrl' => 'http://tdd.sznapka.pl', 'getFormat' => 'xml']); $this->assertEquals('xml', $configuration->getFormat()); // OK }}

Page 30: Automated tests - facts and myths

Mock thingsthat can't be tested quickly or non-

reproducableclass MockedTest extends PHPUnit_Framework_TestCase{ public function testApiCalls() { $buzzMock= \Mockery::mock('\Buzz\Browser'); $buzzMock->shouldReceive('get') ->andReturn('<response><mood>Awesomity</mood></response>');

// this also is wise solution, to write xml fixtures in file // $buzzMock->shouldReceive('get')->once() // ->andReturn(file_get_contents(__DIR__ . '/fixtures.xml'));

$api = new \ApiConsumer($buzzMock); $api->assertEquals('Awesomity', $api->getCurrentMood()); // OK }}

Page 31: Automated tests - facts and myths

Expect declared behaviorsclass MockedTest extends PHPUnit_Framework_TestCase{ public function testExpectationsDeclarations() { $buzzMock= \Mockery::mock('\Buzz\Browser'); $buzzMock->shouldReceive('get') ->andReturn('<response><mood>Awesomity</mood></response>');

$loggerMock = \Mockery::mock('\Monolog\Logger'); // we just want to be sure that Logger::info was called only once $loggerMock->shouldReceive('info')->once();

$api = new \ApiConsumer($buzzMock, $loggerMock); $api->assertEquals('Awesomity', $api->getCurrentMood()); // OK }}

Page 32: Automated tests - facts and myths

Be prepared for failuresand check if you prepared for unexpected situations

class MockedTest extends PHPUnit_Framework_TestCase{ /** @expectedException \MyExceptionWrapper */ public function testFailedConnection() { $buzzMock= \Mockery::mock('\Buzz\Browser'); $buzzMock->shouldReceive('get') ->andThrow('\Buzz\Exception\ClientException');

$loggerMock = \Mockery::mock('\Monolog\Logger'); $loggerMock->shouldReceive('info')->never(); $loggerMock->shouldReceive('err')->once();

(new \ApiConsumer($buzzMock, $loggerMock))->getCurrentMood(); }}

Page 33: Automated tests - facts and myths

We providingAPI for external

consumersit can't be tested...

Page 34: Automated tests - facts and myths

Use Symfony's WebTestCaseto test your API

I call it integration tests

Page 35: Automated tests - facts and myths

Call your API and check if itreturns prepared data

class ExpenditureControllerTest extends WebTestCase{ use IsolatedTestsTrait; // it resets test environment

public function testGetListInJson() { $client = static::createClient(); $client->request('GET', '/expenditures.json'); $json = json_decode($client->getResponse()->getContent());

$this->assertTrue($client->getResponse()->isSuccessful()); $this->assertCount(80, $json); $this->assertGreaterThanOrEqual( new \DateTime($json[79]->created_at), new \DateTime($json[0]->created_at)); }}

Page 36: Automated tests - facts and myths

Use fixtures and resetenvironment

IsolatedTestsTrait should do the trick

Page 37: Automated tests - facts and myths

Steps required to effectivelyrun in isolation

1. configure PDO SQLite in file2. create database3. drop schema4. load fixtres5. copy database as a backup6. copy database from backup for every test7. delete database backup after test suite

Page 38: Automated tests - facts and myths

Requirementschanges

frequentlywe can't keep up with unit

tests

Page 39: Automated tests - facts and myths

Use behavioralapproach

Behat in PHP

Page 40: Automated tests - facts and myths

Describe features as scenariosIt will be readable for: business, developers and machines

Page 41: Automated tests - facts and myths

Perfectly fits into Agileprocess

Page 42: Automated tests - facts and myths

Simple exampleFeature: look for a job In order to find cool job As an aspiring programmer I need to be able to list job offers

Scenario: list offers for PL version Given I am on "/" Then I should see "Dołącz do teamu" And click "Dołącz do teamu" Then I should be on "/kariera" And I should see "PHP Senior Developer (Gliwice)"

Scenario: no offers for EN site Given I am on "/en" Then I should not see "Dołącz do teamu" And I should not see an "#join-us" element

Page 43: Automated tests - facts and myths

Our tests areslow!

Page 44: Automated tests - facts and myths

This could be true ...

Page 45: Automated tests - facts and myths

Always use in-memory sqlitedatabase

Or create clean sqlite database and copyit for every test

Page 46: Automated tests - facts and myths

Group your testsUse PHPUnit's @group or Behat's @tag

Page 47: Automated tests - facts and myths

Create "smoke tests" groupsThose should be fast test, which ensures your system is most likely

stable

Page 48: Automated tests - facts and myths

Slower tests should run duringnight

Page 49: Automated tests - facts and myths

Facts

Page 50: Automated tests - facts and myths

It gives you confidenceabout changes and your code

Page 51: Automated tests - facts and myths

Team is able to rapidlyexperiment with code

Page 52: Automated tests - facts and myths

TDD enforces betterObject Oriented design

Smaller units of code and lower coupling always leads to betterunderstanding of the codebase by future devs

Page 53: Automated tests - facts and myths

End user experiences betterquality

lower 500 error ratio in the production

Page 54: Automated tests - facts and myths

Happier users↓

more $$$ in future

Page 55: Automated tests - facts and myths

Conclusion

Page 56: Automated tests - facts and myths

Setting up an workingenvironment for automated

testsis timely costly at the begining, but it pays off in the future

Page 57: Automated tests - facts and myths

System without any kind ofautomated tests

has big potential to be a big ball of mud

Page 58: Automated tests - facts and myths

Good coverage can be easilyachieved with

mix of unit, functional and behavioral tests

Page 59: Automated tests - facts and myths

You need to build andcultivate

TDD culture in your surrounding

Page 60: Automated tests - facts and myths

Thank you so much forattending!

Feedback is much appreciated

[email protected]

Twitter: @sznapkaGitHub: @wowo

Page 61: Automated tests - facts and myths

Join team :-)XSolve