Prefacio

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

El desarrollo basado en pruebas es una forma de gestionar el miedo durante la programación.

Kent Beck

¡Somos tan inefablemente afortunados! Llevamos años con el desarrollo basado en pruebas.

Han pasado varias décadas desde que los desarrolladores que escribieron el código del Programa Espacial Mercury practicaron el TDD (desarrollo dirigido por pruebas). Las bibliotecas XUnit que facilitan la adopción del desarrollo dirigido por pruebas se remontan al cambio de siglo. De hecho, Kent Beck, que escribió Test-Driven Development: By Example (Addison-Wesley Professional, 2002) y desarrolló el marco JUnit, se refiere a sí mismo como si hubiera "redescubierto" (y no inventado) la práctica del TDD. Esa afirmación es una prueba de su humildad, pero también es la verdad. El TDD es tan antiguo como el propio desarrollo de software.

Entonces, ¿por qué el desarrollo basado en pruebas sigue estando lejos de ser la forma estándar de escribir código? ¿Por qué suele ser la primera práctica que se sacrifica cuando hay presiones de calendario, o cuando hay que recortar los presupuestos de TI, o (mi favorita personal) cuando se desea "aumentar la velocidad del equipo de entrega de software"? Todas estas razones se esgrimen a pesar de la fácil disponibilidad de pruebas empíricas y experimentales de que el TDD reduce el número de defectos, crea un diseño más sencillo y mejora la confianza de los desarrolladores en su propio código.

¿Por qué se adopta el TDD a regañadientes y se abandona fácilmente? Los siguientes argumentos, escuchados a menudo de quienes se resisten a practicarlo, pueden explicar por qué:

No sé por dónde ni cómo empezar.

Quizá la razón más común sea la falta de concienciación y exposición. Como cualquier otra habilidad, escribir código con un estilo basado en pruebas es algo que hay que aprender. Muchos desarrolladores no han tenido el aliciente externo (tiempo, recursos, orientación, estímulo) o la motivación interna (superar las propias reticencias y miedos) para aprender esta habilidad.

El TDD funciona en programas de juguete o durante entrevistas de codificación, pero no al escribir código del "mundo real".

Esto es falso, pero comprensible. La mayoría de los tutoriales y libros sobre desarrollo basado en pruebas -incluido éste- se limitan a elegir ejemplos relativamente sencillos de un dominio obvio. Es difícil escribir un artículo o un libro sobre TDD con código real de una pieza de software extraída de una aplicación implementada comercialmente (por ejemplo, de una institución financiera, un sistema de gestión sanitaria o un automóvil autoconducido). Por un lado, gran parte de ese código del mundo real es propietario y no es de código abierto. Por otra, es tarea del autor mostrar código de un dominio que tenga el mayor atractivo para el mayor público. Sería ilógico, rayano en el oscurantismo, mostrar el TDD en el contexto de un dominio altamente especializado. Hacerlo exigiría, antes que nada, una larga explicación de la jerga arcana y la cantinela de ese dominio. Eso iría en contra del propio propósito del autor: hacer que el TDD sea comprensible, accesible, incluso adorable.

A pesar de estos obstáculos para utilizar código del mundo real en la literatura sobre TDD, los desarrolladores escriben regularmente software de producción utilizando el desarrollo dirigido por pruebas. Quizá el mejor y más convincente ejemplo sea el conjunto de pruebas unitarias del propio marco JUnit. El Kernel de Linux -posiblemente la pieza de software más utilizada del mundo- se está mejorando con pruebas unitarias.

Escribir pruebas a posteriori es suficiente; TDD es demasiado restrictivo y/o pedante.

Resulta más reconfortante oír esto que el discurso ocasional de que "las pruebas unitarias están sobrevaloradas". Escribir pruebas después de escribir código de producción es una mejora con respecto a no escribir ninguna prueba. Cualquier cosa que aumente la confianza de los desarrolladores en su código, reduzca la complejidad accidental y proporcione documentación auténtica es algo bueno. Sin embargo, escribir pruebas unitarias antes de escribir el código de producción proporciona una función forzadora contra la creación de complejidad arbitraria.

TDD nos guía hacia un diseño más sencillo porque proporciona estas dos reglas prácticas como barandillas:

  1. Sólo escribe código de producción para arreglar una prueba que falla.

  2. Refactoriza enérgicamente cuando, y sólo cuando, las pruebas estén en verde.

¿Garantiza el desarrollo basado en pruebas que todo el código que escribamos será automática e inevitablemente el código más sencillo que funcione? No, no lo garantiza. Ninguna práctica, regla, libro o manifiesto puede hacerlo. Depende de las personas que dan vida a estas prácticas garantizar que se consiga y se conserve la simplicidad.

