DEV Community

Cover image for TDD Sencillo
disced
disced

Posted on

TDD Sencillo


Introducción

Este post lo he basado en el libro del Tio Bob (Robert C. Martin), La artesanía del código limpio. Es una lectura muy recomendable ya que amplía muchos conceptos y se desarrollan de forma más extensa de lo que yo pretendo con este post.

Si te apasiona tanto como a mi el desarrollo de software, te darás cuenta que siempre vas a querer ser mejor desarrollador/a, por lo tanto llegarás a la conclusión de que el TDD aumentará tu habilidad en este sentido y vas a querer ponerlo en práctica.

Qué Es El TDD

Es una forma más de escribir código, podemos decir que es una metodología a la hora de programar. El enfoque principal de este proceso son los (temidos) tests, pero no es para tanto, además, nos ofrece muchas ventajas.

Qué Nos Ofrece

Las ventajas que nos ofrece esta metodología de programar las podemos ver en la siguiente lista:

  • Tener un código fácil de leer y entender.
  • Tener un código poco interconectado entre sí.
  • Tener un código corto y muy segmentado.
  • Tener un código fácil de testear.
  • Asegurarnos que nuestro código funciona bien.
  • Tener un código escalable.
  • En ocasiones se llega al desarrollo de algoritmos complejos que sin realizar TDD es difícil llegar a la misma solución.

Para Qué Utilizarlo

Los programadores lo utilizamos para asegurar que nuestro trabajo está bien hecho y no falla.

En el peor de los casos se utiliza para evitar muertes (como bien ha ocurrido en el pasado por fallos de software, Boeing, Tesla...)

Cómo Se Pone En Marcha

Las Tres Leyes

Para entender y aplicar el TDD se describe mediante 3 leyes o principios básicos que siempre debemos seguir para llevarlo a la práctica.

En mi caso lo entendí al leer dichas leyes y ver ejemplos.

Primera Ley

No escribir nunca un código de producción hasta haber escrito una prueba que falle debido a la falta de dicho código.

Vamos a testear la clase persona por ejemplo, pero en nuestro desarrollo de momento no existe dicha clase, lo que haremos será escribir un test que instancie un objeto de la clase persona.

Segunda Ley

Escribir de un test lo mínimo posible para conseguir que falle o que no compile o ejecute. Resolver el fallo escribiendo código de producción.

En el ejemplo, escribimos una línea de código y el test fallará (no existe la clase persona). A continuación, como hemos escrito lo mínimo posible en el test, ahora escribimos código de producción para que pase la prueba, por lo tanto creamos una clase persona.

Tercera Ley

No escribir más código de producción que el que sea suficiente para pasar la prueba que falla en ese momento. Una vez ha pasado la prueba, escribimos más código de prueba *(volver a la primera ley)*

Para pasar la prueba solo se crea la clase persona y se ejecuta el test, debería de funcionar, entonces ahora hay que escribir otra prueba. Por ejemplo utilizar un método de la clase persona, setName por ejemplo. Esta nueva prueba fallará, esto es bueno y es lo que esperamos que ocurra. Ahora volvemos a la primera ley.

Tercera Ley*

Después de poner en práctica las tres leyes cumplimos el ciclo del TDD, pero antes de empezar un nuevo ciclo lo que debemos hacer si corresponde es refactorizar el código, hacerlo más corto, más sencillo o lo que corresponda en cada caso.

La refactorización del anterior código no debe modificar el comportamiento del código, solo debe modificar el código en sí, y debería de pasar todas las anteriores pruebas.

En este breve ejemplo podemos observar dos cosas:

  • Hemos testeado que nuestro código falla.
  • Hemos testeado que nuestro código funciona.

Estos dos conceptos son importantes porque por lo general, nosotros, los programadores, casi siempre testeamos código para que funcione, en este caso obligamos a que falle para después arreglar el fallo y así asegurarnos que no falla.

ciclo tdd

Cómo Funciona En La Práctica

Vamos a ver el ejemplo anterior de manera práctica y en varios ciclos.

Ciclo Uno

1. Creamos el test que falla

Test clase persona
En este caso uso Javascript y hay que tener en cuenta que si importas un modulo que no se exporte, el test no falla, por lo tanto vamos a escribir un poco mas de código de test para que falle.

person.test.js

import { Person } from "./person.js"

describe('Person Suite', () => {
    test('Create Person', () => {
        const p1 = new Person()
    })
})
Enter fullscreen mode Exit fullscreen mode

Si ejecutamos el test mediante jest veremos que falla, estamos importando un módulo que no existe (esto no falla) y estamos intentando instanciar una clase que no existe, aquí es donde falla.

2. Añadimos código mínimo de producción para arreglar el fallo

Creamos clase persona
person.js

class Person {
}

export { Person }
Enter fullscreen mode Exit fullscreen mode

Con este cambio, el test ya pasa y sabemos que nuestra última versión de código funciona.

3. Fin del ciclo (refactorizar código)

De momento no hay nada que refactorizar, así que volvemos a empezar el ciclo.

Ciclo Dos

1. Creamos el test que falla

Ahora quiero añadir un nombre al objeto persona, así que voy a escribir un test que me permita añadir el nombre utilizando un método de la clase (que aún no existe)

person.test.js

...

    test('Should set person name', () => {
        const p1 = new Person()
        p1.setName('Alice')
})
Enter fullscreen mode Exit fullscreen mode

Al ejecutar la suite de tests, el primer test sigue pasando, pero el nuevo no pasa, no existe el método setName. Por lo tanto vamos a arreglar el código de producción para que pase este test.

2. Añadimos código de producción para arreglar el fallo

person.js

class Person {
    setName(name) {}
}
...
Enter fullscreen mode Exit fullscreen mode

Con este sencillo cambio todos nuestros tests pasan y estamos seguros que nuestra última versión de código funciona correctamente.

3. Fin del ciclo (refactorizar código)

En este paso podríamos refactorizar guardando el nombre en un atributo de la clase por ejemplo, pero vamos a evitar saltar pasos y vamos a otro ciclo.

Ciclo Tres

1. Test qué falla

Obtener el nombre de la persona
person.test.js

...
    test('Should get the name of person', () => {
        const p1 = new Person()
        p1.setName('Alice')

        const name = p1.getName()
        expect(name).toEqual('Alice')
    })
Enter fullscreen mode Exit fullscreen mode

2. Arreglar fallo

person.js


class Person {
    setName(name) {
    }

    getName() {
        return 'Alice'  
    }
}
Enter fullscreen mode Exit fullscreen mode

Ahora el test pasa y sabemos que la última versión de nuestro código funciona correctamente.

Ciclo Cuatro

1. Test qué falla

person.test.js

...
    test('Should get the assigned name of person', () => {
        const name = 'Bob'
        const p1 = new Person()
        p1.setName(name)

                // Parte en la que falla
        const pName = p1.getName()
        expect(pName).toEqual(name)
    })
Enter fullscreen mode Exit fullscreen mode

2. Arreglar el fallo

person.js

class Person {
    name = ''
    setName(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}
Enter fullscreen mode Exit fullscreen mode

Y de esta manera podemos ir progresando en el desarrollo de la clase persona hasta complicarla lo máximo posible y sabiendo siempre que la última versión de nuestro código funciona.

También estaremos obligados de manera implícita a escribir código correcto, el tdd nos obliga a ello.

Referencias

La artesanía del código limpio - Anaya Multimedia

Anaya Multimedia , Cómo escribir código del que se sienta orgulloso... todos los días En \'La artesanía del código limpio\' el legendario Robert C

favicon anayamultimedia.es

Top comments (0)