Testing#
Du har sikkert brukt print
-funksjonen for å teste om koden fungerer som den skal. Nå skal vi skrive tester for å forutse hvordan vi forventer at koden skal fungere.
Enkel testing#
For å teste enkle ting kan vi bruke assert
.
La oss ta utgangspunkt i en betalingsmodell. Funksjonen pris
skal ta et heltall alder
og et flyttall vanlig_pris
som argumenter og returnere et flyttall pris
som representerer en pris.
Eldre (\(67\) år eller over) skal betale \(50\%\) av vanlig pris.
Barn fra og med \(5\) år og yngre har gratis billett.
Barn fra og med \(6\) år til og med \(17\) år skal betale \(40\%\) av vanlig pris.
Før vi begynner å skrive funksjonen kan vi allerede vite et par ting. Hvis vanlig pris er \(100\) kr så vil disse tingene stemme:
Billetten for en som er \(67\) år vil koste \(50.0\) kr.
Billetten for en som er \(6\) år vil koste \(40.0\) kr.
Billetten for en som er \(5\) år vil koste \(0.0\) kr.
Billetten for en som er \(18\) år vil koste \(100.0\) kr.
Vi kan sjekke disse testtilfellene (testcases) i Python med assert
.
assert pris(67, 100) == 50.0
assert pris(6, 100) == 40.0
assert pris(5, 100) == 0.0
assert pris(18, 100) == 100.0
Her kommer et eksempel på hele programmet:
def pris(alder : int, vanlig_pris : int) -> float:
if alder >= 67:
return vanlig_pris * 0.5
elif alder < 6:
return 0.0
elif alder < 18:
return vanlig_pris * 0.4
else:
return float(vanlig_pris)
assert pris(67, 100) == 50.0, "Prisen stemmer ikke for en 67-åring"
assert pris(6, 100) == 40.0, "Prisen stemmer ikke for en 6-åring"
assert pris(5, 100) == 0.0, "Prisen stemmer ikke for en 5-åring"
assert pris(18, 100) == 100.0, "Prisen stemmer ikke for en 18-åring"
Hvis noen av testene feiler får vi en feilmelding med AssertionError
og den stringen vi har skrevet etter komma.
Endrer vi prisen for alder < 6
til noe annet enn 0.0
får vi nå en feilmelding:
AssertionError: Prisen stemmer ikke for en 5-åring
Merk
Det er ikke så vanlig å ha testene i samme fil som den koden som skal testes. Vanligvis skriver man tester i en egen .py
-fil og importerer det man skal teste fra en annen .py
-fil.
For eksempel kan man teste billettsystem.py
ved å lage en fil test_billettsystem.py
og importere funksjonen man skal teste med import pris from billettsystem
.
En advarsel
Det kan være fristende å bruke assert
i en funksjon for å sjekke om argumentene til funksjonen er riktig, men dette anbefales ikke fordi asserts
ignoreres når Python kjøres med -O
i terminalvinduet.
I stedet for:
def tid(s, v):
assert v != 0
assert isinstance(s, (int, float)) == True
assert isinstance(v, (int, float)) == True
return s/v
Bruk heller:
def tid(s, v):
if isinstance(s, (int, float)) == True and isinstance(v, (int, float)) == True:
if v != 0:
return s/v
else:
raise ZeroDivisionError("Du kan ikke dele på null.")
else:
raise TypeError("Bare tall er akseptert som argument.")
Oppgaver#
Oppgave 1 🎫
Her kommer et eksempel på et annet billettsystem.
Barn \(9\) år og under kommer inn gratis.
Ungdom (til og med \(17\) år) får et avslag på \(30\%\).
Eldre (\(60\) år og over) får et avslag på \(20\%\).
Under kommer et eksempel hvor pris
-funksjonen har flere feil.
def pris(alder : int, vanlig_pris : int) -> float:
if alder < 9:
return 0.0
elif alder <= 17:
return vanlig_pris * 0.3
elif alder > 60:
return vanlig_pris * 0.2
else:
return float(vanlig_pris)
assert pris(34, 50) == 50.0
assert pris(9, 50) == 0.0
assert pris(17, 50) == 35.0
assert pris(60, 50) == 40.0
Vil noen av testtilfellene med
assert
gå gjennom uten feilmelding?Fiks funksjonen slik at koden går gjennom alle testtilfellene uten feilmelding.
Oppgave 2 🧬
I denne oppgaven skal vi feilsøke kjede med DNA.
DNA
DNA-molekyler inneholder informasjon som basepar. DNA har en struktur som en dobbel heliks. Man kan tenke på det som to lange tråder med trappetrinn mellom, litt som en spiraltrapp.
Hvis det er en
"A"
på den ene siden, så er det en"T"
på den andre siden.Hvis det er en
"T"
på den ene siden, så er det en"A"
på den andre siden.Hvis det er en
"C"
på den ene siden, så er det en"G"
på den andre siden.Hvis det er en
"G"
på den ene siden, så er det en"C"
på den andre siden.
Her kommer to sider av et DNA-molekyl, men det skjuler seg en feil i den genetiske koden… en mutasjon!
oppe = "TTCCAAATGTGAAGTCCCACTATATATAAGTACCTTGATGGACCCAGAGATATAAACGTGCGTCGTACCTAGAAATTAAA"
nede = "AAGGTTTACACTTCAGGGTGATATATATTCATGGAACTACCTGGGTCTCTCTATTTGCACGCAGCATGGATCTTTAATTT"
Bruk assert
i en for-løkke for å finne hvor feilen ligger på DNA-tråden. Rett så opp i feilen.
Oppgave 3 ✖️
Fakultet (factorial) er definert på denne måten:
\(0! = 1\)
\(n! = n \cdot (n-1) \cdot (n-2) \cdot ... \cdot 3 \cdot 2 \cdot 1\)
Du skal lage en funksjon fakultet(n)
som tar et heltall n
som argument og returnerer \(n!\), men først…
Lag tre testtilfeller med
assert
for hvordan du forventer at funksjonenfakultet(n)
skal fungere.Lag funksjonen
fakultet(n)
og sørg for at testene går gjennom uten feilmelding.
Oppgave 4 🧲
Andregradslikninger på formen \(ax^2 + bx + c = 0\) har løsningene \(x_1=\frac{-b+\sqrt{b^2-4ac}}{2a}\) og \(x_2=\frac{-b-\sqrt{b^2-4ac}}{2a}\).
Du skal lage en funksjon som finner løsningene for en andregradslikning, men først…
Bruk din matematiske intuisjon, en graftegner eller internett for å finne tre forskjellige andregradslikninger hvor man har ingen løsning, én løsning eller to løsninger.
Gjør likningene du fant om til testtilfeller med
assert
.Lag funksjonen slik at koden går gjennom testtilfellene uten feilmelding.