El contenido de este libro explica e instruye sobre cómo funciona el desarrollo dirigido por pruebas en tres lenguajes de programación diferentes. Su propósito es inculcar en los desarrolladores el hábito y la autoconfianza para utilizar TDD como práctica habitual. Puede que ese propósito sea ambicioso, pero espero que no sea esquivo.

¿Qué es el desarrollo basado en pruebas?

El desarrollo dirigido por pruebas es una técnica de diseño y estructuración del código que fomenta la simplicidad y aumenta la confianza en el código, incluso a medida que aumenta su tamaño.

Veamos las distintas partes de esta definición.

Una técnica

El desarrollo basado en pruebas es una técnica. Es cierto que esta técnica nace de un conjunto de creencias sobre el código, a saber:

  • Esa simplicidad -el arte de maximizar la cantidad de trabajo no realizado- es esencial1

  • Que la obviedad y la claridad son más virtuosas que la astucia

  • Que escribir código despejado es un componente clave para tener éxito

A pesar de estar arraigado en estas creencias, en la práctica, el TDD es una técnica. Al igual que montar en bici, amasar masa o resolver ecuaciones diferenciales, es una habilidad con la que nadie nace y que todo el mundo tiene que aprender.

Aparte de esta sección, este libro no se detiene en el sistema de creencias que hay detrás del desarrollo dirigido por pruebas. Se da por supuesto que ya lo suscribes o que estás dispuesto a probar el TDD como una habilidad nueva (u olvidada).

La mecánica de esta técnica -escribir primero una prueba unitaria que falla, luego escribir enérgicamente el código suficiente para que pase, y después tomarse el tiempo necesario para limpiarla- ocupa la mayor parte de este libro. Tendrás muchas oportunidades de probar esta técnica por ti mismo.

A fin de cuentas, es más satisfactorio aprender una habilidad e imbuirse de las creencias que la apoyan, igual que montar en bici es más agradable si te recuerdas a ti mismo que es bueno para tu salud y para el medio ambiente.

Diseñar y estructurar el código

Observa que el TDD no consiste fundamentalmente en probar el código. Es cierto que utilizamos pruebas unitarias para dirigir el código, pero el propósito de TDD es mejorar el diseño y la estructura del código.

Este enfoque es vital. Si TDD sólo tratara de las pruebas, no podríamos argumentar de forma eficaz a favor de escribir las pruebas antes de escribir el código de negocio, en lugar de después. Es el objetivo de diseñar un software mejor lo que nos impulsa; las pruebas son simplemente un vehículo para este progreso. Las pruebas unitarias que obtenemos mediante TDD son una ventaja añadida; el beneficio principal es la simplicidad del diseño que conseguimos.

¿Cómo conseguimos esta simplicidad? Mediante el mecanismo de refactorización rojo-verde, que se describe detalladamente al principio del Capítulo 1.

Un sesgo hacia la simplicidad

La sencillez no es una mera noción esotérica. En software, podemos medirla. Menos líneas de código por función, menor complejidad ciclomática, menos efectos secundarios, menores requisitos de tiempo de ejecución o memoria: cualquier subconjunto de estos (u otros) requisitos puede tomarse como medida objetiva de simplicidad.

El desarrollo basado en pruebas, al obligarnos a crear "la cosa más sencilla que funcione" (es decir, la que consiga superar todas las pruebas), nos empuja constantemente hacia estas métricas de simplicidad. No se nos permite añadir código superfluo "por si lo necesitamos" o porque "lo vemos venir". Primero debemos escribir una prueba que falle para justificar la escritura de dicho código. El hecho de escribir primero la prueba actúa como una función forzadora que nos obliga a enfrentarnos antes a una complejidad arbitraria. Si la función que vamos a desarrollar está mal definida, o nuestra comprensión de ella es defectuosa, nos resultará difícil escribir una buena prueba desde el principio. Esto nos obligará a abordar estos problemas antes de escribir una línea de código de producción. Ésta es la virtud de TDD: al ejercer la disciplina de conducir nuestro código a través de pruebas, eliminamos la complejidad arbitraria en cada coyuntura.

Esta virtud no es mística: utilizar el desarrollo basado en pruebas no reducirá a la mitad tu tiempo de desarrollo, las líneas de código o el recuento de defectos. Lo que te permitirá es detener la tentación de introducir una complejidad artificial y artificiosa. El código resultante -impulsado por la disciplina de escribir primero las pruebas que fallan- surgirá como la forma más sencilla de hacer el trabajo, es decir, el código más simple que satisfaga las necesidades de las pruebas.

Mayor confianza

