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

Test-Driven Development

Test-Driven Development

Test-Driven Development o TDD es una metodología de desarrollo de software que intenta de manera proactiva garantizar que nuestro código funciona como debería, además de prevenir y reducir el número de defectos y bugs de nuestro código. La idea principal de esta metodología es realizar de forma inicial las pruebas unitarias para el código que tenemos que implementar e ir creando un conjunto de pruebas que nos avisen inmediatamente si hemos introducido algún cambio que modifique su funcionamiento.

Desde que el TDD fue "redescubierto" por Kent Beck, ha sido una de las técnicas ágiles que más difusión ha alcanzado y goza de especial popularidad en estos momentos. Sin embargo, a menudo es mal aplicado y los equipos que lo implementan se ven aquejados de problemas comunes, que terminan haciendo que se abandone. Muchos desarrolladores piensan que desarrollar tests unitarios sale más caro, que es una pérdida de tiempo, pero sólo una reflexión, ¿cuánto tiempo pasáis depurando vuestro código? ¿cuántas veces habéis arreglado algún bug que se podría haber detectado con un test unitario?

En esta charla trataremos los siguientes puntos:
- Hablar sobre el origen de TDD
- Explicar brevemente cómo se realiza TDD
- Entrar en detalle de las ventajas e inconvenientes de TDD
- Justificar por qué TDD funciona de esta manera y qué conseguimos con ello
- Ver el lado oscuro de TDD trayendo opiniones relevantes que critican TDD y, a partir de ellas, ver qué cosas se podrían mejorar

Adrián Matellanes

April 19, 2018
Tweet

More Decks by Adrián Matellanes

Other Decks in Programming

