mostrando cobertura de pruebas funcionales sin puntos ciegos
Tengo un código de producción de golang y pruebas funcionales para él escritas no en golang. Las pruebas funcionales ejecutan binarios compilados. La versión muy simplificada de mi código de producción está aquí:main.go
:
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
os.Exit(0)
}
if i%2 == 0 {
os.Exit(1)
}
time.Sleep(time.Second)
}
}
Quiero construir un perfil de cobertura para mis pruebas funcionales. Para hacerlo agregomain_test.go
archivo con contenido:
package main
import (
"os"
"testing"
)
var exitCode int
func Test_main(t *testing.T) {
go main()
exitCode = <-exitCh
}
func TestMain(m *testing.M) {
m.Run()
// can exit because cover profile is already written
os.Exit(exitCode)
}
Y modificarmain.go
:
package main
import (
"flag"
"fmt"
"math/rand"
"os"
"runtime"
"time"
)
var exitCh chan int = make(chan int)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
exit(0)
}
if i%2 == 0 {
fmt.Println("status 1")
exit(1)
}
time.Sleep(time.Second)
}
}
func exit(code int) {
if flag.Lookup("test.coverprofile") != nil {
exitCh <- code
runtime.Goexit()
} else {
os.Exit(code)
}
}
Luego construyo cobertura binaria:
go test -c -coverpkg=. -o myProgram
Luego, mis pruebas funcionales ejecutan este binario de cobertura, como este:
./myProgram -test.coverprofile=/tmp/profile
6507374435908599516
PASS
coverage: 64.3% of statements in .
Y construyo salida HTML que muestra cobertura:
$ go tool cover -html /tmp/profile -o /tmp/profile.html
$ open /tmp/profile.html
ProblemaMétodoexit
nunca mostrará una cobertura del 100% debido a una afecciónif flag.Lookup("test.coverprofile") != nil
. Entonces líneaos.Exit(code)
es un punto ciego para mis resultados de cobertura, aunque, de hecho, las pruebas funcionales van en esta línea y esta línea debe mostrarse en verde.
Por otro lado, si elimino la condiciónif flag.Lookup("test.coverprofile") != nil
, la líneaos.Exit(code)
terminará mi binario sin crear un perfil de cobertura.
Cómo reescribirexit()
y tal vezmain_test.go
para mostrar coberturasin puntos ciegos?
La primera solución que viene a la mente estime.Sleep()
:
func exit(code int) {
exitCh <- code
time.Sleep(time.Second) // wait some time to let coverprofile be written
os.Exit(code)
}
}
Pero no es muy bueno porque hará que el código de producción disminuya antes de salir.