Abdeckung von Funktionstests ohne blinde Flecken anzeigen
Ich habe einen Produktions-Golang-Code und Funktionstests dafür, die nicht in Golang geschrieben sind. Funktionstests führen kompilierte Binärdateien aus. Eine sehr vereinfachte Version meines Produktionscodes finden Sie hier: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)
}
}
Ich möchte ein Abdeckungsprofil für meine Funktionstests erstellen. Dazu füge ich @ hinmain_test.go
Datei mit Inhalt:
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)
}
Und änderemain.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)
}
}
Dann erstelle ich Coverage Binary:
go test -c -coverpkg=. -o myProgram
Dann führen meine Funktionstests diese Coverage-Binärdatei wie folgt aus:
./myProgram -test.coverprofile=/tmp/profile
6507374435908599516
PASS
coverage: 64.3% of statements in .
Und ich erstelle eine HTML-Ausgabe mit Abdeckung:
$ go tool cover -html /tmp/profile -o /tmp/profile.html
$ open /tmp/profile.html
ProbleMethodeexit
wird aufgrund der Bedingung @ niemals eine 100% ige Abdeckung anzeigif flag.Lookup("test.coverprofile") != nil
. Also lineos.Exit(code)
ist ein bisschen blinder Fleck für meine Abdeckungsergebnisse, obwohl in der Tat Funktionstests in dieser Zeile angezeigt werden und diese Zeile als grün angezeigt werden sollte.
uf der anderen Seite, wenn ich Zustand entfernenif flag.Lookup("test.coverprofile") != nil
, die Linieos.Exit(code)
beendet meine Binärdatei, ohne ein Abdeckungsprofil zu erstellen.
Wi umschreibenexit()
und vielleichtmain_test.go
um Berichterstattung zu zeigenohne blinde Flecken?
ie erste Lösung, die in den Sinn kommt, isttime.Sleep()
:
func exit(code int) {
exitCh <- code
time.Sleep(time.Second) // wait some time to let coverprofile be written
os.Exit(code)
}
}
Aber es ist nicht sehr gut, da der Produktionscode vor dem Beenden langsamer wird.