Codedekking uitgelegd: lijn versus filiaaldekking en wat 100% werkelijk betekent

  1. Home
  2. Blog
  3. Software testen

Softwaretesten

Codedekking uitgelegd: Lijn versus filiaaldekking en wat 100% werkelijk betekent

Dekking vertelt u welke code uw tests hebben uitgevoerd. Het vertelt u niet of de tests iets hebben gecontroleerd. We hebben een kleine module op drie manieren gemeten om het verschil te laten zien.

8 min leestijd
Codedekking uitgelegd: lijn versus filiaaldekking en wat 100% werkelijk betekent

Belangrijkste punten

  • Codedekking meet hoeveel van uw code tijdens tests wordt uitgevoerd.
  • De dekking van filialen is strenger dan lijndekking, en nuttiger.
  • In onze test bereikte een suite met geen beweringen nog steeds een dekking van 100%.
  • Gebruik dekking om ongeteste code te vinden, niet als bewijs van kwaliteit.

Een team rapporteert trots dat de code voor 95% bedekt is, en verzendt vervolgens een bug in een regel die “gedekt” was. Dit is geen tegenstrijdigheid. De dekking beantwoordt één beperkte vraag: hebben de tests deze code uitgevoerd? Of ze het resultaat hebben gecontroleerd, is een heel andere vraag.

We gebruikten Python met dekking.py 7.17 en pytest 9.2. Elk nummer en rapport hieronder is uit onze eigen run. De ideeën zijn in elke taal toepasbaar.

Wat is codedekking?

Codedekking is het percentage van uw code dat wordt uitgevoerd terwijl uw geautomatiseerde tests worden uitgevoerd. Een tool registreert welke lijnen, en eventueel welke vertakkingen, zijn uitgevoerd en rapporteert vervolgens wat er is gemist.

Het is het nuttigst in omgekeerde richting. Een lage dekking in een gebied vertelt u met zekerheid dat er geen tests zijn uitgevoerd. Een hoge dekking zegt veel minder.

Soorten dekking

Typ Vraag die het beantwoordt
Functie Is elke functie minstens één keer aangeroepen?
Regel (verklaring) Heeft elke lijn minstens één keer gelopen?
Tak Ging elke if beide kanten op, waar en onwaar?
Conditie Heeft elk onderdeel van een gecombineerde voorwaarde (a and b) beide waarden aangenomen?
MC/DC Heeft elke conditie onafhankelijk de uitkomst veranderd? Gebruikt in veiligheidskritische software.

Elk niveau is strenger dan het niveau erboven. De meeste teams houden de lijn- en aftakkingsdekking bij. Conditiedekking en MC/DC komen voor in luchtvaart- en automobielnormen, waar gereedschapsondersteuning gespecialiseerd is.

De code die we hebben gemeten

def shipping_fee(total, is_member, express=False):
    if total < 0:
        raise ValueError("total cannot be negative")
    fee = 0 if total >= 1000 else 50
    if is_member:
        fee = max(fee - 25, 0)
    if express:
        fee += 100
    return fee

Ons eerste testbestand kende twee tests:

def test_regular_order():
    assert shipping_fee(500, False) == 50

def test_member_express():
    assert shipping_fee(500, True, express=True) == 125

We hebben het uitgevoerd met de takmeting ingeschakeld:

coverage run --branch -m pytest test_shipping.py
coverage report -m

Het rapport lezen

Name          Stmts   Miss Branch BrPart  Cover   Missing
---------------------------------------------------------
shipping.py       9      1      6      1    87%   3
  • Stmts 9, Miss 1: negen uitvoerbare instructies, waarvan er één nooit is uitgevoerd.
  • Tak 6, BrDeel 1: drie if beslissingen geven zes mogelijke uitkomsten. Eén beslissing ging maar één kant op.
  • Ontbrekende 3: regel 3, de raise ValueError, is nooit uitgevoerd. Geen enkele test heeft een negatief totaal behaald.

De oplossing is een test voor het foutpad. Voor een grote bestelling hebben we ook een test toegevoegd:

def test_free_over_1000():
    assert shipping_fee(1000, False) == 0

def test_negative_total():
    with pytest.raises(ValueError):
        shipping_fee(-1, False)

Bij beide bestanden toonde het rapport 100% en geen ontbrekende regels of gedeeltelijke vertakkingen. Foutpaden zijn de klassieke ontdekkingen van gap-dekking. Daarom passen tests voor ongeldige invoer, ontworpen met technieken als equivalentiepartitionering, er zo goed bij.

Wat het rapport verborgen hield

