Tilbake
3.9
Feilsøking og testing av programmer

3.9 Feilsøking og testing av programmer

Systematisk feilsøking, debugging-teknikker og testing av programkode.

50 min
5 oppgaver
DebuggingSyntaksfeilLogiske feilTestmetoderFeilmeldinger
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 5 oppgaver

Feilsøking og testing

Alle programmerarar lagar feil – det er ein heilt naturleg del av utviklingsprosessen. Skilnaden mellom ein nybyrjar og ein erfaren programmerar er ikkje at den erfarne lagar færre feil, men at den erfarne er betre til å finne og rette dei.

Det finst tre hovudtypar feil i program:
1. Syntaksfeil – brot på reglane i programmeringsspråket
2. Køyretidsfeil – feilen oppstår når programmet blir køyrt
3. Logiske feil – programmet køyrer utan feilmeldingar, men gir feil resultat

I dette kapittelet skal du lære:
- Korleis du skil mellom dei tre feiltypane
- Systematisk feilsøking med print-debugging
- Korleis du les og tolkar feilmeldingar
- Testing med assert og edge cases

Tre typar feil
Syntaksfeil (SyntaxError)
Oppstår når koden bryt reglane i programmeringsspråket. Programmet startar ikkje eingong.

# Manglende kolon etter if
if x > 5
    print("Stor")  # SyntaxError: expected ':'

# Feil innrykk
def beregn():
print("Hei")       # IndentationError: expected an indented block

Køyretidsfeil (RuntimeError)
Programmet startar, men krasjar undervegs.

tall = [1, 2, 3]
print(tall[5])      # IndexError: list index out of range

resultat = 10 / 0   # ZeroDivisionError: division by zero

alder = int("hei")  # ValueError: invalid literal for int()

Logiske feil
Programmet køyrer utan feilmeldingar, men gir feil resultat. Desse er vanskelegast å finne!

# Skal beregne gjennomsnitt, men glemmer parenteser
gjennomsnitt = sum_tall / antall + 1  # Feil: deler bare sum_tall
gjennomsnitt = sum_tall / (antall + 1)  # Riktig: deler på (antall + 1)
✏️Identifisere feiltypar

Klassifiser følgjande feil som syntaksfeil, køyretidsfeil eller logisk feil:

