Why Testing your code?
Test your PHP code Using PhpUnit, learn the basics to write tests, mock your objects and perform both Unit and Functional testing, and learn about TDD.
3. 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
8. <?php
namespace TDDTest;
use PHPUnitFrameworkTestCase;
use TDDReceipt;
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'
);
}
}
9.
10. 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
12. <?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>
13. <!--- 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>
16. 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');
}}
17. //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);
}
18. 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],
];
}
19. Test Doubles
Replace Dependency (Isolation)
Ensure a condition occurs
Improve the performance of our tests
Dummy
Fake
Stub
Spy
Mock
20. Dummy
● Dummy objects are passed around but never actually used. Usually they are
just used to fill parameter lists.
Eg: empty $config array
21. Fake
● Fake objects actually have working implementations, but usually take some
shortcut which makes them not suitable for production.
Eg: in memory database
22. 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.
23. 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.
24. Mock
● Mocks objects pre-programmed with expectations which form a specification
of the calls they are expected to receive.
25. public function total(array $items = [], $coupon) {
$sum = array_sum($items);
if (!is_null($coupon)) {
return $sum - ($sum * $coupon);
}
return $sum;
}
26. 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
27. 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
}