El código debe inspirar confianza, especialmente el código del que somos autores. Esta confianza, aunque en sí misma es un sentimiento nebuloso, se basa en una expectativa de previsibilidad. Confiamos en las cosas cuyo comportamiento podemos prever. Si la cafetería de la esquina me cobra de menos un día y al día siguiente me cobra de más por la misma cantidad, es probable que pierda la confianza en el personal, aunque los dos días me salga a cuenta. Es propio de la naturaleza humana que valoremos la regularidad y la previsibilidad incluso más que el valor neto. El jugador más afortunado del mundo, que tal vez acabe de ganar 10 veces seguidas en una mesa de ruleta, no diría que "confía" o tiene "confianza" en la rueda. Nuestra afinidad por la previsibilidad sobrevive incluso a la suerte tonta.

El desarrollo basado en pruebas aumenta la confianza en nuestro código porque cada nueva prueba flexibiliza el sistema de formas nuevas y no probadas anteriormente, ¡literalmente! Con el tiempo, el conjunto de pruebas que creamos nos protege contra los fallos de regresión.

Esta batería de pruebas en constante aumento es la razón de que, a medida que crece el tamaño del código, también lo hace su calidad y nuestra confianza en él.

¿A quién va dirigido este libro?

Este es un libro para desarrolladores, es decir, para personas que escriben software.

Hay muchos títulos profesionales que acompañan a esta vocación: "ingeniero de software", "arquitecto de aplicaciones", "ingeniero devops", "ingeniero de automatización de pruebas", "programador", "hacker", "susurrador de código" e innumerables más. Los títulos pueden ser impresionantes o humildes, modernos o solemnes, tradicionales o modernos. Sin embargo, lo único que tienen en común las personas que profesan estos títulos es lo siguiente: pasan al menos una parte de su semana -si no todos los días- delante de un ordenador, leyendo y/o escribiendo código fuente.

He elegido el término desarrolladores para representar a esta comunidad de la que soy un miembro humilde y agradecido.

Escribir código es una de las actividades más liberadoras e igualitarias que uno pueda imaginar. En teoría, todo lo que uno necesita como destreza física es la posesión de un cerebro. La edad, el género, el sexo, la nacionalidad, el origen nacional... nada de esto debería ser una barrera. Tener discapacidades físicas no debería ser una barrera.

Sin embargo, sería ingenuo suponer que la realidad es tan pulcra o justa como eso. El acceso a los recursos informáticos no es equitativo. Es necesario un cierto nivel de riqueza, libertad y seguridad. El acceso se ve aún más obstaculizado por un software mal escrito, un hardware mal diseñado y una miríada de otras limitaciones de uso que impiden que todas las personas aprendan a programar basándose únicamente en su interés y esfuerzo.

He intentado que este libro sea accesible al mayor número de personas posible. En particular, he intentado hacerlo accesible a las personas con discapacidades físicas. Las imágenes tienen texto alternativo para facilitar la lectura electrónica. El código está disponible en GitHub. Y la prosa es sencilla.

En términos de experiencia, este libro está destinado tanto a personas que aún están aprendiendo a programar como a quienes ya saben programar. Si te estás iniciando en uno (o más) de los tres lenguajes de este libro, estás dentro del público al que va dirigido.

Sin embargo, este libro no enseña los fundamentos de la programación en ningún lenguaje, incluidos Go, JavaScript o Python. La capacidad de leer y escribir código en al menos uno de los lenguajes de programación es un requisito. Si eres absolutamente nuevo en la programación, sería conveniente que afianzaras los fundamentos de la escritura de código en uno de los tres lenguajes antes de continuar con este libro.

El punto óptimo para este libro abarca desde desarrolladores que han superado sus primeras incursiones en la programación hasta arquitectos experimentados, como se muestra en la Figura P-1. (Kent Beck es un caso atípico). (Kent Beck es un caso atípico).

This book is for developers who are early in their careers, are in mid-career, or are seasoned developers. Even industry experts can find valuable insights in this book. However, people who are learning how to program may find the examples difficult to follow. And Kent Beck is an outlier!
Figura P-1. Este es un libro para desarrolladores de software

Escribir código puede ser, por turnos, estimulante y exasperante. Sin embargo, incluso en su momento más frustrante, siempre debería haber algo más que un atisbo de optimismo y una pizca de confianza en que podemos hacer que el código cumpla nuestras órdenes. Con perseverancia, descubrirás que tu viaje a través de este libro es fructífero y que la alegría de escribir código de forma dirigida por pruebas es algo que querrás saborear mucho después de haber terminado de leer el Capítulo 14.

¿Cuáles son los requisitos previos para leer este libro?

Por equipamiento y destreza técnica, deberías:

  • Tener acceso a un ordenador con conexión a Internet.

  • Poder instalar y eliminar software en ese ordenador. Es decir, tu acceso a ese ordenador no debe estar restringido; en la mayoría de los casos esto requeriría tener acceso de "Administrador" o "Superusuario" en ese ordenador.

  • Ser capaz de iniciar y utilizar un programa shell, un navegador web, un editor de texto y, opcionalmente, un entorno de desarrollo integrado (IDE) en ese ordenador.

  • Tener instaladas (o poder instalar) las herramientas de ejecución de uno de los lenguajes utilizados en este libro.

  • Ser capaz de escribir y ejecutar un programa sencillo - "Hola Mundo"- en uno de los lenguajes utilizados en este libro.