1. print("Hei" (manglande parentes)
2. Eit program som reknar ut arealet av ein sirkel med areal = 2 * pi * r i staden for pi * r**2
3. navn = input("Navn: ") etterfølgt av print(navn + 10)

1. Syntaksfeil – manglande avsluttande parentes er eit brot på Python-syntaksen. Python vil gi SyntaxError: '(' was never closed og programmet vil ikkje starte.

2. Logisk feil – formelen 2 * pi * r er omkrinsen, ikkje arealet. Programmet køyrer utan feilmeldingar, men gir feil svar. Dette er den vanskelegaste feiltypen fordi Python ikkje kan vite kva du meinte å skrive.

3. Køyretidsfeil – du kan ikkje leggje saman ein streng (navn) og eit tal (10) i Python. Programmet startar og ventar på input, men krasjar med TypeError når det prøver å utføre addisjonen.

📝Oppgave 1

Kva type feil er det når programmet køyrer utan feilmeldingar, men gir feil resultat?

Print-debugging

Den enklaste og mest brukte feilsøkingsteknikken er å leggje inn print-setningar for å sjå kva som skjer inne i programmet.

Strategi:
1. Identifiser kvar feilen truleg oppstår
2. Legg inn print()-setningar for å vise variabelverdiar
3. Køyr programmet og analyser utskrifta
4. Flytt/legg til print-setningar for å snevre inn feilen
5. Fjern print-setningar når feilen er funnen

Eksempel – feilsøkje ei utrekning:

def beregn_karakter(poeng, maks_poeng):
    prosent = poeng / maks_poeng * 100
    print(f"DEBUG: poeng={poeng}, maks={maks_poeng}, prosent={prosent}")

    if prosent >= 90:
        return 6
    elif prosent >= 75:
        return 5
    elif prosent >= 55:
        return 4
    elif prosent >= 40:
        return 3
    elif prosent >= 20:
        return 2
    else:
        return 1

karakter = beregn_karakter(45, 60)
print(f"DEBUG: karakter={karakter}")

Tips: Bruk prefikset DEBUG: på feilsøkingsutskrifter, slik at dei er lette å finne og fjerne etterpå.

✏️Finne ein logisk feil med print-debugging

Følgjande program skal finne det største talet i ei liste, men gir feil resultat. Bruk print-debugging til å finne feilen.

def finn_storst(tall):
    storst = 0
    for t in tall:
        if t > storst:
            storst = t
    return storst

resultat = finn_storst([-3, -1, -7, -2])
print(resultat)  # Forventer -1, men får 0

Vi legg inn print-setningar for å sjå kva som skjer:

def finn_storst(tall):
    storst = 0
    print(f"DEBUG: startverdi storst={storst}")
    for t in tall:
        print(f"DEBUG: sjekker {t} > {storst} => {t > storst}")
        if t > storst:
            storst = t
    return storst

Utskrift:

DEBUG: startverdi storst=0
DEBUG: sjekker -3 > 0 => False
DEBUG: sjekker -1 > 0 => False
DEBUG: sjekker -7 > 0 => False
DEBUG: sjekker -2 > 0 => False

Feilen: Startverdien storst = 0 er større enn alle negative tal! Ingen verdiar erstattar han.

Løysing: Sett storst = tall[0] (første element) i staden for 0:

def finn_storst(tall):
    storst = tall[0]  # Bruk første element som startverdi
    for t in tall[1:]:
        if t > storst:
            storst = t
    return storst

📝Oppgave 2

Følgjande program skal rekne ut summen av alle partal i ei liste, men gir feil resultat. Finn feilen og forklar han.

def sum_partall(tall):
    total = 0
    for t in tall:
        if t % 2 == 1:
            total += t
    return total

resultat = sum_partall([1, 2, 3, 4, 5, 6])
print(resultat)  # Forventer 12, men får 9

Systematisk feilsøking

Erfarne programmerarar følgjer ein systematisk framgangsmåte for feilsøking:

Steg 1: Les feilmeldinga nøye
Python-feilmeldingar inneheld verdifull informasjon:

Traceback (most recent call last):
  File "program.py", line 5, in <module>
    resultat = tall[10]
IndexError: list index out of range
- Fila og linjenummeret: line 5 – feilen er på linje 5
- Feiltypen: IndexError – indeksen er utanfor rekkevidda til lista
- Skildringa: list index out of range – du prøver å hente eit element som ikkje finst

Steg 2: Isoler feilen
- Kommenter ut delar av koden for å finne kvar feilen oppstår
- Test med enkle, kjende inputverdiar
- Reduser problemet til den minste koden som reproduserer feilen

Steg 3: Forstå feilen
- Kva forventa du at koden skulle gjere?
- Kva gjer koden faktisk?
- Kva er skilnaden?

Steg 4: Rett feilen og test
- Gjer éi endring om gongen
- Test med fleire ulike inputverdiar
- Kontroller at rettinga ikkje introduserer nye feil

📝Oppgave 3

Du får feilmeldinga:

Traceback (most recent call last):
  File "sensor.py", line 12, in <module>
    temperatur = int(svar)
ValueError: invalid literal for int() with base 10: 'tjueto'
Kva er mest sannsynleg årsaka til feilen?

Testing med assert

assert er eit Python-nøkkelord som sjekkar om eit vilkår er sant. Viss vilkåret er usant, krasjar programmet med ein AssertionError.

def beregn_areal(lengde, bredde):
    return lengde * bredde

# Tester
assert beregn_areal(5, 3) == 15, "5 × 3 skal gi 15"
assert beregn_areal(0, 10) == 0, "0 × 10 skal gi 0"
assert beregn_areal(2.5, 4) == 10.0, "2.5 × 4 skal gi 10.0"
print("Alle tester bestått!")

Edge cases – grensetilfelle som ofte avslører feil:
- Tom liste eller streng
- Null (0) som input
- Negative tal
- Svært store tal
- Same verdi for all input

def gjennomsnitt(tall):
    if len(tall) == 0:
        return 0  # Håndter tom liste
    return sum(tall) / len(tall)

# Test med edge cases
assert gjennomsnitt([10]) == 10        # Bare ett element
assert gjennomsnitt([]) == 0           # Tom liste
assert gjennomsnitt([-5, 5]) == 0      # Positive og negative
assert gjennomsnitt([3, 3, 3]) == 3    # Alle like
print("Alle tester bestått!")
✏️Skrive testar for ein funksjon

Skriv testar med assert for funksjonen er_gyldig_alder(alder) som returnerer True viss alderen er mellom 0 og 150.

def er_gyldig_alder(alder):
    return 0 <= alder <= 150

# Vanlige tilfeller
assert er_gyldig_alder(25) == True, "25 er gyldig"
assert er_gyldig_alder(0) == True, "0 er gyldig"
assert er_gyldig_alder(150) == True, "150 er gyldig"

# Ugyldige verdier
assert er_gyldig_alder(-1) == False, "-1 er ugyldig"
assert er_gyldig_alder(151) == False, "151 er ugyldig"
assert er_gyldig_alder(-100) == False, "-100 er ugyldig"

# Edge cases - grenseverdier
assert er_gyldig_alder(1) == True, "1 er gyldig"
assert er_gyldig_alder(149) == True, "149 er gyldig"

print("Alle tester bestått!")

Vi testar:
- Vanlege verdiar som vi veit skal gi True eller False
- Grenseverdiar (0, 1, 149, 150, 151, -1) som er der feil ofte oppstår
- Ekstremt ugyldige verdiar for å vere sikre

📝Oppgave 4

Skriv ein funksjon er_partall(tall) som returnerer True viss talet er partal, og False elles. Skriv deretter minst 5 assert-testar som dekkjer vanlege tilfelle og edge cases.

Oppsummering

I dette kapittelet har du lært systematisk feilsøking og testing:

- Syntaksfeil – brot på reglane i språket, blir oppdaga før programmet startar
- Køyretidsfeil – programmet krasjar under køyring (IndexError, TypeError, osv.)
- Logiske feil – programmet gir feil resultat utan feilmeldingar
- Print-debugging – legg inn print() for å sjå kva som skjer inne i koden
- Systematisk feilsøking – les feilmelding → isoler → forstå → rett → test
- assert – sjekk at funksjonar gir rett resultat med kjende inputverdiar
- Edge cases – test med grenseverdiar som tomme lister, null og negative tal

Nøkkelomgrep


OmgrepForklaring
SyntaksfeilBrot på reglane i programmeringsspråket
KøyretidsfeilFeil som oppstår når programmet blir køyrt
Logisk feilProgrammet gir feil resultat utan feilmeldingar
Print-debuggingBruke print() til å vise variabelverdiar under feilsøking
assertSjekkar at eit vilkår er sant, krasjar viss ikkje
Edge caseGrensetilfelle som kan avsløre feil (tom liste, 0, negative tal)
📝Oppgave 5

Følgjande program har tre feil – éin syntaksfeil, éin køyretidsfeil og éin logisk feil. Finn og rett alle tre. Forklar kva type feil kvar av dei er.

def beregn_statistikk(malinger)
    antall = len(malinger)
    gjennomsnitt = sum(malinger) / antall
    avvik = []
    for i in range(antall + 1):
        avvik.append(malinger[i] - gjennomsnitt)
    total_avvik = sum(avvik) / antall
    return gjennomsnitt, total_avvik

resultat = beregn_statistikk([20, 22, 25, 21, 23])
print(f"Gjennomsnitt: {resultat[0]}, Avvik: {resultat[1]}")

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.