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

TDD

Christian
October 26, 2012

 TDD

Presentación acerca de TDD para el betabeers de Barcelona (26/10/2012)

Christian

October 26, 2012
Tweet

More Decks by Christian

Other Decks in Programming

Transcript

  1. Christian Soronellas
    Soy desarrollador web
    Windsurf y surf en mi tiempo
    libre :)
    Trabajo en emagister
    Me encanta la comunidad
    OpenSource
    @theUniC github.com/theUniC

    View full-size slide

  2. Antes de empezar

    View full-size slide

  3. Quién no sabe lo qué es un unit-test?

    View full-size slide

  4. Quién tiene o alguna vez ha tenido
    miedo de tocar el código?

    View full-size slide

  5. Quién tiene confianza de subir a
    producción sin romper nada?

    View full-size slide

  6. Objetivos
    · Introducción a la metodología
    · Caso de uso práctico
    · Tips & Best-practices para hacer
    unit-test con #rigor
    @theUniC

    View full-size slide

  7. Qué es TDD?

    View full-size slide

  8. TDD
    · Es una metodología de diseño de software
    @theUniC

    View full-size slide

  9. TDD
    · Es una metodología de diseño de software
    @theUniC
    · Usa test-first cómo punto de entrada

    View full-size slide

  10. TDD
    · Es una metodología de diseño de software
    @theUniC
    · Usa test-first cómo punto de entrada
    · Usa refactoring para eliminar la duplicidad
    de código

    View full-size slide

  11. TDD
    · Es una metodología de diseño de software
    @theUniC
    · Usa test-first cómo punto de entrada
    · Usa refactoring para eliminar la duplicidad
    de código
    · Usa baby-steps para desgranar problemas
    complejos

    View full-size slide

  12. TDD
    · Es una metodología de diseño de software
    @theUniC
    · Usa test-first cómo punto de entrada
    · Usa refactoring para eliminar la duplicidad
    de código
    · Usa baby-steps para desgranar problemas
    complejos
    · Es ideal para usarse conjuntamente con
    unit-tests.

    View full-size slide

  13. @theUniC
    El ciclo virtuoso #riguroso

    View full-size slide

  14. @theUniC
    Fase 1
    El ciclo virtuoso #riguroso

    View full-size slide

  15. @theUniC
    Escribir un test
    que falle
    El ciclo virtuoso #riguroso

    View full-size slide

  16. @theUniC
    Fase 2
    El ciclo virtuoso #riguroso

    View full-size slide

  17. @theUniC
    Escribir el código
    mínimo para que el
    test pase
    El ciclo virtuoso #riguroso

    View full-size slide

  18. @theUniC
    Fase 3
    El ciclo virtuoso #riguroso

    View full-size slide

  19. @theUniC
    Refactorizar aquellas
    partes duplicadas
    El ciclo virtuoso #riguroso

    View full-size slide

  20. Porqué TDD?

    View full-size slide

  21. Proporciona una manera predecible
    de desarrollar

    View full-size slide

  22. Fomenta el uso de los principios
    YAGNI y KISS y de la filosofía DRY

    View full-size slide

  23. Infunde coraje a los desarrolladores

    View full-size slide

  24. Caso de uso
    Desarrollo de una pequeña librería para el cálculo de
    factoriales
    @theUniC

    View full-size slide


  25. Dado un número entero positivo n, el factorial se
    define como el producto de todos los números
    enteros positivos desde 1 hasta n
    wikipedia

    View full-size slide

  26. “De acuerdo con la convención matemática de
    producto vacío, el valor de 0! debe definirse como
    0! = 1.
    wikipedia

    View full-size slide

  27. n! = 1 · 2 · 3 · 4 · ... · (n - 1) · n

    View full-size slide

  28. n! = 1 · 2 · 3 · 4 · ... · (n - 1) · n
    5! = 1 · 2 · 3 · 4 · 5 // 120
    4! = 1 · 2 · 3 · 4 // 24
    0! = 1

    View full-size slide

  29. 5! = 120
    4! = 24
    0! = 1

    View full-size slide

  30. public function testFactorialNumber()
    {
    $fn = new FactorialNumber();
    $this->assertEquals(1, $fn->factorial(0));
    }

    View full-size slide

  31. ~$ phpunit
    PHPUnit 3.7.8 by Sebastian Bergmann.
    Configuration read from phpunit.xml.dist
    PHP Fatal error: Class 'FactorialNumber'
    not found in FactorialNumberTest.php on line
    12
    PHP Stack trace: ...

    View full-size slide

  32. class FactorialNumber
    {
    public function factorial()
    {
    }
    }

    View full-size slide

  33. FAILURES!
    Tests: 1, Assertions: 1, Failures: 1.

    View full-size slide

  34. class FactorialNumber
    {
    public function factorial()
    {
    return 1;
    }
    }

    View full-size slide

  35. OK (1 test, 1 assertion)

    View full-size slide

  36. 5! = 120
    4! = 24
    0! = 1

    View full-size slide

  37. public function testFactorialNumber()
    {
    $fn = new FactorialNumber();
    $this->assertEquals(1, $fn->factorial(0));
    $this->assertEquals(24, $fn->factorial(4));
    }

    View full-size slide

  38. FAILURES!
    Tests: 2, Assertions: 2, Failures: 1.

    View full-size slide

  39. class FactorialNumber
    {
    public function factorial($n)
    {
    if (0 == $n) return 1;
    return 24;
    }
    }

    View full-size slide

  40. OK (1 test, 2 assertions)

    View full-size slide

  41. 5! = 120
    4! = 24
    0! = 1

    View full-size slide

  42. public function testFactorialNumber()
    {
    $fn = new FactorialNumber();
    $this->assertEquals(1, $fn->factorial(0));
    $this->assertEquals(24, $fn->factorial(4));
    $this->assertEquals(120, $fn->factorial(5));
    }

    View full-size slide

  43. FAILURES!
    Tests: 3, Assertions: 3, Failures: 1.

    View full-size slide

  44. class FactorialNumber
    {
    public function factorial($n)
    {
    if (0 == $n) return 1;
    else {
    if (4 == $n) return 24;
    return 120;
    }
    }
    }

    View full-size slide

  45. OK (1 test, 3 assertions)

    View full-size slide

  46. class FactorialNumber
    {
    public function factorial($n)
    {
    if (0 == $n) return 1;
    else {
    if (4 == $n) return 24;
    return 120;
    }
    }
    }

    View full-size slide

  47. class FactorialNumber
    {
    public function factorial($n)
    {
    if (0 == $n) return 1;
    else {
    if (4 == $n) return (4 * 3 * 2 * 1);
    return (5 * 4 * 3 * 2 * 1);
    }
    }
    }

    View full-size slide

  48. class FactorialNumber
    {
    public function factorial($n)
    {
    if (0 == $n) return 1;
    else {
    if (4 == $n) return (4 * 3 * 2 * 1);
    return 5 * $this->factorial(4);
    }
    }
    }

    View full-size slide

  49. class FactorialNumber
    {
    public function factorial($n)
    {
    if (0 == $n) return 1;
    return $n * $this->factorial($n - 1);
    }
    }

    View full-size slide

  50. OK (1 test, 3 assertions)

    View full-size slide

  51. 5! = 120
    4! = 24
    0! = 1

    View full-size slide

  52. Unit-testing best-practices
    Para escribir unit-tests con #rigor

    View full-size slide

  53. Usar nombres de tests descriptivos y
    coherentes

    View full-size slide

  54. public function testFind()
    {
    // ...
    }

    View full-size slide

  55. public function testFindUserByEmailOrderedById()
    {
    // ...
    }

    View full-size slide

  56. public function testFindUserByEmailOrderedById()
    {
    // ...
    }

    View full-size slide

  57. public function testFindUserByEmailOrderedById()
    {
    // ...
    }

    View full-size slide

  58. Usar siempre la mejor aserción
    posible

    View full-size slide

  59. public function testBestAssertionsEver()
    {
    $this->assertTrue(in_array(1, array(1, 2, 3));
    // vs
    $this->assertContains(1, array(1, 2, 3));
    }

    View full-size slide

  60. public function testBestAssertionsEver()
    {
    $this->assertEquals(1, count(array(1)));
    // vs
    $this->assertCount(1, array(1, 2, 3));
    }

    View full-size slide

  61. public function testBestAssertionsEver()
    {
    $this->assertTrue($myObject instanceof MyClass);
    // vs
    $this->assertInstanceOf($myObject, ‘MyClass’);
    }

    View full-size slide

  62. Aislar la unidad de código sobre la
    que se hace test

    View full-size slide

  63. class UsersDao
    {
    private $db;
    public function __construct(DBConnection $db)
    {
    $this->db = $db;
    }
    public function findByEmail($email)
    {
    $sql = sprintf(‘SELECT * FROM users u WHERE email = “%s”’, $email);
    $result = $this->db->query($sql);
    return new User($result);
    }
    }

    View full-size slide

  64. public function testFindByEmail()
    {
    $db = new DBConnection('127.0.0.1', ‘testuser’, ‘p4ssw0rd’, ‘dbname’);
    $usersDao = new UsersDao($db);
    $user = $usersDao->findByEmail(‘[email protected]’);
    $this->assertEquals(‘[email protected]’, $user->getEmail());
    }

    View full-size slide

  65. public function testFindByEmail()
    {
    $queryResult = array(
    ‘id’ => 1,
    ‘email’ => ‘[email protected]’,
    ‘password’ => ‘***’
    );
    $pdoMock = $this->getMock(‘DBConnection’, array(‘query’));
    $pdoMock
    ->expects($this->once())
    ->method(‘query’)
    ->with(
    $this->equalTo(‘SELECT * FROM users u WHERE email = “[email protected]”’)
    )
    ->will($this->returnValue($queryResult))
    ;
    $usersDao = new UsersDao($pdoMock);
    $user = $usersDao->findByEmail(‘[email protected]’);
    $this->assertInstanceOf($user, ‘MyUserClass’);
    $this->assertEquals(‘[email protected]’, $user->getEmail());
    }

    View full-size slide

  66. Lo que viene ahora es el secreto del
    testing

    View full-size slide

  67. The secret in testing is in writing
    testeable code
    Miško Hevery

    View full-size slide

  68. ¡Gracias!
    @theUniC
    github.com/theUniC

    View full-size slide