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
ValueErrordersom vi prøver å sette en negativ radius.Vi skal få en
TypeErrordersom skaleringsfaktoren ikke er et tall.Vi skal få en
ValueErrordersom skaleringsfaktoren er negativ.Vi skal få areal og omkrets lik
0dersom radius er lik0.Arealet skal øke med en faktor
4dersom vi skalerer med skaleringsfaktor2.Omkretsen skal øke med en faktor
2dersom 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.pyogtest_temperatur.pyi samme mappe.Sett opp
test_temperatur.pyog lag noen tomme testmetodertest_konstruktør,test_som_fahrenheitogtest_som_kelvin. (Du kan brukepassfor å lage metoder som ikke gjør noen ting)
Her er noen krav som du må teste med testmetodene dine.
Man skal få en
ValueErrordersom man setter temperaturen til-273.15eller under.Man skal få en
TypeErrordersom temperaturen man setter ikke er et tall.For en temperatur
0.0skal man få ut32.0grader fahrenheit, og273.15grader kelvin.For en temperatur
100.0skal man få ut212.0grader fahrenheit og373.15grader kelvin.
Lag
temperatur.pyog sjekk at alle testene går gjennom medpython -m unittest -v test_temperatur.pyunderveis.
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
dockikke ha over halvpartenBattleships. Man skal få enValueErrornår man prøver å docke et skip som gjør at det blir over halvparten.En
Transporterfår ikke docke med"Gleep"eller"OopGloop"igoods. Da skal man få enValueError. Disse stoffene er bannlyst.Det er ikke lov å docke et
Battleshipmed faction"Borg"eller"Glorg". Da skal man få enValueError. Disse faksjonene skaper bare trøbbel.Skip av typen
Explorerkan 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
dockmer 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.