4. 44
Automated Tests
Why should I write tests?
● To find bugs before our customers do it for us
● To not be called in the middle of the night
5. 55
Automated Tests
Why should I write tests?
● To find bugs before our customers do it for us
● To not be called in the middle of the night
● Professionalism
6. 66
Automated Tests
Why should I write tests?
Every time a bug goes to production
it means you as a programmer failed to do your job.
Robert C. Martin (Uncle Bob) in “The Clean Coder”
7. 77
Automated Tests
Why should I write tests?
● To find bugs before our customers do it for us
● To not be called in the middle of the night
● Professionalism
● Customers lose confidence when they find bugs
8. 88
Automated Tests
Why should I write tests?
● To find bugs before our customers do it for us
● To not be called in the middle of the night
● Professionalism
● Customers lose confidence when they find bugs
● Increases the developer confidence in refactoring and changing things
9. 99
Automated Tests
Why should I write tests?
● To find bugs before our customers do it for us
● To not be called in the middle of the night
● Professionalism
● Customers lose confidence when they find bugs
● Increases the developer confidence in refactoring and changing things
● Actually reduces costs in a long term
15. 1515
Automated Tests
Unit Tests with PHPUnit
Installation:
composer require --dev phpunit/phpunit
Symfony suggests using the .phar file but the composer version is more maintainable* and
it’s available for everyone in the project.
*My opinion :)
18. 1818
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests:
● Isolated
● Runs very fast
● Reliable (not failing randomly)
19. 1919
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests:
● Isolated
● Runs very fast
● Reliable (not failing randomly)
● No logic inside
20. 2020
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests:
● Isolated
● Runs very fast
● Reliable (not failing randomly)
● No logic inside
● Assertion on only one object
21. 2121
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: Isolated
● No actual access to other components, e.g.: API, database, queue server or file system
22. 2222
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: Isolated
● No actual access to other components, e.g.: API, database, queue server or file system
● Tests shouldn’t depend on the behaviour of other systems
23. 2323
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: Isolated
● No actual access to other components, e.g.: API, database, queue server or file system
● Tests shouldn’t depend on the behaviour of other systems
● Mock everything that the tested code doesn’t control
24. 2424
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: Isolated
● No actual access to other components, e.g.: API, database, queue server or file system
● Tests shouldn’t depend on the behaviour of other systems
● Mock everything that the tested code doesn’t control
● Produces deterministic behavior
26. 2626
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: Runs very fast
● Some milliseconds
● Feedback loop is instantaneous
27. 2727
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: Runs very fast
● Some milliseconds
● Feedback loop is instantaneous
● Developers won’t be discouraged from running them
28. 2828
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: No logic inside
● No flow control (if, else, etc.)
29. 2929
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: No logic inside
● No flow control (if, else, etc.)
● No loops (while, for, etc.)
30. 3030
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: No logic inside
● No flow control (if, else, etc.)
● No loops (while, for, etc.)
● No goto
31. 3131
Automated Tests
Unit Tests with PHPUnit
Characteristics of good unit tests: No logic inside
● No flow control (if, else, etc.)
● No loops (while, for, etc.)
● No goto - I’m kidding about this one
34. 3434
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
35. 3535
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
a. You can also use the annotation @test instead of the prefix. Use your project’s standard.
36. 3636
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
a. You can also use the annotation @test instead of the prefix. Use your project’s standard.
4. Method names describe what is being tested
37. 3737
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
a. You can also use the annotation @test instead of the prefix. Use your project’s standard.
4. Method names describe what is being tested
5. Body has three stages
38. 3838
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
a. You can also use the annotation @test instead of the prefix. Use your project’s standard.
4. Method names describe what is being tested
5. Body has three stages
a. Prepare
39. 3939
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
a. You can also use the annotation @test instead of the prefix. Use your project’s standard.
4. Method names describe what is being tested
5. Body has three stages
a. Prepare
b. Execute
40. 4040
Automated Tests
Unit Tests with PHPUnit
Anatomy of an Unit Test
1. Extends from TestCase
2. Class name ends with *Test
3. Method names start with test*
a. You can also use the annotation @test instead of the prefix. Use your project’s standard.
4. Method names describe what is being tested
5. Body has three stages
a. Prepare
b. Execute
c. Assert
47. 4747
Automated Tests
Unit Tests with PHPUnit
Location of test files: tests/<bundleName>
Running the tests via console:
This is nice, but you should integrate
phpunit into your PHPStorm, so that
running tests becomes a matter of
pressing a key combination.
51. 5151
Automated Tests
Functional Tests - Overview
Functional Tests simulate the user behavior throughout the system and guarantee that:
● Components and systems work together as expected
52. 5252
Automated Tests
Functional Tests - Overview
Functional Tests simulate the user behavior throughout the system and guarantee that:
● Components and systems work together as expected
● Your system functions as it should as a whole
53. 5353
Automated Tests
Functional Tests - Overview
Functional Tests simulate the user behavior throughout the system and guarantee that:
● Components and systems work together as expected
● Your system functions as it should as a whole
● The acceptance criterias in the story are met
54. 5454
Automated Tests
Functional Tests - Overview
Functional Tests simulate the user behavior throughout the system and guarantee that:
● Components and systems work together as expected
● Your system functions as it should as a whole
● The acceptance criterias in the story are met
● Your Product Owner/Manager is happy
56. 5656
Automated Tests
Functional Tests - Overview
The anatomy of a functional test with PHPUnit is not very different from an unit test.
With Symfony, you extend it from
WebTestCase instead of TestCase.
57. 5757
Automated Tests
Functional Tests - Overview
The anatomy of a functional test with PHPUnit is not very different from an unit test.
With Symfony, you extend it from
WebTestCase instead of TestCase.
1. Prepare (create the client)
58. 5858
Automated Tests
Functional Tests - Overview
The anatomy of a functional test with PHPUnit is not very different from an unit test.
With Symfony, you extend it from
WebTestCase instead of TestCase.
1. Prepare (create the client)
2. Execute (make an actual request)
59. 5959
Automated Tests
Functional Tests - Overview
The anatomy of a functional test with PHPUnit is not very different from an unit test.
With Symfony, you extend it from
WebTestCase instead of TestCase.
1. Prepare (create the client)
2. Execute (make an actual request)
3. Assert (navigate through the DOM)
61. 6161
Automated Tests
Functional Tests - Overview
Location of your tests: tests/<bundleName>/Controller
In case your kernel is not in the standard directory, add this to your phpunit.xml:
62. 6262
Automated Tests
Functional Tests - Client Object
When you create a client you have access to an object with browsing capabilities. You can:
● Execute requests: $client->request(‘httpMethod’, ‘url’);
63. 6363
Automated Tests
Functional Tests - Client Object
When you create a client you have access to an object with browsing capabilities. You can:
● Execute requests: $client->request(‘httpMethod’, ‘url’);
● Navigate:
○ $client->back();
○ $client->forward();
○ $client->reload();
64. 6464
Automated Tests
Functional Tests - Client Object
When you create a client you have access to an object with browsing capabilities. You can:
● Execute requests: $client->request(‘httpMethod’, ‘url’);
● Navigate:
○ $client->back();
○ $client->forward();
○ $client->reload();
● Submit forms: $client->submit($domElement, [formInfo, ...]);
65. 6565
Automated Tests
Functional Tests - Client Object
When you create a client you have access to an object with browsing capabilities. You can:
● Execute requests: $client->request(‘httpMethod’, ‘url’);
● Navigate:
○ $client->back();
○ $client->forward();
○ $client->reload();
● Submit forms: $client->submit($domElement, [formInfo, ...]);
● Execute clicks on links: $client->click($domElement);
66. 6666
Automated Tests
Functional Tests - Client Object
When you create a client you have access to an object with browsing capabilities. You can:
● Execute requests: $client->request(‘httpMethod’, ‘url’);
● Navigate:
○ $client->back();
○ $client->forward();
○ $client->reload();
● Submit forms: $client->submit($domElement, [formInfo, ...]);
● Execute clicks on links: $client->click($domElement);
69. 6969
Automated Tests
Functional Tests - Crawler Object
The Crawler allows you to navigate/traverse through a DOM structure in HTML or XML.
Not like this, though…
just because mooountains! :)
70. 7070
Automated Tests
Functional Tests - Crawler Object
The Crawler allows you to navigate/traverse through a DOM structure in HTML or XML.
Actually like this!
73. 7373
Automated Tests
Functional Tests - Crawler Object
You can also extract information from the selected nodes:
● Attribute value: $crawler->attr(‘attributeName’);
74. 7474
Automated Tests
Functional Tests - Crawler Object
You can also extract information from the selected nodes:
● Attribute value: $crawler->attr(‘attributeName’);
● Text: $crawler->text();
75. 7575
Automated Tests
Functional Tests - Crawler Object
You can also extract information from the selected nodes:
● Attribute value: $crawler->attr(‘attributeName’);
● Text: $crawler->text();
● Multiple attributes: $crawler->extract([‘attr1’, ‘attr2’, ...]);
76. 7676
Automated Tests
Functional Tests - Crawler Object
You can also extract information from the selected nodes:
● Attribute value: $crawler->attr(‘attributeName’);
● Text: $crawler->text();
● Multiple attributes: $crawler->extract([‘attr1’, ‘attr2’, ...]);
Or use shortcuts provided by the Crawler Object:
77. 7777
Automated Tests
Functional Tests - Crawler Object
You can also extract information from the selected nodes:
● Attribute value: $crawler->attr(‘attributeName’);
● Text: $crawler->text();
● Multiple attributes: $crawler->extract([‘attr1’, ‘attr2’, ...]);
Or use shortcuts provided by the Crawler Object:
● Select link by name: $crawler->selectLink(‘seeFreeStuff’);
78. 7878
Automated Tests
Functional Tests - Crawler Object
You can also extract information from the selected nodes:
● Attribute value: $crawler->attr(‘attributeName’);
● Text: $crawler->text();
● Multiple attributes: $crawler->extract([‘attr1’, ‘attr2’, ...]);
Or use shortcuts provided by the Crawler Object:
● Select link by name: $crawler->selectLink(‘seeFreeStuff’);
● Select button by name: $crawler->selectButton(‘getFreeStuff’);
82. 8282
Automated Tests
Functional Tests - Profile Object
To enable the profiler to be used in tests:
This tells the profiler to only collect the data when $client->enableProfiler() is called.
85. 8585
Automated Tests
Functional Tests - Profile Object
To use the profile data in your tests:
1. Enable the profiler locally.
2. Execute the request.
86. 8686
Automated Tests
Functional Tests - Profile Object
To use the profile data in your tests:
1. Enable the profiler locally.
2. Execute the request.
3. Assert against the metrics provided by
the profiler.
88. 8888
Automated Tests
Functional Tests - Framework Objects Access
A.k.a. “Accessing the Container”.
Although it’s recommended to test only the response, you can access the DI Container:
89. 8989
Automated Tests
Functional Tests - Framework Objects Access
A.k.a. “Accessing the Container”.
Although it’s recommended to test only the response, you can access the DI Container:
$client->getContainer();
90. 9090
When using Symfony’s client, it creates a Kernel with the environment set to “test”.
Symfony then loads the config from app/config/config_test.yml.
Automated Tests
Functional Tests - Client Configuration
91. 9191
When using Symfony’s client, it creates a Kernel with the environment set to “test”.
Symfony then loads the config from app/config/config_test.yml.
When creating the client you can override some of its options:
Automated Tests
Functional Tests - Client Configuration
92. 9292
When using Symfony’s client, it creates a Kernel with the environment set to “test”.
Symfony then loads the config from app/config/config_test.yml.
When creating the client you can override some of its options:
● The environment:
○ static::createClient([‘environment’ => ‘my_own_env’]);
Automated Tests
Functional Tests - Client Configuration
93. 9393
When using Symfony’s client, it creates a Kernel with the environment set to “test”.
Symfony then loads the config from app/config/config_test.yml.
When creating the client you can override some of its options:
● The environment:
○ static::createClient([‘environment’ => ‘my_own_env’]);
● The debug mode:
○ static::createClient([‘debug’ => false]);
Automated Tests
Functional Tests - Client Configuration
94. 9494
When using Symfony’s client, it creates a Kernel with the environment set to “test”.
Symfony then loads the config from app/config/config_test.yml.
When creating the client you can override some of its options:
● The environment:
○ static::createClient([‘environment’ => ‘my_own_env’]);
● The debug mode:
○ static::createClient([‘debug’ => false]);
● HTTP Headers:
○ static::createClient([], [‘HTTP_USER_AGENT’ = > ‘Exoclient/1.0’]);
Automated Tests
Functional Tests - Client Configuration
95. 9595
When using Symfony’s client, it creates a Kernel with the environment set to “test”.
Symfony then loads the config from app/config/config_test.yml.
When creating the client you can override some of its options:
● The environment:
○ static::createClient([‘environment’ => ‘my_own_env’]);
● The debug mode:
○ static::createClient([‘debug’ => false]);
● HTTP Headers:
○ static::createClient([], [‘HTTP_USER_AGENT’ => ‘Exoclient/1.0’]);
You can also override the HTTP Headers for a specific request:
$client->request->(‘METHOD’, ‘URL’, [], [], [‘HTTP_USER_AGENT’ => ‘Exoclient/1.0’]);
Automated Tests
Functional Tests - Client Configuration
96. 9696
Automated Tests
Functional Tests - Request and Response Introspection
You also have access to internal objects of the client, e.g.:
● History: $client->getHistory();
97. 9797
Automated Tests
Functional Tests - Request and Response Introspection
You also have access to internal objects of the client, e.g.:
● History: $client->getHistory();
● Cookies: $client->getCookieJar();
98. 9898
Automated Tests
Functional Tests - Request and Response Introspection
You also have access to internal objects of the client, e.g.:
● History: $client->getHistory();
● Cookies: $client->getCookieJar();
● Response: $client->getResponse();
99. 9999
Automated Tests
Functional Tests - Request and Response Introspection
You also have access to internal objects of the client, e.g.:
● History: $client->getHistory();
● Cookies: $client->getCookieJar();
● Response: $client->getResponse();
● Crawler (DOM Navigator): $client->getCrawler();