Kijk nog eens naar het eerste rapport. Er stond dat alleen lijn 3 ontbrak. Maar bij de eerste twee tests werden er beide een totaal van 500 gebruikt, dus de regel voor gratis verzending voor bestellingen van 1000 of meer werd nooit getest, en het rapport vermeldde dit niet.

De reden is dat fee = 0 if total >= 1000 else 50 op één regel staat. dekking.py meet vertakkingen tussen regels, dus een voorwaardelijke expressie binnen een enkele regel telt als één uitgevoerde instructie. Als die regel een bug zou bevatten, zoals > in plaats van >=, zou de eerste suite nog steeds 87% hebben weergegeven zonder enige hint. Het testen van de grens zelf, zoals beschreven in grenswaardeanalyse, is wat deze vastlegt.

100% dekking zonder controles

Vervolgens hebben we een opzettelijk slechte test geschreven die elk pad oproept maar niets beweert:

def test_runs_everything_but_checks_nothing():
    shipping_fee(500, True, express=True)
    shipping_fee(1000, False)
    shipping_fee(500, False)
    try:
        shipping_fee(-1, False)
    except ValueError:
        pass
shipping.py       9      0      6      0   100%

De dekking bereikte 100% lijn- en filiaaldekking. De functie kan elk willekeurig getal retourneren en deze test zou nog steeds slagen. Dit is de kernlimiet van de dekking: het meet de uitvoering, niet de verificatie.

Tip: Lees bij het beoordelen van een pull-verzoek de beweringen, en niet alleen de dekkingswijziging. Een test die dekking toevoegt zonder een zinvolle bewering voegt alleen maar vals vertrouwen toe.

Als je wilt meten of tests daadwerkelijk bugs ontdekken, gebruik je mutatietests. Een tool als mutmut voor Python, PIT voor Java of Stryker voor JavaScript brengt kleine wijzigingen in je code aan, zoals het omdraaien van >= naar >, en controleert of een test mislukt. Onze no-asss-test zou ervoor zorgen dat elke mutatie overleeft.

Welk doel te stellen

Er bestaat geen universeel correct getal. Praktische begeleiding:

  • Ga niet voor de volle 100%. De laatste paar procent betekent vaak het testen van triviale code of het schrijven van tests die slechts één lijn bevatten.
  • Veel teams streven naar een totaalpercentage van grofweg 70 tot 85%, met hogere verwachtingen ten aanzien van de kernbedrijfslogica.
  • Let op de trend, niet op het aantal. De berichtgeving die bij elke release afneemt, is een waarschuwingssignaal.
  • Vereist dekking van nieuwe code in pull-verzoeken in plaats van oude code in één keer te forceren.
  • Sluit uit wat er niet toe doet, zoals gegenereerde code, met duidelijke regels.

De wet van Goodhart is van toepassing: wanneer een maatregel een doelwit wordt, is deze niet langer een goede maatregel. Harde doelen moedigen tests aan, zoals ons voorbeeld zonder assertiviteit.

Hulpmiddelen per taal

Taal Gemeenschappelijke hulpmiddelen
Python dekking.py, pytest-cov
JavaScript / TypeScript Istanbul (nyc), ingebouwd in Jest en Vitest
Java JaCoCo
.NET Overtrek
Ga ga testen -dekking
Rapportage Codecov, SonarQube, overalls

Dekking in CI

Voer dekking uit als onderdeel van uw CI-pijplijn en publiceer het rapport zodat reviewers kunnen zien welke nieuwe regels nog niet zijn getest. Met dekking.py mislukt coverage report --fail-under=80 de build onder een drempel. Houd elke drempel bescheiden en combineer deze met een regel over nieuwe code, zodat één groot verouderd bestand niet elke wijziging blokkeert.

Naast dekking: betere vragen om te stellen

  • Bestrijken tests de risicovolle, vaak gewijzigde delen van de code?
  • Worden grenzen en foutenpaden getest, en niet alleen het gelukkige pad?
  • Zou een test mislukken als deze regel verkeerd was?
  • Zijn de tests snel en stabiel genoeg om bij elke wijziging uit te voeren?

Deze horen thuis in elke teststrategie. Dekking helpt alleen bij het beantwoorden van de eerste vraag.

Exclusief code en lezen van HTML-rapporten

Sommige code is het niet waard om direct te testen, zoals debug-helpers of een blok dat alleen wordt uitgevoerd als een script met de hand wordt gestart. Met dekking.py kunt u regels uitsluiten met een opmerking:

if __name__ == "__main__":  # pragma: no cover
    main()

U kunt ook uitsluitingen en de te meten bronmappen instellen in de configuratie, bijvoorbeeld in pyproject.toml:

