Introducción: por qué TDD no es una religión, sino un salvavidas
\n\nImagina que estás reparando el cableado en una casa vieja. Apagas el interruptor general, pero aún así tienes miedo de meter las manos en el panel. Así se siente aproximadamente un desarrollador que hace cambios en un proyecto sin pruebas. Especialmente en Go, un lenguaje donde el tipado estático da una falsa sensación de seguridad.
\n\nEl desarrollo guiado por pruebas (TDD) en Go no es una tendencia de moda ni un ritual sectario. Es una metodología que transforma el miedo a la refactorización en confianza. Según un estudio de IBM, los proyectos con TDD muestran un 40% menos de defectos. Y en Go, donde el compilador ya elimina la mitad de los errores, TDD remata el 50% restante.
\n\nEn este artículo no daremos conferencias. Tomaremos una tarea real: escribiremos un pequeño servicio HTTP para acortar enlaces. Y recorreremos todo el camino del TDD: desde la prueba roja hasta la verde y la refactorización. ¡Allá vamos!
\n\n¿Qué es realmente TDD?
\n\nSi has oído hablar de Red-Green-Refactor, ya estás al tanto. Si no, recuerda tres pasos simples:
\n\n- \n
- Red — escribimos una prueba que falla a propósito (porque la funcionalidad aún no existe). \n
- Green — escribimos el código mínimo para que la prueba pase. No ideal, sino simplemente funcional. \n
- Refactor — mejoramos el código sin cambiar su comportamiento. Las pruebas son nuestro seguro. \n
En Go, este ciclo es especialmente agradable gracias al paquete integrado testing. No necesitas instalar jest o pytest; todo está ya en la biblioteca estándar. Pero muchos principiantes ignoran las pruebas, pensando que Go ya es "seguro". Y se equivocan.
¿Por qué TDD en Go funciona mejor que en otros lenguajes?
\n\nA la comunidad de Go le encanta la simplicidad. Aquí TDD no se convierte en una burocracia de mocks y stubs. En su lugar, escribes pruebas basadas en tablas (table-driven tests): compactas, legibles, claras. Un caso de prueba, una línea. Y sí, las pruebas en Go son rápidas. Milisegundos para cientos de casos es lo normal.
\n\nPor cierto, en el blog oficial de Go se ha destacado en repetidas ocasiones: "Las pruebas son documentación". Si tu prueba se lee como una especificación, lo estás haciendo bien.
\n\nConfigurando el entorno: qué necesitas para empezar
\n\nSupongo que ya tienes Go instalado. Si no, brew install go o apt install golang-go. Verifica la versión: go version. Para este artículo, basta con Go 1.21+.
Creemos el proyecto:
\n\nmkdir url-shortener-tdd\ncd url-shortener-tdd\ngo mod init url-shortener\n\nListo. Sin frameworks, solo la biblioteca estándar y desarrollo guiado por pruebas en Go.
\n\nEscribimos la primera prueba: Red
\n\nSupongamos que queremos una función Shorten(url string) string que convierta una URL larga en un hash corto. Todavía no existe, y eso es genial. Escribamos la prueba:
// shortener_test.go\npackage main\n\nimport "testing"\n\nfunc TestShorten(t *testing.T) {\n url := "https://pythonlib.ru/very/long/path?with=params&and=stuff"\n result := Shorten(url)\n\n if len(result) == 0 {\n t.Error("Shorten devolvió una cadena vacía")\n }\n\n if len(result) > 10 {\n t.Errorf("Esperaba un hash corto, obtuve %d caracteres", len(result))\n }\n}\n\nEjecutamos: go test -v. Vemos rojo (bueno, técnicamente un error de compilación). La función Shorten no existe. Perfecto, estamos en la etapa Red.
Código mínimo: Green
\n\nAhora escribimos exactamente lo necesario para que la prueba pase. Sin criptografía, solo un hash:
\n\n// shortener.go\npackage main\n\nimport (\n "crypto/sha256"\n "fmt"\n)\n\nfunc Shorten(url string) string {\n hash := sha256.Sum256([]byte(url))\n return fmt.Sprintf("%x", hash[:4]) // tomamos los primeros 4 bytes\n}\n\nEjecutamos la prueba de nuevo. ¿Verde? Excelente. Pero el código es horrible: el hash tiene colisiones, y ni siquiera estamos comprobando qu