Anna Filina
PRO
August 22, 2015
88

# Unit Testing By Example

Everyone tells you that you need to test. You know the theory, but you don't know where to begin. What to test? What cases to write? Through realistic and pragmatic examples, this presentation will take you away from var_dump and ease you into the testing business until you're ready to do TDD. All this without losing sight of the tight deadlines.

August 22, 2015

## Transcript

1. foolab.ca | @foolabca
Unit Testing
by Example
FrOSCon, Sankt Augustin - August 22, 2015

2. Anna Filina
• Developer
• Problem solver
• Teacher
• Advisor
2

3. Objectives
• Make testing enjoyable.
• Make it useful.
• Reduce pre-release stress.
3

4. You don’t become an
expert overnight

5. You don’t start with
100% coverage

6. Testing without
automation

7. Step 1: found bug
\$item = new CartItem("Skyrim", 30);
\$item->setQuantity(0.1);
\$this->assertEquals(1, \$item->getQuantity());
7

8. Step 1: found bug
\$item = new CartItem("Skyrim", 30);
\$item->setQuantity(0.1);
\$this->assertEquals(1, \$item->getQuantity());
public function setQuantity(\$qty)
{
\$this->qty = ceil(\$qty);
}
8

9. Regression Testing

10. Step 2: improve code
\$item = new CartItem("Skyrim", 30);
\$item->setQuantity(2);
\$cart->addItem(\$item);
\$this->assertEquals(0, \$cart->getShipping());
\$this->assertEquals(60, \$cart->getTotal());
10

11. Step 2: improve code
public function getShipping()
{
if (\$this->getSubtotal() >= 40) {
return 0;
}
else {
return 15;
}
}
11

12. Test both cases
\$item = new CartItem("Skyrim", 30);
\$item->setQuantity(1);
\$cart->addItem(\$item);
\$this->assertEquals(15, \$cart->getShipping());
\$this->assertEquals(45, \$cart->getTotal());
12

13. Step 3: write code
public function getTotal()
{
//...
\$taxes = \$this->getApplicableTaxes();
foreach (\$taxes as \$tax)
{
\$total += \$subtotal * \$tax->getPercent();
}
//...
}
13

14. Step 3: write code
array (size=2)
0 =>
array (size=2)
'name' => string 'GST' (length=3)
'percent' => float 0.05
1 =>
array (size=2)
'name' => string 'QST' (length=3)
'percent' => float 0.09975
14

15. Step 3: write code
\$cart = new Cart();
\$taxes = \$cart->getApplicableTaxes();
\$this->assertInternalType('array', \$taxes);
\$this->assertCount(2, \$taxes);
\$gst = \$taxes[0];
\$this->assertEquals(0.05, \$gst->getPercent());
15

16. Advantages
• More tests.
• Easy to write.
• Never fall too far.
16

17. Data from CSV

18. Step 4: before (TDD)
\$import = new CatalogImport();
\$products = \$import->parseFromCsv('catalog.csv');
\$this->assertInternalType('array', \$products);
\$this->assertCount(2, \$products);
\$this->assertArrayHasKey('name', \$products[0]);
\$this->assertArrayHasKey('price', \$products[0]);
18

19. Tips
• How it’s not supposed to work.
• Plan for exceptions.
• Focus on realistic scenarios.
19

20. Don't waste time
\$total = 5;
\$this->assertNotNull(\$total);
20

21. Recap
• Testing takes practice
• Write tests when you see
a bug
• Write tests when you
improve code
• Write tests as you write
new code
• Write tests before you
write code
• Test unexpected
scenarios
21

22. Cyclomatic Complexity
22

23. Execution Paths
public function getShipping()
{
if (\$this->subtotal >= 50) {
return 0;
}
return \$this->shipping;
}
23

24. Example
24
start
product loop free shipping? gift wrap?
end

25. Zero times
foreach (\$products as \$product) {
\$total = \$product->price * \$product->quantity;
}
if (\$total > 0) {
echo 'found';
}
25

26. Multiple times
\$total = 0;
foreach (\$products as \$product) {
\$total = \$product->price * \$product->quantity;
}
if (\$total > 0) {
echo 'found';
}
26

27. Anna Filina
• Development: PHP, JS, etc.
• Fix problems: bugs, performance, etc.
• Workshops: testing, Symfony, AngularJS, API, etc.
• Advisor: testing strategy, legacy code, etc.
27

28. @aﬁlina aﬁlina.com