[tool.coverage.run]
branch = true
source = ["shop"]

[tool.coverage.report]
show_missing = true
exclude_also = ["if TYPE_CHECKING:"]

Wees spaarzaam met uitsluitingen en bekijk ze als code. Elk ervan is een beslissing dat sommige regels nooit zullen worden gecontroleerd. Het uitsluiten van een moeilijk te testen foutafhandelaar alleen maar om het aantal op te heffen, schiet het doel voorbij.

Voor het dagelijkse werk is het HTML-rapport nuttiger dan de terminaltabel. Voer coverage html uit en open htmlcov/index.html. Elk bestand wordt weergegeven met uitgevoerde regels in het groen, gemiste regels in rood en gedeeltelijke vertakkingen in geel, zodat je in één oogopslag kunt zien welke if nooit een andere weg is ingeslagen. Veel redacteuren kunnen ook dekking in de marge weergeven, waardoor hiaten zichtbaar worden tijdens het schrijven van de code in plaats van achteraf.

Dekking vóór refactoring

Dekking is ook een veiligheidscontrole vóór refactoring. Als u van plan bent een module te herstructureren, bekijk dan eerst het rapport ervan. Rode gebieden hebben geen tests om u te waarschuwen als gedrag verandert, dus voeg karakteriseringstests toe die het huidige gedrag vastleggen voordat u begint. Op deze manier is dekking niet langer een doelwit, maar wordt het een praktisch planningsinstrument.

Hetzelfde rapport helpt wanneer een bug naar de productie ontsnapt. Zoek de regel waar de bug zich bevond en controleer of deze door een test is uitgevoerd. Zo niet, dan heb je een gat gevonden dat de moeite waard is om te dichten. Als een test dit wel heeft uitgevoerd, is het probleem een ​​zwakke bewering, en dat is precies de situatie die ons voorbeeld zonder bewering liet zien. Beide antwoorden vertellen u hoe u de suite kunt verbeteren.

Tot slot

Codedekking is een zaklamp, geen cijfer. Gebruik branchedekking om code te vinden die geen enkele test raakt, vooral de foutafhandeling, en schrijf vervolgens tests die echte beweringen doen. Als u zich één resultaat van onze run herinnert, laat het dan dit zijn: 100% dekking werd bereikt door een test die niets controleerde.

Veelgestelde vragen

Wat is codedekking bij testen?

Het is het percentage code dat wordt uitgevoerd terwijl geautomatiseerde tests worden uitgevoerd, gemeten aan de hand van lijnen, vertakkingen of omstandigheden. Het laat zien wat tests hebben aangeraakt, niet of ze het hebben geverifieerd.

Wat is het verschil tussen lijn- en filiaaldekking?

Lijndekking controleert of elke lijn liep. Branchedekking controleert of elke beslissing beide kanten op ging. Takdekking vindt ongeteste paden die lijndekking mist.

Is 100% codedekking goed?

Niet op zichzelf. In onze test bereikte een suite zonder beweringen 100%. Streef naar zinvolle tests op belangrijke code in plaats van naar een perfect getal.

Wat is een goed codedekkingspercentage?

Veel teams mikken in totaal op ongeveer 70 tot 85%, waarbij meer op kritische logica gericht is. De trend en de kwaliteit van de beweringen zijn belangrijker dan het exacte aantal.

Waarin verschilt het testen van mutaties van dekking?

Mutatietesten veranderen uw code enigszins en controleren of een test mislukt. Het meet of tests bugs detecteren, wat de dekking niet kan doen.

Blijf leren

Werk met Stack Quora

Hulp nodig met testen, WordPress of SEO?

We helpen teams betere software te leveren en hun sites te laten groeien. Vertel ons waar u mee bezig bent en wij stellen een duidelijke volgende stap voor.

Blijf lezen

Meer handleidingen over testen, AI en moderne ontwikkeling

Genoten van dit artikel? Kies een onderwerp en ga direct naar onze nieuwste tutorials.

Kunstmatige intelligentie

AI-hallucinaties uitgelegd: waarom taalmodellen dingen verzinnen en hoe ze te verminderen

AI-hallucinaties uitgelegd: wat ze zijn, waarom taalmodellen ze produceren, veelvoorkomende typen, hoe je ze kunt verminderen met aarding en aanwijz…

Lees artikel →
DevOps

Omgevingsvariabelen uitgelegd: .env-bestanden, geheimen en configuratie goed gedaan

Omgevingsvariabelen uitgelegd met Python-voorbeelden die we hebben uitgevoerd: ze lezen en instellen, waarom elke waarde een string is, .env-bestand…

Lees artikel →
Softwareontwikkeling

