Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unit Testing by Example

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.

Anna Filina
PRO

March 23, 2017
Tweet

More Decks by Anna Filina

Other Decks in Programming

Transcript

  1. @afilina
    Unit Testing
    by Example
    Southeast Valley .NET UG - March 23, 2017

    View Slide

  2. Anna Filina
    • Project rescue expert
    • Dev, trainer, speaker
    • 1 company
    • 2 conferences

    View Slide

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

    View Slide

  4. You Don’t Become an Expert
    Overnight

    View Slide

  5. You Don’t Start With
    100% Coverage

    View Slide

  6. Testing Without Automation

    View Slide

  7. Manually
    • Check database
    • var_dump
    • Only what changed
    • "Good enough" is subjective

    View Slide

  8. Problems
    • Last-minute bugs
    • Discovered by customers
    • Afraid of the code

    View Slide

  9. Automated
    • Control
    • Discover bugs
    • Confidence
    • More features, fewer bugs

    View Slide

  10. $qty = 0.1

    View Slide

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

    View Slide

  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);
    }

    View Slide

  13. Too Simple?
    • Prevent future breaks
    • Why code is written this way
    • Same effort as comments

    View Slide

  14. Regression Testing

    View Slide

  15. Step 2: Improve Code
    $item = new CartItem("Overwatch", 30);
    $item->setQuantity(2);
    $cart->addItem($item);
    $this->assertEquals(0, $cart->getShipping());

    View Slide

  16. Step 2: Improve Code
    public function getShipping()
    {
    if ($this->subtotal >= 40) {
    return 0;
    }
    else {
    return 15;
    }
    }

    View Slide

  17. Test Both Cases
    $item = new CartItem("Overwatch", 30);
    $item->setQuantity(1);
    $cart->addItem($item);
    $this->assertEquals(15, $cart->getShipping());

    View Slide

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

    View Slide

  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

    View Slide

  20. Step 3: New Code
    $cart = new Cart();
    $taxes = $cart->getApplicableTaxes();
    $this->assertCount(2, $taxes);
    $gst = $taxes[0];
    $this->assertEquals(0.05, $gst['percent']);

    View Slide

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

    View Slide

  22. Data From CSV

    View Slide

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

    View Slide

  24. A New Mindset
    • Write less code
    • Stay focused
    • Elegant code
    • Works right away

    View Slide

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

    View Slide

  26. Don't Waste Time
    $total = 5;
    $this->assertNotNull($total);

    View Slide

  27. How Many Cases?

    View Slide

  28. Cyclomatic Complexity

    View Slide

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

    View Slide

  30. Condition
    Loop

    View Slide

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

    View Slide

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

    View Slide

  33. API Testing
    $this->assertJsonStringEqualsJsonString('
    {
    "data": [
    {
    "slug": "fallout4",
    "name": "Fallout 4"
    }
    ]
    }
    ', $response);

    View Slide

  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.

    View Slide

  35. Testing =

    Preemptive Debugging

    View Slide

  36. @afilina afilina.com

    View Slide