"Configurar tu entorno de desarrollo" en el Capítulo 0 tiene más detalles sobre la instalación.

Cómo leer este libro

El tema de este libro es "cómo hacer desarrollo dirigido por pruebas en Go, JavaScript y Python". Aunque los conceptos tratados son aplicables a los tres lenguajes, el tratamiento de cada uno de ellos requiere cierta separación del material en cada capítulo. La mejor forma de aprender el desarrollo basado en pruebas (como cualquier otra habilidad adquirida) es mediante la práctica. Te animo tanto a leer el texto como a escribir el código por tu cuenta. Llamo a este estilo "seguir el libro", porque incluye lectura activa y codificación activa.

Consejo

Para aprovechar al máximo este libro, escribe el código del ejemplo Dinero en los tres idiomas.

La mayoría de los capítulos tienen secciones de propósito general que son aplicables a las tres lenguas. A éstas les siguen secciones específicas de cada lengua, en las que se describe y desarrolla el código de una de las tres lenguas. Estas secciones específicas de cada lenguaje están siempre claramente marcadas por sus títulos: Go, JavaScript o Python. Al final de cada capítulo hay una o dos secciones que resumen lo que hemos conseguido hasta ahora y lo que viene a continuación.

Los capítulos 5 a 7 son únicos en la medida en que cada uno trata exclusivamente de uno de los tres lenguajes: Go, JavaScript y Python, respectivamente.

La Figura P-2 muestra un diagrama de flujo que describe la disposición de este libro y las distintas formas de seguirlo.

This book can be read sequentially from chapter 0 to chapter 14. Be aware that chapter 5 is exclusively about Go, chapter 6 is about JavaScript, and chapter 7 is about Python. If you're following this book one or two languages at a time, you may need to read these chapters out of order.
Figura P-2. Diagrama de flujo sobre cómo leer este libro

He aquí algunos "itinerarios de lectura" para seguir mejor este libro.

Sigue el Libro Lengua por Lengua

Recomiendo esta vía si se dan una o más de estas condiciones en tu caso:

  1. Estoy deseando sumergirme en una de estas lenguas antes de abordar las otras dos.

  2. Tengo especial curiosidad (¡o escepticismo!) por saber cómo funciona el TDD en uno de los tres idiomas.

  3. Aprendo mejor trabajando en una lengua cada vez, que en varias lenguas simultáneamente.

Sigue el diagrama de flujo mostrado en la Figura P-2 línea por línea. Por ejemplo, si quieres aprender primero TDD en Go, sáltate las secciones marcadas con JavaScript y Python en la primera lectura. Luego haz una segunda lectura del libro para JavaScript, y una tercera para terminar con Python. O puedes hacer los lenguajes en un orden diferente. La segunda y la tercera pasadas deberían ser más rápidas que la primera; sin embargo, ¡prepárate para las peculiaridades de cada lenguaje!

Si sigues el libro de este modo, descubrirás que escribir el código sucesivamente en cada lenguaje te proporciona una mayor comprensión de TDD como principio, más allá delos detalles de las pruebas como característica del lenguaje. Adquirir el hábito de escribir pruebas es necesario; sin embargo, comprender las razones por las que el desarrollo basado en pruebas funciona en todos los lenguajes es aún más importante.

Sigue el Libro primero en dos lenguas y luego en la tercera lengua

Te recomiendo esta vía si te identificas con alguna de las siguientes afirmaciones:

  1. Quiero construir y comparar las soluciones al mismo problema en dos idiomas.

  2. Me siento menos cómodo con una de las lenguas y quiero abordarla después de las otras dos.

  3. Puedo codificar en dos idiomas a la vez, pero me resultaría difícil hacer malabarismos con los tres a la vez.

Sigue el diagrama de flujo que se muestra en la Figura P-2 de dos en dos. Cuando hayas terminado de seguir el problema del dinero para dos lenguas, haz una segunda pasada por el libro para seguir la tercera lengua.

Puede ocurrir que quieras seguir dos lenguas en la primera pasada, pero no puedas decidir qué lengua aplazar a una segunda lectura. Aquí tienes algunas sugerencias para elegir dos de las tres lenguas:

  1. ¿Quieres contrastar un lenguaje tipado dinámicamente con otro tipado estáticamente y mantener simple la pila tecnológica del lenguaje? Sigue primero Go y Python, y después JavaScript.

  2. ¿Estás preparado para aprender formas contrastadas de construir código en dos lenguajes diferentes y listo para enfrentarte a las variaciones de la pila tecnológica? Sigue Go y JavaScript primero, y Python después.

  3. ¿Quieres comparar y contrastar dos lenguajes tipados dinámicamente? Sigue primero a JavaScript y Python, y después a Go.

