Unit Testing by Example

B3b2139e4f2c0eca4efe2379fcebc1c5?s=47 Anna Filina
February 16, 2017

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.

B3b2139e4f2c0eca4efe2379fcebc1c5?s=128

Anna Filina

February 16, 2017
Tweet

Transcript

  1. @afilina Unit Testing by Example PHPUK, London - February 16,

    2017
  2. Anna Filina • Project rescue expert • Dev, trainer, speaker

    • 1 company • 2 conferences
  3. Objectives • Make testing enjoyable. • Make it useful. •

    Reduce pre-release stress.
  4. You Don’t Become an Expert Overnight

  5. You Don’t Start With 100% Coverage

  6. Testing Without Automation

  7. Manually • Check database • var_dump • Only what changed

    • "Good enough" is subjective
  8. Problems • Last-minute bugs • Discovered by customers • Afraid

    of the code
  9. Automated • Control • Discover bugs • Confidence • More

    features, fewer bugs
  10. $qty = 0.1

  11. Step 1: Found Bug $item = new CartItem("Overwatch", 30); $item->setQuantity(0.1);

    $this->assertEquals(1, $item->getQuantity());
  12. Step 1: Found Bug $item = new CartItem("Overwatch", 30); $item->setQuantity(0.1);

    $this->assertEquals(1, $item->getQuantity()); public function setQuantity($qty) { $this->qty = ceil($qty); }
  13. Too Simple? • Prevent future breaks • Why code is

    written this way • Same effort as comments
  14. Regression Testing

  15. Step 2: Improve Code $item = new CartItem("Overwatch", 30); $item->setQuantity(2);

    $cart->addItem($item); $this->assertEquals(0, $cart->getShipping());
  16. Step 2: Improve Code public function getShipping() { if ($this->subtotal

    >= 40) { return 0; } else { return 15; } }
  17. Test Both Cases $item = new CartItem("Overwatch", 30); $item->setQuantity(1); $cart->addItem($item);

    $this->assertEquals(15, $cart->getShipping());
  18. Step 3: New Code public function getTotal() { //... $taxes

    = $this->getApplicableTaxes(); foreach ($taxes as $tax) { $total += $subtotal * $tax->getPercent(); } //... }
  19. Step 3: New 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
  20. Step 3: New Code $cart = new Cart(); $taxes =

    $cart->getApplicableTaxes(); $this->assertInternalType('array', $taxes); $this->assertCount(2, $taxes); $gst = $taxes[0]; $this->assertEquals(0.05, $gst['percent']);
  21. Advantages • More tests. • Easy to write. • Never

    fall too far.
  22. Data From CSV

  23. 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]);
  24. A New Mindset • Write less code • Stay focused

    • Elegant code • Works right away
  25. Tips • How it’s not supposed to work. • Plan

    for exceptions. • Focus on realistic scenarios.
  26. Don't Waste Time $total = 5; $this->assertNotNull($total);

  27. How Many Cases?

  28. Cyclomatic Complexity

  29. Execution Paths public function getShipping() { if ($this->subtotal >= 40)

    { return 0; } return $this->shipping; }
  30. Condition Loop

  31. Zero Times foreach ($products as $product) { $total = $product->price

    * $product->quantity; } if ($total > 0) { echo 'found'; }
  32. Multiple Times $total = 0; foreach ($products as $product) {

    $total = $product->price * $product->quantity; } if ($total > 0) { echo 'found'; }
  33. API Testing $this->assertJsonStringEqualsJsonString(' { "data": [ { "slug": "fallout4", "name":

    "Fallout 4" } ] } ', $response);
  34. 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.
  35. Testing =
 Preemptive Debugging

  36. @afilina afilina.com joind.in