symfony (unit, functional) testing
TRANSCRIPT
![Page 2: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/2.jpg)
![Page 3: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/3.jpg)
Why Testing?Prevent Bugs. (Reputation)
Prevent Fixing same Bugs more than once. (add additional cases each time)
Faster than manual testing.
Additional Documentation.
Upgrading your platform? Refactoring your Code? NO PROBLEM
Keeping your code quality.. Spaghetti Code is not testable ;)
Making QA jobless
![Page 4: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/4.jpg)
1- Unit TestingUnit tests are used to test your “business logic”
![Page 5: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/5.jpg)
If you want the design
of your code to be
better ... write Unit Tests
“Symfony Live London 2015 - Ciaran McNulty”
![Page 6: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/6.jpg)
Most Used Assertions
AssertTrue/AssertFalseAssertEquals(AssertGreaterThan, LessThan)(GreaterThanOrEqual, LessThanOrEqual) AssertContainsAssertTypeAssertNullAssertFileExistsAssertRegExp
![Page 7: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/7.jpg)
<?php
namespace TDD;
class Receipt {
public function total(array $items = []) {
return array_sum($items);
}
}
![Page 8: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/8.jpg)
<?php
namespace TDD\Test;
use PHPUnit\Framework\TestCase;
use TDD\Receipt;
class ReceiptTest extends TestCase {
public function testTotal() {
$Receipt = new Receipt();
$this->assertEquals(
14,
$Receipt->total([0,2,5,8]),
'When summing the total should equal 15'
);
}
}
![Page 9: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/9.jpg)
![Page 10: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/10.jpg)
PHPUnit outcomes.
Printed when the test succeeds.
F
Printed when an assertion fails while running the test method.
E
Printed when an error occurs while running the test method.
S
Printed when the test has been skipped.
I
Printed when the test is marked as being incomplete or not yet implemented
![Page 11: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/11.jpg)
PhpUnit Command linePhpunit
--filter=
--testsuite= <name,...>
--coverage-html <dir>
Other configurations are imported from phpunit.xml (next slide)
#
![Page 12: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/12.jpg)
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="app/autoload.php" backupGlobals="false" colors="true" verbose="true"
stopOnFailure="false">
<php>
<server name="KERNEL_DIR" value="/app/" />
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
</php>
<testsuites>
<!-- compose tests into test suites -->
<testsuite name="Project Test Suite">
<!-- You can either choose directory or single files -->
<directory>tests</directory>
<file>tests/General/ApplicationAvailabilityFunctionalTest.php</file>
</testsuite>
</testsuites>
![Page 13: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/13.jpg)
<!--- This part is for code coverage (choose which directory to check and which to execlude from
coverage)-->
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src/AcmeBundle/Repository</directory>
<exclude>
<directory suffix=".php">./src/AcmeBundle/Tests</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
![Page 14: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/14.jpg)
Arrange-Act-Assert
![Page 15: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/15.jpg)
General Principles
Test In Isolation
Test on thing per Function
If hard to test, reimplement your code
![Page 16: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/16.jpg)
class ReceiptTest extends TestCase {
public function setUp() {
$this->Receipt = new Receipt();
}
public function tearDown() {
unset($this->Receipt);
}
public function testTotal() {
//arrange
$input = [0,2,5,8];
//ACT
$output = $this->Receipt->total($input);
//Assert
$this->assertEquals(
15,
$output,
'When summing the total should equal 15');
}}
![Page 17: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/17.jpg)
//Test Function
public function testTax() {
$inputAmount = 10.00;
$taxInput = 0.10;
$output = $this->Receipt->tax($inputAmount, $taxInput);
$this->assertEquals(
1.00,
$output,
'The tax calculation should equal 1.00'
);
}
//Actual Function
public function tax($amount, $tax) {
return ($amount * $tax);
}
![Page 18: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/18.jpg)
Data Providers/**
* @dataProvider provideTotal
*/
public function testTotal($items, $expected) {
$coupon = null;
$output = $this->Receipt->total($items, $coupon);
$this->assertEquals(
$expected,
$output,
"When summing the total should equal {$expected}"
);
}
public function provideTotal() {
return [
[[1,2,5,8], 16],
[[-1,2,5,8], 14],
[[1,2,8], 11],
];
}
![Page 19: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/19.jpg)
Test DoublesReplace Dependency (Isolation)
Ensure a condition occurs
Improve the performance of our tests
Dummy
Fake
Stub
Spy
Mock
![Page 20: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/20.jpg)
Dummy
● Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Eg: empty $config array
![Page 21: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/21.jpg)
Fake
● Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production.
Eg: in memory database
![Page 22: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/22.jpg)
Stub
● Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
Eg: stub for isConnected() which returns false.
![Page 23: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/23.jpg)
Spy
● Spies are stubs that also record some information based on how they were called.
Eg: an email service that records how many messages it was sent.
![Page 24: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/24.jpg)
Mock
● Mocks objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
![Page 25: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/25.jpg)
public function total(array $items = [], $coupon) {
$sum = array_sum($items);
if (!is_null($coupon)) {
return $sum - ($sum * $coupon);
}
return $sum;
}
![Page 26: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/26.jpg)
public function testTotal() {
$input = [0,2,5,8];
$coupon = null;
$output = $this->Receipt->total($input, $coupon);
$this->assertEquals(
15,
$output,
'When summing the total should equal 15'
);
}
public function testTotalAndCoupon() {
$input = [0,2,5,8];
$coupon = 0.20;
$output = $this->Receipt->total($input, $coupon);
$this->assertEquals(
12,
$output,
'When summing the total should equal 12'
);
}
Dummy
![Page 27: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/27.jpg)
public function total(array $items = [], $coupon) {
$sum = array_sum($items);
if (!is_null($coupon)) {
return $sum - ($sum * $coupon);
}
return $sum;
}
public function tax($amount, $tax) {
return ($amount * $tax);
}
public function postTaxTotal($items, $tax, $coupon) {
$subtotal = $this->total($items, $coupon); //total -> 10
$subtotal += $tax;
return $subtotal + $this->tax($subtotal, $tax); //tax -> 1
}
![Page 28: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/28.jpg)
public function testPostTaxTotal() {
$Receipt = $this->getMockBuilder('TDD\Receipt')
->setMethods(['tax', 'total'])
->getMock();
$Receipt->method('total')
->will($this->returnValue(10.00));
$Receipt->method('tax')
->will($this->returnValue(1.00));
$result = $Receipt->postTaxTotal([1,2,5,8], 0.20, null);
$this->assertEquals(11.00, $result);
}
Stub
![Page 29: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/29.jpg)
public function testPostTaxTotal () {
$items = [1,2,5,8];
$tax = 0.20;
$coupon = null;
$Receipt = $this->getMockBuilder('TDD\Receipt')
->setMethods(['tax', 'total'])
->getMock();
$Receipt->expects($this->once())
->method('total')
->with($items, $coupon)
->will($this->returnValue(10.00));
$Receipt->expects($this->once())
->method('tax')
->with(10.00, $tax)
->will($this->returnValue(1.00));
$result = $Receipt->postTaxTotal([1,2,5,8], 0.20, null);
$this->assertEquals(11.00, $result);
}
Mock
![Page 30: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/30.jpg)
TDDWrite Test, Run Test, Write Code, Run Test, Repeat Until Completed
![Page 31: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/31.jpg)
Data Fixturesphp bin/console doctrine:fixtures:load
class LoadJobsData extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
$user = $manager->getRepository('UserBundle:User')->findBy(array('username' => 'friik'));
$organization = $manager->getRepository('JobsBundle:Organization')->findBy(array('name' =>
'friikcom'));
![Page 32: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/32.jpg)
$job = new Job();
$job->setCreatedBy($user[0]);
$job->setCreatedAt();
$job->setStartDate(new \DateTime());
$job->setEndDate(new \DateTime('+1 week'));
$job->setActive(1);
$job->setJobCaption('new job for all interested');
$job->setEmplType(2);
$job->setOrganization($organization[0]);
$manager->persist($job);
$manager->flush();
}
public function getOrder()
{
return 4;
}
}
![Page 33: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/33.jpg)
protected function setUp()
{
self::bootKernel();
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager();}
public function testFindAllJobsOrderedByDateReturnsResults()
{
$expectedOutput = 2;
$job = $this->em
->getRepository('JobsBundle:Job')
->findAllJobsOrderedByDate()->getResult(Query::HYDRATE_ARRAY);
$this->assertCount($expectedOutput, $job);
}
protected function tearDown()
{
parent::tearDown();
$this->em->close();
$this->em = null; // avoid memory leaks
}
}
![Page 34: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/34.jpg)
2- Functional Testingcheck the integration of the different layers of an
application
![Page 35: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/35.jpg)
Define a client then Request/**
* @dataProvider urlProvider
*/
public function testPageIsSuccessful($url)
{
$client = self::createClient();
$client->request('GET', $url);
$this->assertTrue($client->getResponse()->isSuccessful());
}
public function urlProvider()
{
return array(
array('/jobs'),
array('/jobs/organization/show'),
array('/jobs/organization/add'),
array('/jobs/organization/check'),
);
![Page 36: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/36.jpg)
public function testIndexPageRequestAuthorized()
{
$client = static::createClient();
$crawler = $client->request('GET', '/jobs/job', array(), array(), array(
'PHP_AUTH_USER' => 'friik',
'PHP_AUTH_PW' => 'friikfriik',
));
$crawler = $client->followRedirect();
$response = $client->getResponse();
$this->assertEquals(200, $response->getStatusCode());
}
Authorized client
![Page 37: Symfony (Unit, Functional) Testing](https://reader033.vdocument.in/reader033/viewer/2022051123/5a66b3e07f8b9ab87e8b4737/html5/thumbnails/37.jpg)
public function testOrganizationShowExampleTests()
{
$client = static::createClient();
$crawler = $client->request('GET', '/jobs/organization/show');
$response = $client->getResponse();
//Status Code
// $this->assertEquals(200, $response->getStatusCode());
//Check if page contains content
//$this->assertContains('company', $response->getContent());
$img = $crawler->filterXPath('//img');
$atr = $img->attr('src');
//check for alt attr in image tags
$crawler->filter('img')->each(function ($node, $i) {
$alt = $node->attr('alt');
$this->assertNotNull($alt);
});
}