Si lees el libro de esta forma, descubrirás rápidamente las similitudes y diferencias de hacer TDD en varios lenguajes. Aunque las variaciones sintácticas y de diseño de los lenguajes crean diferencias obvias, te sorprenderá lo profundamente que la disciplina del TDD impregna tu forma de escribir código, independientemente del lenguaje en el que lo hagas.

Sigue el Libro en las Tres Lenguas Simultáneamente

Recomiendo esta vía si alguna de estas afirmaciones se aplica a ti:

  1. Quieres sacar el máximo partido aprendiendo los contrastes y similitudes de las tres lenguas.

  2. Te resulta más fácil leer un libro de principio a fin en lugar de darle varias pasadas.

  3. Tienes cierta experiencia en los tres idiomas, pero no has practicado TDD en ninguno de ellos.

Si puedes escribir código en tres lenguajes simultáneamente sin agobiarte, te recomiendo esta vía.

Independientemente del camino que elijas, ten en cuenta que cuando escribas código, probablemente te enfrentarás a retos que tienen que ver con tu entorno de desarrollo específico. Aunque se ha comprobado que el código de este libro es correcto (y su compilación de integración continua es ecológica), eso no significa que vaya a funcionar en tu ordenador a la primera. (Al contrario, casi puedo garantizarte que encontrarás interesantes tramos empinados en la curva de aprendizaje). Una de las principales ventajas del TDD es que controlas la velocidad a la que avanzas. Cuando te atasques, ve más despacio. Si avanzas en incrementos más pequeños, es más fácil encontrar dónde se desvió el código. Escribir software significa enfrentarse a dependencias erróneas, conexiones de red poco fiables, herramientas extravagantes y los mil choques naturales de los que es heredero el código. Ve más despacio cuando te sientas abrumado: haz tus cambios más pequeños y discretos. Recuerda: ¡el TDD es una forma de gestionar el miedo a escribir código!

Convenciones utilizadas en este libro

Hay dos categorías de convenciones utilizadas en este libro que requieren explicación: las tipográficas y las contextuales.

Convenciones tipográficas

La prosa de este libro está en el tipo de letra utilizado en esta frase. Está pensada para ser leída y no para ser introducida literalmente como código. Cuando hay palabras utilizadas en prosa que también se utilizan en código -como class, interface o Exception- se utiliza un tipo de letra de anchura fija. Esto te avisa de que el término se utiliza o se utilizará -escrito exactamente igual- en código.

Los segmentos de código más largos se separan en sus propios bloques, como se muestra a continuación.

package main

import "fmt"

...1

func main() {
    fmt.Println("hello world")
}
1

Las elipsis significan que se ha omitido código o salida irrelevante.

Todo lo que hay en un bloque de código es, o bien algo que escribes literalmente, o bien algo que el programa produce como salida literal, con dos excepciones.

  1. Dentro de los bloques de código, se utilizan elipses (...) para indicar código omitido o salida omitida. En ambos casos, lo que se omite es irrelevante para el tema actual. No debes escribir estas elipses en el código ni esperar verlas en la salida. Un ejemplo se muestra en el bloque de código anterior.

  2. Dentro de los bloques de código que muestran salida, puede haber valores efímeros -direccionesde memoria, marcas de tiempo, tiempo transcurrido, números de línea, nombres de archivo autogenerados, etc.- quecasi con toda seguridad serán diferentes para ti. Cuando leas esa salida, puedes ignorar con seguridad los valores efímeros concretos, como las direcciones de memoria del siguiente bloque:

AssertionError: <money.Money object at 0x10417b2e0> !=
                <money.Money object at 0x10417b400>
Consejo

Los consejos son sugerencias que pueden serte útiles mientras escribes código. Están separadas del texto principal para facilitar su consulta.

Importante

La información importante que es vital para el tema se identifica así. A menudo hay hipervínculos o notas a pie de página a recursos que proporcionan más información sobre el tema.

En la mayoría de los capítulos, hay un amplio desarrollo y discusión de código en cada uno de los tres lenguajes. (Las excepciones son los capítulos 5, 6 y 7, que tratan exclusivamente de Go, JavaScript y Python respectivamente). Para separar la discusión de cada lenguaje, un encabezamiento y un icono en el margen indican el lenguaje que es competencia exclusiva de esa sección. Mantén los ojos bien abiertos para ver estos tres encabezamientos e iconos:

  • Ve a Go

  • JavaScript JavaScript

  • Python Python

Convenciones léxicas