API-snelheidsbeperking uitgelegd: algoritmen, headers en afhandeling van 429-fouten

API-snelheidsbeperking uitgelegd met een simulatie die we hebben uitgevoerd: token-bucket, vast venster, schuifvenster, 429 reacties, headers van sn…

Lees artikel →
Testautomatisering

Spotten in Python: unittest.mock, patch en de fouten die tests doen liegen

Spotten in Python met unittest.mock, getest: Mock en return_value, side_effect, patchen waar een naam wordt gebruikt, spec en autospec, spotdatums e…

Lees artikel →
Softwaretesten

Codedekking uitgelegd: lijn versus filiaaldekking en wat 100% werkelijk betekent

Codedekking uitgelegd met een echte dekking.py-run: dekking van lijnen, vertakkingen en condities, een rapport lezen, waarom 100% dekking nog steeds…

Lees artikel →
Databases & SQL

DELETE versus TRUNCATE versus DROP in SQL: verschillen, terugdraaien en wanneer elk te gebruiken

DELETE versus TRUNCATE versus DROP uitgelegd met geteste SQL: wat elk verwijdert, terugdraaien, triggers, identiteitsreset, snelheid en hoe PostgreS…

Lees artikel →
Databases & SQL

SQL-weergaven uitgelegd: creëer, gebruik en vermijd de valkuilen, met voorbeelden

SQL-weergaven uitgelegd met query's die we hebben uitgevoerd: een weergave maken, live resultaten, kolommen verbergen, prestaties, bijwerkbare en ge…

Lees artikel →
Softwareontwikkeling

TypeScript-interface versus type: echte verschillen, getest met de compiler

TypeScript-interface versus type, gecontroleerd met de echte compiler: wat beide kunnen doen, wat slechts één kan doen, samenvoegen van declaraties,…

Lees artikel →
Softwareontwikkeling

Python *args en **kwargs uitgelegd: flexibele functies met duidelijke voorbeelden

Python *args en **kwargs uitgelegd met code die we hebben uitgevoerd: in- en uitpakken, parametervolgorde, argumenten die alleen trefwoorden en posi…

Lees artikel →
Softwareontwikkeling

Python Lambda-functies: syntaxis, echt gebruik en wanneer u ze niet moet gebruiken

Python lambda-functies uitgelegd met code die we hebben uitgevoerd: syntaxis, sorteren met sleutel, kaart en filter, sluitingen, de laat-bindende va…

Lees artikel →
Kunstmatige intelligentie

Wat zijn AI-agenten? Hoe ze werken, met een eenvoudige agentloop die u kunt uitvoeren

Wat zijn AI-agenten? Een duidelijke gids voor de agentenlus, tools, geheugen en vangrails, met een kleine Python-lus die we hebben uitgevoerd, echte…

Lees artikel →
DevOps

Monitoring versus waarneembaarheid: het echte verschil, met logboeken, statistieken en sporen

Monitoring versus waarneembaarheid uitgelegd: bekende en onbekende fouten, logboeken, statistieken en sporen, een walkthrough voor afrekenincidenten…

Lees artikel →
DevOps

Docker-volumes versus bindingsmounts: bewaar containergegevens op de juiste manier

Docker-volumes versus bind-mounts uitgelegd: waarom containergegevens verdwijnen, benoemde volumes, bind-mounts, tmpfs, Compose-voorbeelden, back-up…

Lees artikel →
Testautomatisering

TDD versus BDD: belangrijkste verschillen, één functie die op beide manieren is gebouwd en wanneer deze moet worden gebruikt

TDD versus BDD uitgelegd met één kortingsfunctie die in beide richtingen is gebouwd: rood-groen-refactor met code die we hebben uitgevoerd, gegeven-…

Lees artikel →
Softwareontwikkeling

Git merge vs rebase: verschillen, voorbeelden en wanneer je wat gebruikt

Git merge vs rebase uitgelegd met echte logoutput, een vergelijkingstabel, de gouden regel van rebase en een veilige teamwerkwijze.

Lees artikel →
Softwareontwikkeling

Python list comprehension: syntaxis, voorbeelden en wanneer je het vermijdt

Python list comprehension uitgelegd: syntaxis, filteren, if-else, geneste lussen, gemeten tijden en wanneer een gewone for-lus beter is.

Lees artikel →
Databases & SQL

SQL JOIN uitgelegd met voorbeelden (Inner, Left, Right, Full)

Begrijp SQL joins stap voor stap met voorbeeldtabellen en queries: INNER, LEFT, RIGHT, FULL, CROSS en SELF, plus veelgemaakte fouten en prestatietips.

Lees artikel →