perri.to: Un mejunje de cosas

Testeo en go, con go check

  2015-08-28


Aclaración: esto está pensado principalmente para funcionar como mi propia autodocumentación.

Testear en go es bastante simple, como podés ver en la documentación Una estructura básica, un paquete simple:

Un archivo llamado sample.go

package sample

func sampleFunction(sampleSlice []string) {
    sampleSlice = append(sampleSlice, "called")
}

En lo que a go respecta, esto es un paquete y si hacés go build de eso, va a compilar. Agregar testeo a ese paquete es tan simple como agregar un archivo que termine en _test.go Cualquier cosa con el nombre mencionado será interpretada como un archivo de test y, por lo tanto, solo compilada al momento de testear. A todos los efectos prácticos, durante el testeo, tu archivo será considerado parte del paquete cuyo nombre se declara en la sección package del _test.go. Lamentablemente, hasta acá llega la ayuda que nos da go para hacer tests; si leés la documentación, vas a encontrar que no hay un conjunto de herramientas incorporado para cosas como aserciones y suites.

Para resolver esta carencia podemos usar go check Go check agrega la posibilidad de tener suites, aserciones y un conjunto de checks útiles.

La forma de enganchar go check en nuestra base de tests existente es simple:

Primero usamos el concepto agregado de suites, que se encuentran en la forma de structs como:

package sample

import (
    gc "gopkg.in/check.v1"
)

type aTestSuite struct {}

func (a *aTestSuite) TestingSomething(c *gc.C) {
    c.Assert(1, gc.Equals, 1)
}

Una suite es un struct y sus tests son todos sus métodos cuyo nombre lleva el prefijo Test; además tenemos extras como Fixtures y otras cosas muy prácticas (te recomiendo leer el resto de la página).

Para tener una de estas suites corriendo necesitás seguir dos pasos simples. 1 - registrar la suite llamando a: check.Suite() con un puntero a una instancia de tu suite. 2 - llamar al runner check.TestingT dentro de una función con el prefijo Test, lo que nos asegura que va a ser ejecutada por el test runner. Un consejo: llamá a TestingT solo una vez por binario, sin importar en qué paquete, o todo tu conjunto de suites va a correr muchas veces con posibles resultados inesperados.

Un ejemplo terminado se vería así:

package sample

import (
    "testing"

    gc "gopkg.in/check.v1"
)

func TestAll (t *testing.T) { // This could have any Test* name
    gc.TestingT(t)
}
type aTestSuite struct {}

var _ := gc.Suite(&aTestSuite{})

func (a *aTestSuite) TestingSomething(c *gc.C) {
    c.Assert(1, gc.Equals, 1)
}