Este libro discute conceptos básicos de software y respalda esas discusiones con código en tres lenguajes diferentes. Los lenguajes son lo suficientemente diferentes en su terminología individual como para plantear retos a la hora de discutir conceptos comunes.

Por ejemplo, Go no tiene clases ni herencia basada en clases. El sistema de tipos de JavaScript tiene objetos basados en prototipos, lo que significa que todo es en realidad un objeto, incluidas las cosas que normalmente se consideran clases. Python, tal como se utiliza en este libro, tiene los objetos basados en clases más "tradicionales".2 Una frase como "Crearemos una nueva clase llamada Money" no sólo es confusa, sino que es totalmente incorrecta cuando se interpreta en el contexto de Go.

Para reducir las posibilidades de confusión, he adoptado la terminología general que aparece en la Tabla P-1 para referirme a los conceptos clave.

Tabla P-1. Terminología general utilizada en este libro
Plazo Significado Equivalente en Go Equivalente en JavaScript Equivalente en Python

Entidad

Un concepto de dominio singular, con significado independiente; un sustantivo clave

Tipo de estructura

Clase

Clase

Objeto

Una instancia de una Entidad; un sustantivo reificado

Ejemplo de estructura

Objeto

Objeto

Secuencia

Una lista secuencial de Objetos de longitud dinámica

Corta

Matriz

Matriz

Hashmap

Un conjunto de pares (clave-valor), donde tanto las claves como los valores pueden ser Objetos arbitrarios y no puede haber dos claves iguales

Mapa

Mapa

Diccionario

Función

Conjunto de operaciones con un nombre determinado; las Funciones pueden (o no) tener entidades con entradas y salidas, pero no están asociadas directamente a ninguna Entidad

Función

Función

Función

Método

Función asociada a una Entidad. Se dice que un método es "llamado sobre" una instancia de esa Entidad (es decir, un Objeto)

Método

Método

Método

Señalizar un error

Mecanismo por el que una Función o Método indica un fallo

Valor de retorno de error (convencionalmente, el último valor de retorno de una función/método)

Lanza una excepción

Provocar una excepción

El objetivo es utilizar términos que expliquen los conceptos sin favorecer la terminología de un lenguaje de programación sobre otros. Al fin y al cabo, lo más importante de este libro debería ser que el desarrollo basado en pruebas es una disciplina que puede practicarse en cualquier lenguaje de programación.

En las secciones del libro que tratan de uno de los tres lenguajes (que están claramente marcadas en el encabezamiento), el texto utiliza términos específicos del lenguaje. Por ejemplo, en una sección de Go, habrá instrucciones para "definir una nueva estructura llamada Money." El contexto deja claro que esta instrucción es específica de un lenguaje concreto.

Utilizar ejemplos de código

El código fuente de este libro está disponible en https://github.com/saleem/tdd-book-code.

Si tienes una pregunta técnica o un problema al utilizar los ejemplos de código, envía un correo electrónico a

Este libro está aquí para ayudarte a aprender y practicar el arte del desarrollo basado en pruebas. En general, puedes utilizar cualquier código proporcionado en este libro en tus programas y documentación. No es necesario que te pongas en contacto con nosotros para pedirnos permiso, a menos que estés reproduciendo una parte importante del código. Por ejemplo, escribir un programa que utilice varios trozos de código de este libro no requiere permiso. Vender o distribuir ejemplos de libros de O'Reilly sí requiere permiso. Responder a una pregunta citando este libro y el código de ejemplo no requiere permiso. Incorporar una cantidad significativa de código de ejemplo de este libro en la documentación de tu producto sí requiere permiso.

Agradecemos la atribución, pero en general no la exigimos. Una atribución suele incluir el título, el autor, la editorial y el ISBN. Por ejemplo: "Learning Test-Driven Development por Saleem Siddiqui (O'Reilly). Copyright 2022 Saleem Siddiqui, 978-1-098-10647-8".

Si crees que el uso que haces de los ejemplos de código no se ajusta al uso legítimo o al permiso concedido anteriormente, no dudes en ponerte en contacto con nosotros en

Cómo contactar con nosotros

Tenemos una página web para este libro, donde se enumeran erratas, ejemplos y cualquier información adicional. Puedes acceder a esta página en https://oreil.ly/learningTDDbook.

Envía un correo electrónico para comentar o hacer preguntas técnicas sobre este libro.

Para obtener noticias e información sobre nuestros libros y cursos, visita http://oreilly.com.

TDD-Los porqués

Las críticas al TDD -y, por ende, a este libro- pueden adoptar diversas formas. Algunas son creativamente humorísticas, como la refrescante viñeta de Jim Kersey que se muestra en la Figura P-3.

Comic strip with two robotic characters. Character A is wondering how TDD applies to building a bridge. Character B says that step one is to write a failing test, which in this case amounts to driving your car over the cliff! Character A doesn't want to be on the bridge-building project anymore. Character B says: we can discuss that later; take these keys!
Figura P-3. Humor TDD: ¡no cruces un puente que aún no has construido! (Fuente: https://robotkersey.com)

Menos jocosamente, es natural que tengas preguntas sobre el contenido y la estructura del libro. Lo que sigue son respuestas a algunas de esas preguntas.

¿Por qué este libro utiliza Go, JavaScript y Python?

Este libro utiliza Go, JavaScript y Python como los tres lenguajes con los que demostrar la práctica del desarrollo dirigido por pruebas. Es una buena pregunta: ¿por qué estos tres lenguajes?

He aquí algunas razones.

1. Variedad

Las tres lenguas de este libro representan una diversidad de opciones de diseño, como se muestra en la Tabla P-2.

Tabla P-2. Comparación entre Go, JavaScript y Python
Función Ve a JavaScript Python

Orientado a objetos

"Sí y no"

Sí (como lenguaje compatible con ES.next)

Tipos estáticos frente a tipos dinámicos

Tipado estáticamente

Tipado dinámico

Tipado dinámico

Tipos explícitos vs. implícitos

Mayoritariamente explícitos, los tipos de variables pueden ser implícitos

Tipado implícito

Tipado implícito

Coerción automática de tipos

Sin coacción de tipo

Coerción parcial de tipos (para Booleano, Número, Cadena, Objeto). Sin coerción para tipos arbitrarios class

Alguna coerción de tipo implícita (por ejemplo, 0 y "" son falsos)

Mecanismo de excepción

Por convención, el segundo tipo de retorno de los métodos es error, la persona que llama debe comprobar explícitamente si es nil o no

La palabra clave throw se utiliza para señalar una Excepción y try ... catch se utiliza para responder a ella

La palabra clave raise se utiliza para señalar una Excepción y try ... except se utiliza para responder a ella

Genéricos

Todavía no.

No es necesario debido a la tipificación dinámica

No es necesario debido a la tipificación dinámica

Apoyo a las pruebas

Parte del lenguaje (por ejemplo, el paquete testing y el comando go test ); bibliotecas disponibles (por ejemplo, stretchr/testify)

No forma parte del lenguaje, hay muchas bibliotecas disponibles (por ejemplo, Jasmine, Mocha, Jest)

Parte del lenguaje (es decir, la unittest biblioteca); bibliotecas disponibles (por ejemplo, PyTest)

2. Popularidad

Python, JavaScript y Go son los tres lenguajes nuevos que más desean aprender los desarrolladores, según se desprende de varias encuestas anuales realizadas por Stack Overflow en 2017, 2018, 2019 y 2020. La Figura P-4 muestra el resultado de la encuesta de 2020.

In the 2020 Stack Overflow survey, 30% of developers wanted to learn Python, 18.5% wanted to learn JavaScript, and 17.9% wanted to learn Go. This applies to developers not yet programming in that specific language.
Figura P-4. Nuevos lenguajes más deseables de aprender, según una encuesta realizada a desarrolladores por Stack Overflow

En la encuesta Stack Overflow 2021, TypeScript sube al segundo puesto, relegando a JavaScript y Go al tercer y cuarto lugar, respectivamente. Python conserva su primer puesto.

Sintácticamente, TypeScript es un superconjunto estricto de JavaScript. Por lo tanto, se podría argumentar que todo desarrollador que desee aprender TypeScript tiene que saber JavaScript. Albergo la esperanza de que los desarrolladores de TypeScript también encuentren valioso este libro.

3. Una razón personal

Durante los últimos cinco años aproximadamente, he tenido la oportunidad de trabajar en varios proyectos en los que la pila tecnológica incluía uno de estos tres como lenguaje de programación principal. Al trabajar con otros desarrolladores, me di cuenta de que, en general, su afán por aprender y practicar TDD se veía igualado por su incapacidad para encontrar recursos (o reunir la disciplina) para hacerlo. Querían practicar TDD, pero no sabían cómo o no encontraban tiempo para ello. Resulta revelador que esto fuera tan cierto para los desarrolladores experimentados como para los "novatos".

Espero que este libro sirva tanto de guía práctica como de fuente de inspiración para quienes deseen aprender y practicar TDD en cualquier lenguaje, no sólo en Go, JavaScript o Python.

¿Por qué no esta otra lengua?

Para empezar, existe un gran número de lenguajes de programación. Cabría la posibilidad de escribir media docena de libros como éste y aun así cubrir sólo una pequeña fracción de los lenguajes que los desarrolladores de todo el mundo utilizan a diario para escribir código con fines académicos, empresariales y recreativos.3

Además, ya existe un libro excelente sobre el desarrollo dirigido por pruebas en Java. La obra seminal de Kent Beck es lo que me inspiró, al igual que a innumerables desarrolladores, a enamorarme del arte y la ciencia de TDD. También engendró el "problema del dinero" que es uno de los temas principales de este libro.

Estoy seguro de que hay muchos otros lenguajes para los que sería beneficiosa una guía práctica de TDD. ¿Qué tal R? ¿O SQL? ¿O incluso COBOL?

Permíteme asegurarte que la referencia a COBOL no era ni un argumento de paja ni un golpe bajo. A mediados de la década de 2000, trabajé en un proyecto en el que demostré la capacidad de hacer TDD en COBOL utilizando COBOLUnit. ¡Fue lo más divertido que he hecho en un lenguaje que tiene más de una década más que yo!

Espero que recojas el manto. Que aprendas, enseñes y defiendas las habilidades y la disciplina necesarias para practicar el desarrollo basado en pruebas en otros lenguajes. Que escribas un blog, un proyecto de código abierto o el próximo libro de esta serie.

¿Por qué este libro tiene un "Capítulo 0"?

La gran mayoría de los lenguajes de programación utilizan la indexación basada en 0 para las matrices y otras secuencias contables.4 Esto es ciertamente cierto para los tres lenguajes de programación que constituyen la base de este libro. En cierto sentido, este libro honra la rica historia de la cultura de la programación numerando los capítulos empezando por 0.

También quiero rendir homenaje al propio número cero, que es una idea radical. Charles Seife ha escrito todo un libro sobre este número solitario. Al trazar la historia del cero, Seife señala las reservas que los griegos tenían ante un número que no representa nada:

En ese universo [el griego] no existe la nada. No existe el cero. Por ello, Occidente no pudo aceptar el cero durante casi dos milenios. Las consecuencias eran nefastas. La ausencia del cero frenaría el crecimiento de las matemáticas, ahogaría la innovación en la ciencia y, de paso, desordenaría el calendario. Antes de poder aceptar el cero, los filósofos de Occidente tendrían que destruir su universo.

Charles Seife, Cero: la biografía de una idea peligrosa

A riesgo de ponernos demasiado sublimes: el desarrollo basado en pruebas ocupa hoy en la cultura de la programación un lugar similar al que ocupó el cero en la filosofía occidental hace unos milenios. Existe una resistencia a adoptarlo, nacida de una extraña combinación de desprecio, malestar y la creencia de que es demasiado alboroto por nada. "¿Por qué tengo que ser fastidioso escribiendo pruebas primero? ¡Ya sé cómo voy a codificar la función!". "El desarrollo basado en pruebas es pedante: sólo funciona en teoría y nunca en la práctica". "Escribir pruebas después de haber terminado de escribir el código de producción es al menos tan eficaz, si no más, que escribir pruebas primero". ¡Estas y otras objeciones al TDD hacen que se parezca al número cero en lo radical que es!

De todos modos, la práctica de que un libro tenga un Capítulo 0 no es del todo radical. Carol Schumacher ha escrito un libro entero titulado Capítulo Cero: Nociones Fundamentales de Matemática Abstracta, que es un libro de texto estándar de matemáticas avanzadas en muchos planes de estudios universitarios. No hay premio por adivinar con qué capítulo numerado empieza el libro.

La Dra. Schumacher, en el Manual del Instructor de su libro, dice algo que me ha parecido esclarecedor:

Tu tarea como escritor es dar las pistas adecuadas a tus lectores, pistas que les faciliten al máximo la comprensión de lo que intentas decir.

Carol Schumacher, Manual de recursos del instructor para utilizar con el Capítulo Cero

He seguido este consejo al pie de la letra. Desde un punto de vista pragmático, un título que contenga "0" ayuda a diferenciar el Capítulo 0 del tratado que le sigue. El Capítulo 1 de este libro nos introduce en un viaje hacia el TDD que continuará a lo largo de la docena de capítulos siguientes. El Capítulo 0 trata de describir qué es ese viaje, qué debemos saber y tener antes de embarcarnos en él, y qué esperar cuando estemos en él.

Con las aclaraciones fuera del camino, ¡pasemos directamente al Capítulo 0!

1 Esta definición de simplicidad está consagrada en uno de los 12 principios del Manifiesto Ágil.

2 Python es muy fluido en su apoyo a la programación orientada a objetos (POO). Por ejemplo, consulta prototype.pyque implementa en Python objetos basados en prototipos.

3 Aunque es poco probable que un libro sobre TDD en un determinado lenguaje obtenga la aprobación de los editores. ¡Su nombre empieza por "Cerebro" y termina con un improperio!

4 Lua es una notable excepción. Mi amigo Kent Spillner dio una vez una fascinante charla sobre este tema, que resumí aquí.

Get Aprender el desarrollo basado en pruebas now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.