Unit Testing by Example

Unit Testing by Example

Everyone tells you that you need to write tests. You tried it, but your tests ended up not very useful and consumed valuable time. What to test? What conditions to write? Through realistic examples, this presentation will take you from var_dump() and ease you into the testing business. All this without losing sight of the tight deadlines. You will come out of this presentation with a renewed interest in writing unit tests.

B3b2139e4f2c0eca4efe2379fcebc1c5?s=128

Anna Filina

June 08, 2015
Tweet

Transcript

  1. foolab.ca | @foolabca Unit Testing by Example IPC, Berlin -

    June 8, 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.5 1 => array (size=2) 'name' => string 'QST' (length=3) 'percent' => float 0.9975 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.5, $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

  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. Services • Development: PHP, JS, etc. • Fix problems: bugs,

    performance, etc. • Workshops: testing, Symfony, AngularJS • Advisor: testing strategy, architecture, etc. 27