Transcript

  1. Test-Driven Development
    Adrián Matellanes

    View Slide

  2. View Slide

  3. What is TDD?

    View Slide

  4. A development technique
    where you must first write a test that fails
    before you write new code that passes
    the new test

    View Slide

  5. Kent Beck rediscovered this
    technique
    in the 1990s

    View Slide

  6. What is a test?

    View Slide

  7. A procedure intended to establish
    the quality, performance, or
    reliability of something.

    View Slide

  8. use PHPUnit\Framework\TestCase;
    class UserTest extends TestCase
    {
    public function testTalk()
    {
    $user = new User();
    $actual = $user->talk();
    $expected = "Hello world!";
    $this->assertEquals($expected, $actual);
    unset($user);
    }
    }

    View Slide

  9. use PHPUnit\Framework\TestCase;
    class UserTest extends TestCase
    {
    public function testTalk()
    {
    $user = new User();
    $actual = $user->talk();
    $expected = "Hello world!";
    $this->assertEquals($expected, $actual);
    unset($user);
    }
    }
    Setup

    View Slide

  10. use PHPUnit\Framework\TestCase;
    class UserTest extends TestCase
    {
    public function testTalk()
    {
    $user = new User();
    $actual = $user->talk();
    $expected = "Hello world!";
    $this->assertEquals($expected, $actual);
    unset($user);
    }
    }
    Execution

    View Slide

  11. use PHPUnit\Framework\TestCase;
    class UserTest extends TestCase
    {
    public function testTalk()
    {
    $user = new User();
    $actual = $user->talk();
    $expected = "Hello world!";
    $this->assertEquals($expected, $actual);
    unset($user);
    }
    }
    Validation

    View Slide

  12. use PHPUnit\Framework\TestCase;
    class UserTest extends TestCase
    {
    public function testTalk()
    {
    $user = new User();
    $actual = $user->talk();
    $expected = "Hello world!";
    $this->assertEquals($expected, $actual);
    unset($user);
    }
    }
    Teardown

    View Slide

  13. Testing Methods

    View Slide

  14. Black box
    White box

    View Slide

  15. Categories of Tests

    View Slide

  16. Unit
    Integration
    Behavioral

    View Slide

  17. Unit
    Behavioral
    Integration

    View Slide

  18. Test Doubles

    View Slide

  19. Dummy
    Fake
    Stub
    Spy
    Mock

    View Slide

  20. TDD Schools

    View Slide

  21. London School
    Detroit School

    View Slide

  22. Why developers
    not writing tests?

    View Slide

  23. No time
    No budget
    Write once project finishes
    We do not know how to write

    View Slide

  24. “If it's worth building, it's worth testing.
    If it's not worth testing,
    why are you wasting your time working on it?”
    Scott Ambler

    View Slide

  25. What is
    the goal of TDD?

    View Slide

  26. Write clean code
    that works

    View Slide

  27. “The only way to make the deadline —
    the only way to constantly go fast —
    is to keep the code as clean as possible at all times.”
    Robert C. Martin

    View Slide

  28. What makes
    a design good?

    View Slide

  29. The 7 Design Smells
    of Bad Code

    View Slide

  30. Rigidity
    Fragility
    Immobility
    Viscosity
    Needless Repetition
    Opacity
    Needless Complexity

    View Slide

  31. How TDD works?

    View Slide

  32. View Slide

  33. View Slide

  34. Red
    Write a failing test

    View Slide

  35. Green
    Make the test pass

    View Slide

  36. Refactor
    Make it better

    View Slide

  37. Technical Debt

    View Slide

  38. View Slide

  39. “Perfect is the enemy of good.”
    Voltaire

    View Slide

  40. Why do you
    test-drive code?

    View Slide

  41. Predictability

    View Slide

  42. Courage

    View Slide

  43. Documentation

    View Slide

  44. Cleaner Code

    View Slide

  45. Gamification

    View Slide

  46. Reduced
    debugging effort

    View Slide

  47. More productive

    View Slide

  48. Automated

    View Slide

  49. Emergent Design

    View Slide

  50. Coverage

    View Slide

  51. Code coverage refers to
    the amount of code covered
    by test cases

    View Slide

  52. The tragedy of
    100% code coverage

    View Slide

  53. use PHPUnit\Framework\TestCase;
    function division($a, $b)
    {
    return $a / $b;
    }
    class CalculatorTest extends TestCase
    {
    public function testDivision()
    {
    $result = division(10, 5);
    $expected = 2;
    $this->assertEquals($expected, $result);
    }
    }

    View Slide

  54. View Slide

  55. View Slide

  56. View Slide

  57. View Slide

  58. View Slide

  59. Best Practices

    View Slide

  60. Keep the unit small
    Minimize assertions
    Start with the failing test case
    Fast running tests
    Avoid fragile tests
    Rerun all test cases on each failure
    Don’t introduce dependencies between tests
    Follow standard naming conventions
    Use mock objects

    View Slide

  61. The Bad Parts

    View Slide

  62. Hard to apply to existing legacy code
    Requirements misinterpretations
    False sense of security
    How many tests should you write?
    Complex scenarios
    Rapidly changing requirements
    Not having enough knowledge on unit testing and refactoring
    Restricted portability
    Writer/Reader with technical background

    View Slide

  63. Behavior-driven development

    View Slide

  64. Behavioural Test Unit Test

    View Slide

  65. View Slide

  66. Scenario: Dispense $50 cash in multiple denominations
    Given I have $100 in my account
    And I have a card with the PIN 1234
    And I push my card into the machine
    And I enter 1234 for my PIN
    And I push the button next to Withdrawal
    And I push the button next to Checking
    When I push the button next to $50
    Then a $20 bill should be ejected by the cash dispenser
    And a $20 bill should be ejected by the cash dispenser
    And a $10 bill should be ejected by the cash dispenser

    View Slide

  67. Scenario: Dispense $50 cash in multiple denominations
    Given I have $100 in my account
    And I have a card with the PIN 1234
    And I push my card into the machine
    And I enter 1234 for my PIN
    And I push the button next to Withdrawal
    And I push the button next to Checking
    When I push the button next to $50
    Then a $20 bill should be ejected by the cash dispenser
    And a $20 bill should be ejected by the cash dispenser
    And a $10 bill should be ejected by the cash dispenser

    View Slide

  68. Scenario: Dispense $50 cash in multiple denominations
    Given I have $100 in my account
    And I have a card with the PIN 1234
    And I push my card into the machine
    And I enter 1234 for my PIN
    And I push the button next to Withdrawal
    And I push the button next to Checking
    When I push the button next to $50
    Then a $20 bill should be ejected by the cash dispenser
    And a $20 bill should be ejected by the cash dispenser
    And a $10 bill should be ejected by the cash dispenser

    View Slide

  69. Scenario: Dispense $50 cash in multiple denominations
    Given I have $100 in my account
    And I have a card with the PIN 1234
    And I push my card into the machine
    And I enter 1234 for my PIN
    And I push the button next to Withdrawal
    And I push the button next to Checking
    When I push the button next to $50
    Then a $20 bill should be ejected by the cash dispenser
    And a $20 bill should be ejected by the cash dispenser
    And a $10 bill should be ejected by the cash dispenser

    View Slide

  70. Scenario: Dispense $50 cash in multiple denominations
    Given I have $100 in my account
    And I have a card with the PIN 1234
    And I push my card into the machine
    And I enter 1234 for my PIN
    And I push the button next to Withdrawal
    And I push the button next to Checking
    When I push the button next to $50
    Then a $20 bill should be ejected by the cash dispenser
    And a $20 bill should be ejected by the cash dispenser
    And a $10 bill should be ejected by the cash dispenser

    View Slide

  71. TDD vs BDD

    View Slide

  72. TDD
    Hard to apply to existing legacy code
    Inside out
    Fast execution time
    “That is wrong”
    Doing the thing right
    Technical writer/reader
    Low case coverage
    Poor maintainability
    Easy to apply to existing legacy code
    Outside in
    Slow execution time
    “Something is wrong”
    Doing the right thing
    Business writer/reader
    High case coverage
    High maintainability
    BDD

    View Slide

  73. TDD or BDD?

    View Slide

  74. Final Thoughts

    View Slide

  75. View Slide

  76. “It’s a skill!
    Learn it by using it”

    View Slide

  77. Do you release with failing tests?
    Does it depends?

    View Slide

  78. References
    Test Driven Development: By Example by Kent Beck (2002)
    Refactoring by Kent Beck and Martin Fowler (1999)
    Succeeding with Agile by Mike Cohn (2009)
    Working Effectively with Unit Tests by Jay Fields (2014)
    The Art of Unit Testing by Roy Osherove (2013)
    Software Reliability: Principles and Practices by Glenford J. Myers (1976)

    View Slide

  79. Thank you!

    View Slide