Slide 1

Slide 1 text

foolab.ca | @foolabca Unit Testing by Example IPC, Berlin - June 8, 2015

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

You don’t become an expert overnight

Slide 5

Slide 5 text

You don’t start with 100% coverage

Slide 6

Slide 6 text

Testing Without Automation

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Regression Testing

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

Data from CSV

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Cyclomatic Complexity

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Services • Development: PHP, JS, etc. • Fix problems: bugs, performance, etc. • Workshops: testing, Symfony, AngularJS • Advisor: testing strategy, architecture, etc. 27