首页 > 解决方案 > 运行两项测试 - 一项失败,一项一项运行,均为阳性结果

问题描述

当我的 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

标签: pythonunit-testing

解决方案


这里:

class Automat:
    item_id = 30

item_id是一个类属性 - 它在 的所有实例之间共享Automat,这可能是测试相互干扰的方式。

更新

解决问题的item_id一种方法是在setUp方法中重置。


推荐阅读