Testing II#
Når vi skal teste større ting er det hensiktsmessig å lage et testprogram. Det skal vi gjøre ved å bruke den innebygde pakken unittest
.
Testing med unittest
#
La oss ta utgangspunkt i programmet sirkelregner.py
.
import math
class Sirkel:
def __init__(self, r):
if r < 0:
raise ValueError("Radius kan ikke være negativ.")
self.r = r
self.areal = math.pi * self.r ** 2
self.omkrets = 2 * math.pi * self.r
# Skalerer sirkelen med en faktor k
def skaler(self, k):
if type(k) not in [int, float]:
raise TypeError("Skaleringsfaktoren må være et tall.")
elif k < 0:
raise ValueError("Skaleringsfaktoren kan ikke være negativ")
self.__init__(self.r * k)
# Returnerer en string når man printer objekter av klassen
def __str__(self):
return f"Sirkel med radius: {self.r:.3f}, areal: {self.areal:.3f} og omkrets: {self.omkrets:.3f}"
Nå skal vi lage et testprogram. Vi kommer til å kalle testprogrammet test_sirkelregner.py
.
Her er noen av tingene vi skal teste.
Vi skal få en
ValueError
dersom vi prøver å sette en negativ radius.Vi skal få en
TypeError
dersom skaleringsfaktoren ikke er et tall.Vi skal få en
ValueError
dersom skaleringsfaktoren er negativ.Vi skal få areal og omkrets lik
0
dersom radius er lik0
.Arealet skal øke med en faktor
4
dersom vi skalerer med skaleringsfaktor2
.Omkretsen skal øke med en faktor
2
dersom vi skalerer med skaleringsfaktor2
.
Vårt testprogram test_sirkelregner.py
kan se slik ut:
import sirkelregner as sr
import unittest, math
class TestSirkelregner(unittest.TestCase):
# Testmetode for konstruktøren
def test_konstruktør(self):
# Sjekker at vi får ValueError med negativ radius
self.assertRaises(ValueError, sr.Sirkel, -1)
# Sjekker noen regneeksempler
self.assertAlmostEqual(sr.Sirkel(1).areal, math.pi)
self.assertEqual(sr.Sirkel(0).areal, 0)
self.assertAlmostEqual(sr.Sirkel(1).omkrets, 2*math.pi)
self.assertEqual(sr.Sirkel(0).omkrets, 0)
# Testmetode for skaleringsmetoden
def test_skalering(self):
# Lager et eksempel
sirkel = sr.Sirkel(1)
# Sjekker at vi får TypeError med feil type skaleringsfaktor
self.assertRaises(TypeError, sirkel.skaler, "1")
# Sjekker at vi får ValueError med negativ skaleringsfaktor
self.assertRaises(ValueError, sirkel.skaler, -1)
# Sjekker at skaleringen blir riktig
areal_før, omkrets_før = sirkel.areal, sirkel.omkrets
sirkel.skaler(2)
areal_etter, omkrets_etter = sirkel.areal, sirkel.omkrets
self.assertAlmostEqual(areal_etter, 4*areal_før)
self.assertAlmostEqual(omkrets_etter, 2*omkrets_før)
For å kjøre testprogrammet bruker vi python -m unittest -v test_sirkelregner.py
i terminalvinduet.
Da får vi utskriften:
Ran 2 tests in 0.000s
OK
Det betyr at testene gikk gjennom uten feil. Koden fungerer som forventet 👍
Oppgaver#
Oppgave 1 🌡️
I denne oppgaven skal vi lage et testprogram før vi lager et program.
Til slutt skal temperatur.py
inneholde en klasse Temperatur
som har en attributt c
som skal tilsvare grader i celsius og settes i konstruktøren.
Temperatur
skal også ha to metoder.
som_kelvin()
skal returnere temperaturen som kelvin.som_fahrenheit()
skal returnere temperaturen som fahrenheit.
Lag to filer
temperatur.py
ogtest_temperatur.py
i samme mappe.Sett opp
test_temperatur.py
og lag noen tomme testmetodertest_konstruktør
,test_som_fahrenheit
ogtest_som_kelvin
. (Du kan brukepass
for å lage metoder som ikke gjør noen ting)
Her er noen krav som du må teste med testmetodene dine.
Man skal få en
ValueError
dersom man setter temperaturen til-273.15
eller under.Man skal få en
TypeError
dersom temperaturen man setter ikke er et tall.For en temperatur
0.0
skal man få ut32.0
grader fahrenheit, og273.15
grader kelvin.For en temperatur
100.0
skal man få ut212.0
grader fahrenheit og373.15
grader kelvin.
Lag
temperatur.py
og sjekk at alle testene går gjennom medpython -m unittest -v test_temperatur.py
underveis.
Løsningsforslag
test_temperatur.py
import unittest
from temperatur import Temperatur
class TestTemperatur(unittest.TestCase):
def test_konstruktør(self):
# Sjekker at man får ValueError ved c < -273.15
self.assertRaises(ValueError, Temperatur, -273.15)
# Sjekker at man får TypeError ved feil type
self.assertRaises(TypeError, Temperatur, "test")
self.assertRaises(TypeError, Temperatur, [1])
self.assertRaises(TypeError, Temperatur, False)
def test_som_kelvin(self):
# Tester 0 og 100 grader celsius.
t_0 = Temperatur(0)
t_100 = Temperatur(100)
self.assertAlmostEqual(t_0.som_kelvin(), 273.15)
self.assertAlmostEqual(t_100.som_kelvin(), 373.15)
def test_som_fahrenheit(self):
# Tester 0 og 100 grader celsius.
t_0 = Temperatur(0)
t_100 = Temperatur(100)
self.assertAlmostEqual(t_0.som_fahrenheit(), 32.0)
self.assertAlmostEqual(t_100.som_fahrenheit(), 212)
temperatur.py
class Temperatur:
def __init__(self, c):
if type(c) not in [float, int]:
raise TypeError("Typen for temperaturen må være et tall.")
elif c <= -273.15:
raise ValueError("Temperaturen kan ikke være -273.15 eller under.")
else:
self.c = c
def som_fahrenheit(self) -> float:
return self.c * 9/5 + 32
def som_kelvin(self) -> float:
return self.c + 273.15
Oppgave 2 👽
I denne oppgaven skal du lage en klasse Starport
og noen romskip av klassen Starship
.
classDiagram Starport : +list dock Starport : +int amount_of_docks Starport : dock(Starship) Starport : undock(Starship) Starship --o Starport Starship : +str name Starship : +int passengers Explorer --> Starship Explorer : +str captain_name Battleship --> Starship Battleship : +str faction Transporter --> Starship Transporter : +list[str] goods
import starport
import unittest
class TestStarport(unittest.TestCase):
def test_dock(self):
pass
def test_undock(self):
pass
Lag et testprogram. Du kan ta utgangspunkt i programmet over. Her er noen krav som skal testes.
Ifølge intergalaktisk lov kan
dock
ikke ha over halvpartenBattleships
. Man skal få enValueError
når man prøver å docke et skip som gjør at det blir over halvparten.En
Transporter
får ikke docke med"Gleep"
eller"OopGloop"
igoods
. Da skal man få enValueError
. Disse stoffene er bannlyst.Det er ikke lov å docke et
Battleship
med faction"Borg"
eller"Glorg"
. Da skal man få enValueError
. Disse faksjonene skaper bare trøbbel.Skip av typen
Explorer
kan docke, men ikke om kapteinen heterPean-Juc Bicard
, da skal man få enValueError
. Han er bannlyst fra stasjonen.Det skal ikke være mulig å fylle
dock
mer ennamount_of_docks
, da skal man få enValueError
.Når man kjører
undock(ship)
skal man fjerne et skip fradock
.
Lag ferdig starport.py
slik at den passerer alle testene dine.