Slide 1

Slide 1 text

Unit Tests Unit Tests in Symfony2 in Symfony2 Marek Kalnik Marek Kalnik

Slide 2

Slide 2 text

2 Symfony is one of the few Symfony is one of the few PHP projects (...) promoting PHP projects (...) promoting radical changes to the way radical changes to the way developers work developers work Fabien Potencier Fabien Potencier

Slide 3

Slide 3 text

3

Orders

”; } } ?> $row['label']$row['value']

Orders

”; } } ?> $row['label']$row['value'] PHP began with code like that (me too) PHP began with code like that (me too)

Slide 4

Slide 4 text

4

Orders

”; } } ?> $row['label']$row['value']

Orders

”; } } ?> $row['label']$row['value'] We want to improve our work We want to improve our work DIFFICULT TO REUSE SECURITY RISK NO SEPARATION OF CONCERNS NOT TESTED!

Slide 5

Slide 5 text

5 We have to participate in the We have to participate in the changes introduced by Symfony changes introduced by Symfony

Slide 6

Slide 6 text

6 We should unit test our We should unit test our applications applications

Slide 7

Slide 7 text

Unit tests Unit tests it is not only testing it is not only testing

Slide 8

Slide 8 text

8 Impact on development Impact on development According to university study by David S. Janzen[1]: According to university study by David S. Janzen[1]: ● reduces the number of lines of code reduces the number of lines of code ● improves productivity improves productivity ● less effort per line-of-code less effort per line-of-code ● improves code structure improves code structure ● makes developer more confident about their work makes developer more confident about their work [1] http://src.acm.org/subpages/gf_entries_06/DavidJanzen_src_gf06.pdf

Slide 9

Slide 9 text

9 TDD – even better TDD – even better Further improves the code stability and quality: Further improves the code stability and quality: ● http://research.microsoft.com/en-us/groups/ese/nagappan_tdd.pdf http://research.microsoft.com/en-us/groups/ese/nagappan_tdd.pdf ● http://research.microsoft.com/en-us/groups/ese/fp17288-bhat.pdf http://research.microsoft.com/en-us/groups/ese/fp17288-bhat.pdf ● and others... and others... Most successful Theodo Most successful Theodo projects were written using projects were written using the TDD technique. the TDD technique.

Slide 10

Slide 10 text

Symfony2 Symfony2 Test Culture Test Culture

Slide 11

Slide 11 text

11 Symfony2 tests Symfony2 tests • early versions ~5100 tests early versions ~5100 tests • today ~9000 tests today ~9000 tests • Documentation! Documentation! • http://symfony.com/doc/current/book/testing.html http://symfony.com/doc/current/book/testing.html • http://symfony.com/doc/current/cookbook/testing/index.html http://symfony.com/doc/current/cookbook/testing/index.html • http://symfony.com/doc/current/cookbook/form/unit_testing.html http://symfony.com/doc/current/cookbook/form/unit_testing.html

Slide 12

Slide 12 text

12 Interesting TestCases Interesting TestCases • FormComponent::FormIntegrationTestCase FormComponent::FormIntegrationTestCase • FormComponent::TypeTestCase FormComponent::TypeTestCase • *PerformanceTestCase *PerformanceTestCase • LocaleComponent::TestCase LocaleComponent::TestCase • FosUserBundle::FosUserExtensionTest FosUserBundle::FosUserExtensionTest • getFullConfig, getEmptyConfig getFullConfig, getEmptyConfig   • TheodoRogerCmsBundle ;-) TheodoRogerCmsBundle ;-)

Slide 13

Slide 13 text

13 Read The Read The Docs Docs Tests! Tests!

Slide 14

Slide 14 text

So how do you do it? So how do you do it?

Slide 15

Slide 15 text

15 Tools Tools PHPUnit running and writing the tests because it's the industry standard Phake (https://github.com/mlively/Phake) mocking because PHPUnit mocks are not flexible enough

Slide 16

Slide 16 text

16 Install Install // composer.json require-dev: { “phpunit/phpunit”: “*”, “phake/phake”: “*” } // composer.json require-dev: { “phpunit/phpunit”: “*”, “phake/phake”: “*” }

Slide 17

Slide 17 text

17 tests.bootstrap.php tests.bootstrap.php

Slide 18

Slide 18 text

18 the setUp the setUp securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } } securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } }

Slide 19

Slide 19 text

19 the mock the mock securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } public function testChecksIfCmsShouldBeEnabled() { Phake::when($this->securityContext)->isGranted('ROLE_ADMIN', null) ->thenReturn(true); } } securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } public function testChecksIfCmsShouldBeEnabled() { Phake::when($this->securityContext)->isGranted('ROLE_ADMIN', null) ->thenReturn(true); } }

Slide 20

Slide 20 text

20 the test the test securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } public function testChecksIfCmsShouldBeEnabled() { Phake::when($this->securityContext)->isGranted('ROLE_ADMIN', null) ->thenReturn(true); $this->assertTrue($this->enabler->isEnabled()); Phake::verify($this->securityContext, Phake::times(1))->isGranted('ROLE_ADMIN', null); } } securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } public function testChecksIfCmsShouldBeEnabled() { Phake::when($this->securityContext)->isGranted('ROLE_ADMIN', null) ->thenReturn(true); $this->assertTrue($this->enabler->isEnabled()); Phake::verify($this->securityContext, Phake::times(1))->isGranted('ROLE_ADMIN', null); } }

Slide 21

Slide 21 text

21 and more and more securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } public function testChecksIfCmsShouldBeEnabled() { Phake::when($this->securityContext)->isGranted('ROLE_ADMIN', null) ->thenReturn(true); $this->enabler->setEnv('cms'); $this->assertTrue($this->enabler->isEnabled()); $this->enabler->setEnv('prod'); $this->assertFalse($this->enabler->isEnabled()); Phake::verify($this->securityContext, Phake::times(1))->isGranted('ROLE_ADMIN', null); } } securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } public function testChecksIfCmsShouldBeEnabled() { Phake::when($this->securityContext)->isGranted('ROLE_ADMIN', null) ->thenReturn(true); $this->enabler->setEnv('cms'); $this->assertTrue($this->enabler->isEnabled()); $this->enabler->setEnv('prod'); $this->assertFalse($this->enabler->isEnabled()); Phake::verify($this->securityContext, Phake::times(1))->isGranted('ROLE_ADMIN', null); } }

Slide 22

Slide 22 text

22 group group securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } securityContext = Phake::mock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->enabler = new CmsEnablerExtension($this->securityContext); } $ bin/phpunit -c app/ --group unit $ bin/phpunit -c app/ --group unit

Slide 23

Slide 23 text

23 other stuff other stuff refactor your tests – it's a code to maintain too! use fixtures (Alice, Phaker) ! be close to production

Slide 24

Slide 24 text

Questions ? Questions ?