Cómo escribir pruebas unitarias en Go

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: Creación de un programa de muestra para realizar pruebas unitarias
  • Paso 2: Cómo escribir pruebas unitarias en Go
  • Paso 3: Probar su código Go usando el go testcomando
  • Paso 4: Cómo escribir pruebas basadas en tablas en Go
  • Paso 5: Cómo escribir pruebas de cobertura en Go
  • Paso 6: Cómo escribir puntos de referencia en Go
  • Paso 7: documentar el código Go con ejemplos
  • Conclusión
  • El autor seleccionó a la Fundación FreeBSD para recibir una donación como parte del programa Write for DOnations .

    Introducción

    Una prueba unitaria es una función que prueba un fragmento específico de código de un programa o paquete. El trabajo de las pruebas unitarias es verificar la corrección de una aplicación y son una parte crucial del lenguaje de programación Go .

    En este tutorial, creará un programa pequeño y luego ejecutará una serie de pruebas en su código utilizando el paquete de Go testingy el go testcomando . Una vez que complete el tutorial, tendrá un conjunto de pruebas unitarias en funcionamiento que incluye una prueba unitaria basada en tablas , una prueba de cobertura , un punto de referencia y un ejemplo documentado .

    Prerrequisitos

    Para completar este tutorial, necesitarás lo siguiente:

    • Familiaridad con el lenguaje de programación Go. Visite nuestra serie de tutoriales/libro electrónico, Cómo programar en Go , para obtener una introducción general al lenguaje.

    • Tienes instalada la versión 1.11 o superior de Go en tu equipo local. Puedes seguir estas instrucciones para instalar Go en Linux , macOS y Windows . En macOS, también puedes instalar Go usando el administrador de paquetes Homebrew .

    Nota: Este tutorial utiliza módulos Go, que es un sistema de gestión de paquetes introducido en la versión 1.11 de Go. Los módulos Go están pensados ​​para reemplazar $GOPATH y se convirtieron en la opción predeterminada a partir de la versión 1.13 de Go. Para obtener una descripción general más completa de las diferencias entre los módulos Go y $GOPATH, considere leer esta publicación oficial del blog del equipo principal de Go .

    Este tutorial fue probado usando la versión 1.14 de Go

    Paso 1: Creación de un programa de muestra para realizar pruebas unitarias

    Antes de poder escribir pruebas unitarias, necesita algo de código para que sus pruebas lo analicen. En este paso, creará un pequeño programa que sume dos números enteros. En los pasos siguientes, lo utilizará go testpara probar el programa.

    Primero, crea un nuevo directorio llamado math:

    1. mkdir ./math

    Moverse dentro del nuevo directorio:

    1. cd ./math

    Este será el directorio raíz de su programa y ejecutará todos los comandos restantes desde aquí.

    Ahora, usando nanosu editor de texto preferido, cree un nuevo archivo llamado math.go:

    1. nano math.go

    Añade el siguiente código:

    ./matemáticas/matemáticas.go

    package math// Add is our function that sums two integersfunc Add(x, y int) (res int) {return x + y}// Subtract subtracts two integersfunc Subtract(x, y int) (res int) {return x - y}

    Aquí estás creando dos funciones llamadas Addy Subtract. Cada función acepta dos números enteros y devuelve su suma ( func Add) o su diferencia ( func Subtract).

    Guarde y cierre el archivo.

    En este paso, escribiste código en Go. Ahora, en los siguientes pasos, escribirás algunas pruebas unitarias para asegurarte de que tu código funcione correctamente.

    Paso 2: Cómo escribir pruebas unitarias en Go

    En este paso, escribirá su primera prueba en Go. Para escribir pruebas en Go, es necesario un vínculo a un archivo de prueba, y este archivo de prueba siempre debe terminar en _test.go. Por convención, los archivos de prueba de Go siempre se encuentran en la misma carpeta o paquete donde se encuentra el código que están probando. El compilador no crea estos archivos cuando ejecuta el go buildcomando, por lo que no debe preocuparse de que terminen en las implementaciones.

    Y como ocurre con todo lo que ocurre en Go, el lenguaje tiene opiniones firmes sobre las pruebas. El lenguaje Go ofrece un paquete mínimo pero completo llamadotesting que los desarrolladores usan junto con el go testcomando. El testingpaquete ofrece algunas convenciones útiles, como pruebas de cobertura y evaluaciones comparativas, que explorará a continuación.

    Utilice su editor para crear y abrir un nuevo archivo llamado math_test.go:

    1. nano math_test.go

    Una función de prueba en Go incluye esta firma: func TestXxxx(t *testing.T). Esto significa que todas las funciones de prueba deben comenzar con la palabra Test, seguida de un sufijo cuya primera palabra esté en mayúscula. Las funciones de prueba en Go reciben solo un parámetro y, en este caso, es un puntero de tipo testing.T. Este tipo contiene métodos útiles que necesitará para generar resultados, registrar errores en la pantalla y señalar fallas, como el t.Errorf()método.

    Añade el siguiente código a math_test.go:

    ./matemáticas/prueba_matemáticas.go

    package mathimport "testing"func TestAdd(t *testing.T){    got := Add(4, 6)    want := 10    if got != want {        t.Errorf("got %q, wanted %q", got, want)    }}

    Primero, declara el nombre del paquete que desea probar math. Luego, importa el testingpaquete en sí, lo que hace que estén disponibles el testing.Ttipo y los demás tipos y métodos exportados por el paquete. El código y la lógica de prueba están contenidos en la TestAddfunción.

    Resumiendo, las siguientes son características de una prueba en Go:

    • El primer y único parámetro debe sert *testing.T
    • La función de prueba comienza con la palabra Testseguida de una palabra o frase que comienza con una letra mayúscula (la convención es utilizar el nombre del método bajo prueba, por ejemplo, TestAdd)
    • La prueba llama t.Erroro t.Failpara indicar una falla (está llamando t.Errorporque devuelve más detalles que t.Fail)
    • Puede utilizarlo t.Logpara proporcionar información de depuración que no falle
    • Las pruebas se guardan en archivos utilizando esta convención de nombres:, foo_test.gocomo math_test.go.

    Guarde y luego cierre el archivo.

    En este paso, escribiste tu primera prueba en Go. En el siguiente paso, comenzarás a usarlo go testpara probar tu código.

    Paso 3: Probar su código Go usando el go testcomando

    En este paso, probará su código. go testes un subcomando poderoso que lo ayuda a automatizar sus pruebas. go testacepta diferentes indicadores que pueden configurar las pruebas que desea ejecutar, cuánta verbosidad devuelven las pruebas y más.

    Desde el directorio raíz de su proyecto, ejecute su primera prueba:

    1. go test

    Recibirá el siguiente resultado:

    OutputPASSok      ./math 0.988s

    PASSsignifica que el código funciona como se esperaba. Cuando una prueba falla, verás FAIL.

    El go testsubcomando solo busca archivos con el _test.gosufijo . go testluego escanea esos archivos en busca de funciones especiales, incluidas func TestXxxy varias otras que cubriremos en pasos posteriores. go testluego genera un paquete principal temporal que llama a estas funciones de la manera adecuada, las compila y las ejecuta, informa los resultados y finalmente limpia todo.

    Probablemente sea go testsuficiente para nuestro pequeño programa, pero habrá ocasiones en las que querrás ver qué pruebas se están ejecutando y cuánto tiempo lleva cada una. Agregar el -vindicador aumenta la verbosidad. Vuelve a ejecutar tu prueba con el nuevo indicador:

    1. go test -v

    Verá el siguiente resultado:

    Output=== RUN   TestAdd--- PASS: TestAdd (0.00s)PASSok      ./math 1.410s

    En este paso, ejecutaste una prueba unitaria básica con el go testsubcomando. En el siguiente paso, escribirás una prueba unitaria más compleja basada en tablas.

    Paso 4: Cómo escribir pruebas basadas en tablas en Go

    Una prueba basada en tablas es como una prueba unitaria básica, excepto que mantiene una tabla de diferentes valores y resultados. El conjunto de pruebas itera sobre estos valores y los envía al código de prueba. Con este enfoque, podemos probar varias combinaciones de entradas y sus respectivas salidas.

    Ahora reemplazará su prueba unitaria con una tabla de estructuras, cuyos campos incluyen los dos argumentos necesarios (dos números enteros) y el resultado esperado (su suma) para su Addfunción.

    Reabrir math_test.go:

    1. nano math_test.go

    Elimine todo el código del archivo y agregue en su lugar la siguiente prueba unitaria controlada por tablas:

    ./matemáticas/prueba_matemáticas.go

    package mathimport "testing"// arg1 means argument 1 and arg2 means argument 2, and the expected stands for the 'result we expect'type addTest struct {    arg1, arg2, expected int}var addTests = []addTest{    addTest{2, 3, 5},    addTest{4, 8, 12},    addTest{6, 9, 15},    addTest{3, 10, 13},    }func TestAdd(t *testing.T){    for _, test := range addTests{        if output := Add(test.arg1, test.arg2); output != test.expected {            t.Errorf("Output %q not equal to expected %q", output, test.expected)        }    }}

    Aquí se define una estructura, se llena una tabla de estructuras que incluyen los argumentos y los resultados esperados para la Addfunción y, luego, se escribe una nueva TestAddfunción. En esta nueva función, se itera sobre la tabla, se ejecutan los argumentos, se comparan los resultados con cada resultado esperado y, luego, se devuelven los errores, en caso de que se produzcan.

    Guarde y cierre el archivo.

    Ahora ejecuta la prueba con la -vbandera:

    1. go test -v

    Verás el mismo resultado que antes:

    Output=== RUN   TestAdd--- PASS: TestAdd (0.00s)PASSok      ./math 1.712s

    Con cada iteración del bucle, el código prueba el valor calculado por la Addfunción frente a un valor esperado.

    En este paso, escribiste una prueba basada en tablas. En el siguiente paso, escribirás una prueba de cobertura.

    Paso 5: Cómo escribir pruebas de cobertura en Go

    En este paso, escribirá una prueba de cobertura en Go . Al escribir pruebas, suele ser importante saber qué parte del código real cubren las pruebas. Esto generalmente se conoce como cobertura . Este es también el motivo por el que no ha escrito una prueba para su Subtractfunción, para que podamos ver una prueba de cobertura incompleta.

    Ejecute el siguiente comando para calcular la cobertura de su prueba unitaria actual:

    1. go test -coverprofile=coverage.out

    Recibirá el siguiente resultado:

    OutputPASScoverage: 50.0% of statementsok      ./math 2.073s

    Go ha guardado estos datos de cobertura en el archivo coverage.out. Ahora puede presentar los resultados en un navegador web.

    Ejecute el siguiente comando:

    1. go tool cover -html=coverage.out

    Se abrirá un navegador web y se mostrarán los resultados:

    El texto verde indica cobertura, mientras que el texto rojo indica lo contrario.

    En este paso, probaste la cobertura de tu prueba unitaria basada en tablas. En el siguiente paso, realizarás una evaluación comparativa de tu función.

    Paso 6: Cómo escribir puntos de referencia en Go

    En este paso, escribirá una prueba comparativa en Go . La evaluación comparativa mide el rendimiento de una función o programa. Esto le permite comparar implementaciones y comprender el impacto de los cambios que realiza en su código. Con esa información, puede revelar partes de su código fuente de Go que vale la pena optimizar.

    En Go, las funciones que adoptan la forma func BenchmarkXxx(*testing.B)se consideran puntos de referencia. go testejecutará estos puntos de referencia cuando proporcione el -benchindicador. Los puntos de referencia se ejecutan de forma secuencial.

    Agreguemos un punto de referencia a nuestra prueba unitaria.

    Abierto math_test.go:

    1. nano math_test.go

    Ahora agregue una función benchamrk usando la func BenchmarkXxx(*testing.B)sintaxis:

    ./prueba_matematica.go

    ...func BenchmarkAdd(b *testing.B){    for i :=0; i  b.N ; i++{        Add(4, 6)    }}

    La función de referencia debe ejecutar el código de destino bN veces, donde N es un número entero que se puede ajustar. Durante la ejecución de la referencia, bN se ajusta hasta que la función de referencia dure lo suficiente para que se pueda cronometrar de manera confiable. El --benchindicador acepta sus argumentos en forma de expresión regular.

    Guarde y cierre el archivo.

    Ahora vamos a usarlo go testnuevamente para ejecutar nuestro benchmark:

    1. go test -bench=.

    Coincidirán .con cada función de referencia en un archivo.

    También puedes declarar funciones de referencia explícitamente:

    1. go test -bench=Add

    Ejecute cualquiera de los comandos y verá un resultado como este:

    Outputgoos: windowsgoarch: amd64pkg: mathBenchmarkAdd-4          1000000000               1.07 ns/opPASSok      ./math 2.074s

    El resultado significa que el bucle se ejecutó 10.000.000 de veces a una velocidad de 1,07 nanosegundos por bucle.

    Nota: Intente no comparar su código Go en un sistema ocupado que se esté utilizando para otros fines, ya que interferirá con el proceso de evaluación comparativa y obtendrá resultados inexactos.

    Ahora ha añadido un punto de referencia a su prueba unitaria en crecimiento. En el siguiente y último paso, añadirá ejemplos a su documentación, que go testtambién se evaluarán.

    Paso 7: documentar el código Go con ejemplos

    En este paso, documentarás tu código Go con ejemplos y luego probarás esos ejemplos . Go se centra mucho en la documentación adecuada, y el código de ejemplo agrega otra dimensión tanto a la documentación como a la prueba. Los ejemplos se basan en métodos y funciones existentes. Tus ejemplos deben mostrar a los usuarios cómo usar un fragmento específico de código. Las funciones de ejemplo son el tercer tipo de función tratada especialmente por el go testsubcomando.

    Para comenzar, vuelva a abrir math_test.go,

    1. nano math_test.go

    Ahora, agregue el código resaltado. Esto agregará el fmtpaquete a la lista de importación y su función de ejemplo al final del archivo:

    ./matemáticas/prueba_matemáticas.go

    package mathimport (    "fmt"    "testing")// arg1 means argument 1 and arg2 means argument 2, and the expected stands for the 'result we expect'type addTest struct {    arg1, arg2, expected int}var addTests = []addTest{    addTest{2, 3, 5},    addTest{4, 8, 12},    addTest{6, 9, 15},    addTest{3, 10, 13},}func TestAdd(t *testing.T) {    for _, test := range addTests {        if output := Add(test.arg1, test.arg2); output != test.expected {            t.Errorf("Output %q not equal to expected %q", output, test.expected)        }    }}func BenchmarkAdd(b *testing.B) {    for i := 0; i  b.N; i++ {        Add(4, 6)    }}func ExampleAdd() {    fmt.Println(Add(4, 6))    // Output: 10}

    La Output:línea se utiliza para especificar y documentar el resultado esperado.

    Nota : La comparación ignora los espacios iniciales y finales.

    Guarde y cierre el archivo.

    Ahora vuelva a ejecutar su prueba unitaria:

    1. go test -v

    Verás un resultado actualizado como este:

    Output=== RUN   TestAdd--- PASS: TestAdd (0.00s)=== RUN   ExampleAdd--- PASS: ExampleAdd (0.00s)PASSok      ./math   0.442s

    Ahora también se prueban sus ejemplos. Esta función mejora su documentación y también hace que sus pruebas unitarias sean más sólidas.

    Conclusión

    En este tutorial, creó un programa pequeño y luego escribió una prueba unitaria básica para comprobar su funcionalidad. Luego, reescribió su prueba unitaria como una prueba unitaria basada en tablas y luego agregó una prueba de cobertura, un punto de referencia y un ejemplo documentado.

    Dedicar tiempo a escribir pruebas unitarias adecuadas es útil para usted como programador porque aumenta su confianza en que el código o programa que ha escrito seguirá funcionando como se espera. El testingpaquete de Go le proporciona considerables capacidades de pruebas unitarias. Para obtener más información, consulte la documentación oficial de Go.

    Y si desea aprender más sobre programación en Go, visite nuestra serie de tutoriales / libro electrónico gratuito, Cómo codificar en Go .

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion