Article in English can be found on dev.to/arxeiss/false-positive-go-code-coverage-3k7j
TL;DR: Pro získání metriky code coverage, není potřeba instalovat žádné speciální nástroje. Vše je obsaženo v základní instalaci. Jenže bez přepínače -coverpkg
může být výsledné procento pokrytí mnohem vyšší než je ve skutečnosti. Níže je vše ukázáno vše na příkladu.
Jak nainstalovat Go, připravit si prostředí a další je popsáno v článku Jak začít s jazykem Go.
Showtime!
Za testy v Go se považují soubory, které jsou ve stejném balíčku (složce) jako zdrojový kód balíčku a jméno souboru končí na _test.go
. Tyto soubory se ignorují při buildu, ale zahrnují se v testech. Pro názorné ukázky jsem použil Github repozitář arxeiss/go-false-positive-coverage. Ve kterém jsou 2 balíčky, unary a binary a připravené testy.
Krok 1. Falešná naděje, výsledek 100% pokrytí
Po naklonování repozitáře lze spustit příkazy zmíněné níže. Je jasně viditelné, že hlavní balíček main
a balíček unary
neobsahují žádné testové soubory a výsledné skóre 100 % je spočteno pouze na základě binary
balíčku. Pokud tedy balíček testy neobsahuje, vůbec se nezapočítává do skóre. Ostatně stačí si prohlédnout soubor coverage.out
a zmínka o souborech mimo binary
balíček zde vůbec není. Proto go tool cover
zobrazí 100% pokrytí, protože jiné balíčky nezná.
# Spuštění testů pro aktuální a všechny vnořené balíčky a uložení výsledku do coverage.out
go test -covermode=count -coverprofile=coverage.out ./...
# ? github.com/arxeiss/go-false-positive-coverage [no test files] # ok github.com/arxeiss/go-false-positive-coverage/binary 0.002s coverage: 100.0% of statements # ? github.com/arxeiss/go-false-positive-coverage/unary [no test files]
# Spočtení celkového pokrytí testy
go tool cover -func coverage.out
# github.com/arxeiss/go-false-positive-coverage/binary/operations.go:3: Add 100.0% # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:7: Sub 100.0% # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:11: Mul 100.0% # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:15: Div 100.0% # total: (statements) 100.0%
Krok 2. Přidáním testů klesne celkové skóre
V balíčku unary
je připraven soubor operations_test.go.bak
, stačí odebrat .bak
koncovku, spustit opět stejné příkazy jako výše, ale celkové skóre bude nižší! Pouze 71.4 %. Protože byly přidány testy do dalšího balíčku, je do celkového code coverage zahrnut i tento balíček. Jenže v něm nejsou otestovány všechny funkce. Proto celkové pokrytí klesne.
Příklad: Pokud balíček A
je plně pokrytý testy a používá funkce z balíčku B
, který testy nemá vůbec, bude pokrytí balíčku B
0%! Go totiž nezapočítá do coverage průchod funkcí, pokud je zavolána z jiného balíčku. I to se při použití přepínače -coverpkg
změní. Ve výsledku může tedy balíček bez testů být 100% pokrytý díky použití jinými balíčky.
Krok 3. Použití přepínače -coverpkg
Pro získání celkového skóre bez ohledu na přítomnost testů v jednotlivých balíčcích je nutné použít přepínač -coverpkg
. Ten říká, které všechny balíčky se mají otestovat. A i přesto, že balíček neobsahuje žádné testy, je započítán a zahrnut do souboru coverage.out.
go test -covermode=count -coverprofile=coverage.out -coverpkg=github.com/arxeiss/go-false-positive-coverage/... ./... # ? github.com/arxeiss/go-false-positive-coverage [no test files] # ok github.com/arxeiss/go-false-positive-coverage/binary 0.002s coverage: 44.4% of statements in github.com/arxeiss/go-false-positive-coverage/... # ok github.com/arxeiss/go-false-positive-coverage/unary 0.002s coverage: 11.1% of statements in github.com/arxeiss/go-false-positive-coverage/... go tool cover -func coverage.out # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:3: Add 100.0% # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:7: Sub 100.0% # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:11: Mul 100.0% # github.com/arxeiss/go-false-positive-coverage/binary/operations.go:15: Div 100.0% # github.com/arxeiss/go-false-positive-coverage/main.go:10: main 0.0% # github.com/arxeiss/go-false-positive-coverage/unary/operations.go:5: Abs 100.0% # github.com/arxeiss/go-false-positive-coverage/unary/operations.go:9: Sin 0.0% # github.com/arxeiss/go-false-positive-coverage/unary/operations.go:13: Cos 0.0% # total: (statements) 55.6%
Krok 4. Problém s generovaným kódem
Hlavní problém zmíněného přepínače je, že zahrnuje opravdu vše. A pokud je součástí kódu nějaký generovaný kód, třeba Protobuf definice, jsou také zahrnuty. Jenže ty se většinou netestují a berou se tak jak jsou. Toto už nelze vyřešit nějakým přepínačem, a je nutné využít shell skriptů. Jednoduše odstranit veškeré výskyty z coverage.out. Více o problému na StackOverflow.
cat coverage.out | grep -v ".pb.go" > coverage.filtered.out go tool cover -func coverage.filtered.out
Vlastní zkušenosti s Go, psaním testů v Go nebo měření code coverage sdílejte v komentářích.
K tomuto článku již není možné přidávat další komentáře