¿Cómo ejecutar pruebas de golang de forma secuencial?
Cuando ejecuto go test
, mi salida:
--- FAIL: TestGETSearchSuccess (0.00s)
Location: drivers_api_test.go:283
Error: Not equal: 200 (expected)
!= 204 (actual)
--- FAIL: TestGETCOSearchSuccess (0.00s)
Location: drivers_api_test.go:391
Error: Not equal: 200 (expected)
!= 204 (actual)
Pero después de volver a ejecutar go test
, todas mis pruebas pasan.
Las pruebas fallan solo cuando reinicio mi base de datos MySQL y luego las ejecuto go test
por primera vez.
Para cada GET
solicitud, hago una POST
solicitud antes para asegurarme de que haya datos creados en la base de datos.
¿Alguien podría ayudarme a asegurarme de que las pruebas se ejecuten de forma secuencial? ¿ Es decir que las POST
solicitudes se ejecutan antes que las GET
solicitudes?
No puede ni debe confiar en el orden de ejecución de la prueba. El orden en que se ejecutan las pruebas no está definido y con el uso de indicadores de prueba es posible excluir la ejecución de las pruebas, por lo que no tiene ninguna garantía de que se ejecutarán.
Por ejemplo, el siguiente comando solo ejecutará pruebas cuyo nombre contenga una 'W'
letra:
go test -run W
También tenga en cuenta que si algunas funciones de prueba se marcan como elegibles para la ejecución paralela utilizando el T.Parallel()
método, la herramienta go reordenará las pruebas para ejecutar primero pruebas no paralelas y luego ejecutar pruebas paralelas en paralelo bajo ciertas circunstancias (controladas por indicadores de prueba como -p
). Puedes ver ejemplos de esto en esta respuesta: ¿ Las pruebas se ejecutan en paralelo en Go o una por una?
Las pruebas deben ser independientes entre sí. Si una función de prueba tiene requisitos previos, eso no se puede hacer/implementar en otra función de prueba.
Opciones para realizar tareas adicionales antes de ejecutar una función de prueba:
- Puedes ponerlo en la propia función de prueba.
- Puedes ponerlo en una
init()
función de paquete, en el_test.go
propio archivo. Esto se ejecutará una vez antes de que comience la ejecución de las funciones de prueba. - Puede optar por implementar una
TestMain()
función que se llamará primero y en la que puede realizar una configuración adicional antes de llamarM.Run()
para activar la ejecución de funciones de prueba. - Puede combinar las opciones anteriores.
En su caso en paquete init()
o TestMain()
debe verificar si su base de datos está inicializada (hay registros de prueba insertados), y si no, insertar los registros de prueba.
Tenga en cuenta que a partir de Go 1.7, puede utilizar subpruebas en las que define el orden de ejecución de las subpruebas. Para obtener más información, consulte la publicación del blog: Uso de subpruebas y subbenchmarks y la documentación del paquete testing
.
Para aquellos que, como yo, tienen problemas debido a que se ejecutan múltiples pruebas simultáneas. Encontré una manera de limitar el número máximo de pruebas que se ejecutan en paralelo:
go test -p 1
Con esto, su prueba se ejecutará secuencialmente una por una.
Fuente
Aparte de las bibliotecas de terceros como Convey y Ginkgo , con Golang 1.7 simple puedes ejecutar pruebas de forma secuencial. Puede leer más aquí
func TestFoo(t *testing.T) {
// <setup code>
t.Run("A=1", func(t *testing.T) { ... })
t.Run("A=2", func(t *testing.T) { ... })
t.Run("B=1", func(t *testing.T) { ... })
// <tear-down code>
}
Y puedes ejecutarlos condicionalmente con:
go test -run '' # Run all tests.
go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar".
go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=".
go test -run /A=1 # For all top-level tests, run subtests matching "A=1".
Entonces digamos que tienes un user
paquete de una API REST que deseas probar. Debe probar el controlador de creación para poder probar el controlador de inicio de sesión. Normalmente tendría esto en eluser_test.go
type UserTests struct { Test *testing.T}
func TestRunner(t *testing.T) {
t.Run("A=create", func(t *testing.T) {
test:= UserTests{Test: t}
test.TestCreateRegularUser()
test.TestCreateConfirmedUser()
test.TestCreateMasterUser()
test.TestCreateUserTwice()
})
t.Run("A=login", func(t *testing.T) {
test:= UserTests{Test: t}
test.TestLoginRegularUser()
test.TestLoginConfirmedUser()
test.TestLoginMasterUser()
})
}
Luego puedo agregar métodos al tipo UserTest que no serán ejecutados por el go test
comando en ningún _test.go
archivo.
func (t *UserTests) TestCreateRegularUser() {
registerRegularUser := util.TableTest{
Method: "POST",
Path: "/iot/users",
Status: http.StatusOK,
Name: "registerRegularUser",
Description: "register Regular User has to return 200",
Body: SerializeUser(RegularUser),
}
response := util.SpinSingleTableTests(t.Test, registerRegularUser)
util.LogIfVerbose(color.BgCyan, "IOT/USERS/TEST", response)
}
La mejor manera de lograrlo es crear un TestMain
, como se presenta aquí .
import (
"testing"
"os"
)
func TestMain(m *testing.M) {
// Do your stuff here
os.Exit(m.Run())
}