🔥 Zapisy zamknięte, ale możesz pobrać Roadmapę .NET i dołączyć do listy oczekujących — Pobierz i dołącz do Listy VIP →

Code coverage w .NET — jak mierzyć i dlaczego 100% to zły cel

Code coverage mierzy, który procent linii (albo gałęzi) kodu został wykonany podczas uruchomienia testów. To użyteczny sygnał, gdzie testów brakuje — ale wysoki procent nie oznacza automatycznie, że kod jest dobrze przetestowany.

Uruchomienie pomiaru — coverlet.collector

dotnet add package coverlet.collector
dotnet test --collect:"XPlat Code Coverage"

Po uruchomieniu coverlet.collector generuje plik coverage.cobertura.xml w katalogu TestResults/{guid}/ — surowe dane o tym, które linie zostały wykonane. Sam XML jest nieczytelny dla człowieka, więc kolejny krok to zamiana go na raport HTML.

Czytelny raport HTML — ReportGenerator

dotnet tool install -g dotnet-reportgenerator-globaltool
reportgenerator -reports:"TestResults/**/coverage.cobertura.xml" -targetdir:"CoverageReport" -reporttypes:Html

Otwarcie CoverageReport/index.html pokazuje pokrycie per projekt, per klasa, per metoda — z podświetleniem konkretnych linii, które nie zostały wykonane przez żaden test.

Line coverage vs branch coverage — różnica, która ma znaczenie

public string OcenKlienta(int liczbaZamowien)
{
    if (liczbaZamowien > 100)
        return "VIP";
    return "Standard";
}
[Fact]
public void OcenKlienta_DuzoZamowien_ZwracaVip()
{
    Assert.Equal("VIP", Serwis.OcenKlienta(150));
}

Ten jeden test daje 100% line coverage dla metody OcenKlienta — każda linia kodu została wykonana (obie instrukcje return znajdują się na osobnych liniach, ale narzędzie liczy wykonane linie, nie ścieżki). Mimo to branch coverage wynosi 50% — gałąź else (liczbaZamowien <= 100) nigdy nie została przetestowana. Gdyby ktoś zamienił > na >=, ten jeden test by tego nie wykrył.

[Fact]
public void OcenKlienta_MaloZamowien_ZwracaStandard()
{
    Assert.Equal("Standard", Serwis.OcenKlienta(50));
}

Dopiero dodanie drugiego testu (sprawdzającego gałąź przeciwną) daje realne 100% branch coverage. Line coverage bez branch coverage potrafi dać fałszywe poczucie bezpieczeństwa — warto włączyć pomiar branch coverage (reportgenerator pokazuje oba), nie tylko line coverage.

Dlaczego 100% coverage nie gwarantuje braku bugów

[Fact]
public void ObliczRabat_DzialaPoprawnie()
{
    var wynik = Serwis.ObliczRabat(5);
    // brak asercji — test "przechodzi", bo nic nie sprawdza!
}

Ten test wykonuje każdą linię metody ObliczRabat — coverage pokaże 100%. Test nie sprawdza jednak absolutnie niczego: brak Assert oznacza, że test przejdzie niezależnie od tego, co metoda zwróci. Wysoki coverage mówi tylko “ten kod został wykonany”, nie mówi “ten kod działa poprawnie” — to dwie różne rzeczy, które łatwo pomylić, patrząc tylko na procent w raporcie.

Praktyczny próg — gdzie faktycznie warto celować w wysoki coverage

Nie ma jednej magicznej liczby (80%? 90%?), która pasuje do każdego projektu. Sensowniejsze pytanie: które części kodu najbardziej boli, gdy się zepsują? Logika biznesowa w warstwie Domain/Application (zobacz Clean Architecture) zasługuje na wysoki coverage z realnymi asercjami. Proste DTO, automatycznie generowane gettery/settery czy kod konfiguracyjny startowego Program.cs — dużo mniej. Pogoń za 100% coverage w całym projekcie często kończy się testami, które istnieją tylko po to, żeby podnieść liczbę w raporcie, nie po to, żeby faktycznie coś zweryfikować.

Podsumowanie

Code coverage mierzysz przez dotnet test --collect:"XPlat Code Coverage" i zamieniasz na czytelny raport HTML przez reportgenerator. Kluczowa różnica: line coverage pokazuje, które linie zostały wykonane, branch coverage pokazuje, które ścieżki logiczne (if/else) zostały przetestowane — ten drugi wskaźnik wyłapuje więcej realnych luk. Wysoki procent coverage bez sensownych asercji w testach nic nie gwarantuje — traktuj coverage jako mapę pokazującą, gdzie testów brakuje, nie jako cel sam w sobie.

👨‍💻
Mariusz Jurczenko
Senior .NET Developer · 10+ lat doświadczenia komercyjnego

Programista .NET z doświadczeniem komercyjnym w firmach takich jak NFZ, Kamsoft, Diagnostyka, Hermes Reply Polska czy Etisoft Smart Solutions. Twórca kursów, z których skorzystało już ponad 11 000 osób w Strefie Kursów i ponad 1 000 kursantów na dev-hobby.pl.

Specjalizacja: Clean Code, Clean Architecture i uczenie programowania tak, żeby dało się je naprawdę zrozumieć — nie wykuć.

🚀 Co dalej?

Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.

Dodaj komentarz

czytanie to początek

Zamień wiedzę w umiejętności

Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.

Pobieram roadmapę →