Search
This is an old revision of the document!
Cílem cvičení je procvičit si na příkladu, jak přetavit specifikace ve formě textového popisu do testů, které ověří shodu implementace se specifikacemi. (Jde především o princip vytváření testů; zde použitá realizace testů je zvolena z důvodu jednoduchosti.)
Dostali jste se do týmu, který vyvíjí počítačovou hru. Rosemary je obchodnice, která v této hře vede obchůdek se smíšeným zbožím (jehož implementaci máte ve správě). Obchod prodává především potraviny (tzv. normal items), ale Rosemary umí sehnat a nabídnout také jisté speciální předměty. Rosemary je pečlivá a vede si evidenci o stavu zboží, které má na skladě. Na konci každého dne stav všeho zboží aktualizuje.
Každé zboží nebo předmět, které má Rosemary na skladě, budeme reprezentovat instancí třídy Item:
Item
class Item: def __init__(self, name, days_left, quality): self.name = name self.days_left = days_left self.quality = quality
Každé zboží či předmět má tedy
name
days_left
quality
Rosemary může mít na skladě i speciální předměty, které se určují podle specifického jména. Mezi tyto speciální předměty patří
“Aged Brie”
“Diamond”
“Tickets”
Tyto předměty jsou zvláštní v tom, že se chovají (stárnou) jinak než normální zboží.
Ve hře se na konci každého dne zavolá pro každé zboží na skladě funkce update(). Ta aktualizuje (obvykle sníží) hodnoty days_left a quality:
update()
>>> bread = Item('Bread', days_left=3, quality=5) >>> update(bread) >>> print(bread.days_left) 2 >>> print(bread.quality) 4
Poznámka 1: Funkce update() je modifikátorem, tj. nic nevrací, ale přímo na místě modifikuje instanci třídy Item, kterou jí předáme jako argument.
Poznámka 2: Z hlediska objektového návrhu by bylo lepší, kdyby update() byla metodou ve třídě Item a kdybychom mohli od třídy Item odvodit další třídy, např. BrieItem, DiamondItem, apod., které by věděly, jak sami sebe aktualizovat. Celý zbytek hry ale využívá pouze Item ve formě uvedené výše; zde popsané změny by si vyžádaly dalekosáhlé úpravy v kódu celé hry, a proto je zatím nemáme právo udělat.
Funkce update() musí dodržet následující pravidla:
days_left == 0
Funkce update() už je implementována. Vaším úkolem je sestavit sadů testů pro tuto funkci, které ověří, že se implementace funkce chová podle specifikací. Konkrétně je vaším úkolem vytvořit modul test_rosemary.py s co nejúplnější sadou testů, který nahrajete do BRUTE, kde vám oznámíme, jak dobrou sadu testů máte.
test_rosemary.py
Při testování softwaru je ideální v každém testu testovat pouze jedinou věc tak, aby při selhání testu bylo ihned zřejmé, co je špatně. (Kdyby měl test mnoho možností, proč selhat, netušili byste, která z nich za selhání může.) Je proto zcela obvyklé mít hodně testů a mít je krátké!
Specifikace:
update
rosemary.py
inspect
importlib
test_
True
False
Traceback (most recent call last): File "check_test.py", line 128, in run_test result = getattr(module, fn.fn_name)()
Vzor souboru test_rosemary.py:
from rosemary import Item, update def test_normal_item_decreases_days_left(): # Prepare for the test item = Item('Bread', days_left=3, quality=5) # Call to the tested function update(item) # Check the specification return item.days_left == 2 def test_... ... def test_... ...
Poznámka: Zde se zcela obejdeme bez jakéhokoli testovacího frameworku, dokonce i bez modulu testing.py, který jsme si vytvářeli na přednášce.
testing.py
Jak už bylo řečeno, v BRUTE k vašemu testovému modulu test_rosemary.py připojíme naši implementaci funkce update() v modulu rosemary.py. Máme k dispozici nejen (snad) správnou implementaci, ale i mnoho chybných s mnoha různými chybami. Vaši sadu testů vyzkoušíme na všech implementacích funkce update(). Cílem je, aby