当我的Automat类中没有正数的给定产品和purchaseItem
方法时,我正在尝试对find_price_of_given_id
进行单元测试。
import unittest
from Automat import Automat
from Bank import Bank
from Item import Item
from exceptions.NoItemException import NoItemException
class AutomatTest(unittest.TestCase):
def test_checkPriceOfGivenID(self):
bank = Bank()
automat = Automat(bank)
Cola = Item(2)
automat.add_object(Cola)
self.assertEqual(automat.find_price_of_given_id(30), 2)
def test_checkIfPurchaseItemCanBeProcessedWhenNoProduct(self):
bank = Bank()
automat2 = Automat(bank)
Soda = Item(2, 0)
automat2.add_object(Soda)
self.assertEqual(automat2.purchaseItem(30), "Given amount it too small and " \
"no item with " + str(30) + " in automat!")
if __name__ == '__main__':
unittest.main()
如果我一个接一个地运行测试,则两个都通过。如果我运行整个课程,则说明test_checkPriceOfGivenID
失败了:
Testing started at 14:12 ...
C:\Users\Admin\PycharmProjects\vending-machine\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2018.3.4\helpers\pycharm\_jb_unittest_runner.py" --path C:/Users/Admin/PycharmProjects/vending-machine/AutomatTest.py
Launching unittests with arguments python -m unittest C:/Users/Admin/PycharmProjects/vending-machine/AutomatTest.py in C:\Users\Admin\PycharmProjects\vending-machine
Ran 2 tests in 0.004s
Error
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\unittest\case.py", line 59, in testPartExecutor
yield
File "C:\ProgramData\Anaconda3\lib\unittest\case.py", line 615, in run
testMethod()
File "C:\Users\Admin\PycharmProjects\vending-machine\AutomatTest.py", line 15, in test_checkPriceOfGivenID
self.assertEqual(automat.find_price_of_given_id(30), 2)
File "C:\Users\Admin\PycharmProjects\vending-machine\Automat.py", line 28, in find_price_of_given_id
raise NoItemException
exceptions.NoItemException.NoItemException
FAILED (errors=1)
Process finished with exit code 1
自动机类
from Item import Item
from exceptions.NoItemException import NoItemException
from exceptions.NoProperAmountException import NoProperAmountException
from Coin import Coin
from decimal import *
class Automat:
item_id = 30
def __init__(self, _bank, objects=None):
self.bank = _bank
if objects is None:
objects = {}
self.objects = objects
self.purchaseItemBank = []
def add_object(self, obj: Item):
id_to_assign = Automat.item_id
self.objects.update({id_to_assign: obj})
Automat.item_id = Automat.item_id + 1
return id_to_assign
def find_price_of_given_id(self, item_id):
if self.objects.get(item_id) is not None:
return self.objects.get(item_id).get_price()
else:
raise NoItemException
def find_amount_of_given_id(self, item_id):
if self.objects.get(item_id) is not None:
return self.objects.get(item_id).get_amount()
else:
raise NoItemException
def checkIfAmountIsPositive(self, item_id):
if self.objects.get(item_id) is not None:
var = True if self.objects.get(item_id).get_amount() > 0 else False
return var
else:
raise NoItemException
def withdrawItem(self, item_id):
self.objects.get(item_id).decrease()
def purchaseItem(self, item_id):
sumOfCoins = 0
if 30 <= item_id <= 50:
lista = []
for i in self.purchaseItemBank:
lista.append(i)
sumOfCoins += i.getCoinValue()
priceOfGivenProduct = self.find_price_of_given_id(item_id)
if sumOfCoins < priceOfGivenProduct:
if not self.checkIfAmountIsPositive(item_id):
return "Given amount it too small and " \
"no item with " + str(item_id) + " in automat!"
else:
raise NoProperAmountException
else:
if not self.checkIfAmountIsPositive(item_id):
return "No item with " + str(item_id) + " in automat!"
a = round(abs(Decimal(priceOfGivenProduct) - sumOfCoins), 2)
listaCopy = self.bank.getSortedBankListWithCoins()
if a > 0:
if len(listaCopy) == 0:
return "Nie mozna wydac"
for i, v in enumerate(self.bank.bank):
if a == 0:
break
elif a >= v.getCoinValue():
a = a - v.getCoinValue()
listaCopy.remove(v)
elif a < v.getCoinValue():
continue
if i + 1 == (len(self.bank.bank)):
return "Nie mozna wydac"
if a > 0:
return "Nie mozna wydac"
self.bank.bank = listaCopy.copy()
self.withdrawItem(item_id)
for iterator in lista:
self.bank.addMoney(iterator)
return "Wydano towar"
else:
raise NoItemException
物品类别:
class Item:
def __init__(self, price, amount=5):
self.amount = amount
self.price = price
def get_price(self):
return self.price
def get_amount(self):
return self.amount
def decrease(self):
self.amount -= 1
def __str__(self):
return f"{self.amount} @ {self.price}"
银行类别:
class Bank:
def __init__(self):
self.bank = []
def addMoney(self, value):
self.bank.append(value)
def getSumBank(self):
return sum(value.getCoinValue() for value in self.bank)
def getSumOfGivenCoins(self, *args):
suma = 0
for i in args:
suma += i.getCoinValue()
return suma
def getSortedBankListWithCoins(self):
self.bank.sort(key=lambda x: x.getCoinValue(), reverse=True)
listaCopy = self.bank.copy()
return listaCopy
答案 0 :(得分:3)
这里:
class Automat:
item_id = 30
item_id
是一个类属性-它在Automat
的所有实例之间共享,这可能就是测试之间相互干扰的方式。
更新:
解决此问题的一种方法是使用setUp
方法重置item_id
。
答案 1 :(得分:2)
您需要将item_id
转换为实例变量:
class Automat:
def __init__(self, _bank, objects=None):
self.item_id = 30
# rest of init here ...
def add_object(self, obj: Item):
id_to_assign = self.item_id
self.objects.update({id_to_assign: obj})
self.item_id += 1
return id_to_assign
现在,所有ID都将从30
开始,并且您的单元测试将能够找到这些项目。