用于类方法的Python单元测试

时间:2015-09-19 19:51:09

标签: python unit-testing

初学者级问题..试图了解我如何才能最好地使用内置unittest。在下面的简单示例中,方法consume_food选择一个食物项目,然后我调用food.cut()方法。 将来,此方法可能会返回Drink对象的实例。 #commented code表示可能的未来实施。在这种情况下,self.milk将不会定义cut方法。

我想为consume_foodpick_food方法添加单元测试。我想先为原始实现执行此操作,然后在添加self.milk功能后对其进行更改。

编辑:目的是为现有的api编写单元测试,以便我可以捕获任何此类更改(即缺少Drink.cut方法),迫使我更新方法和单元测试。

有人可以帮我们告诉我如何为这个例子编写单元测试吗?

class Fruit:
    def cut(self):
        print("cut the fruit")

class Drink:
    def pour(self):
       print("pour the drink")


class A:
   def __init__(self):
       self.apple = Fruit()
       self.banana=Fruit()
       #self.milk = Drink()
       #self.liquid_diet = True

   def consume_food(self):
       food = pick_food()
       food.cut()
       print("consuming the food")

   def pick_food(self):
       return self.apple                                 
       #if self.liquid_diet: return self.milk
       #return self.apple

1 个答案:

答案 0 :(得分:3)

问题是,您的cut()consume_food()方法现在并没有做太多的事情,这使您在测试中执行它们后可以有意义assertions

所以我建议稍微扩展你的初始代码,让这些方法对各自的对象起作用,这样你就可以在调用这些方法后对它们的状态做出有意义的断言。

现在,他们真正做的就是写STDOUT,这是一种全局状态 - 应该是generally be avoided并且是always difficult to test。 (我并不是说打印输出是件坏事 - 但如果那是你的代码所做的唯一的事情,那么测试就会非常棘手。)

所以我介绍了一个具有Food方法的公共超类consume(),并设置了相应的属性。同样,cut()上的Fruit方法现在设置了您可以测试的属性。

import unittest


class Food(object):
    def __init__(self):
        self.consumed = False

    def consume(self):
        self.consumed = True


class Fruit(Food):
    def __init__(self):
        super(Fruit, self).__init__()
        self.been_cut = False

    def cut(self):
        print("cut the fruit")
        self.been_cut = True


class Consumer(object):
    def __init__(self):
        self.apple = Fruit()
        self.banana = Fruit()

    def consume_food(self):
        food = self.pick_food()
        food.cut()
        print("consuming the food")
        food.consume()

    def pick_food(self):
        return self.apple

现在,这些测试可以在调用相关方法后对对象的状态进行断言。请注意,它们遵循AAA pattern - Arrange Act Assert

  • 首先,您按照您需要的方式安排测试对象(实例化消费者)。
  • 然后你对被测对象行动(调用相关方法)
  • 最后,对期望对象所在的结果状态进行断言
class TestConsumer(unittest.TestCase):

    def test_consume_food_consumes_the_apple(self):
        c = Consumer()
        c.consume_food()
        self.assertTrue(c.apple.consumed,
                        "Expected apple to be consumed")

    def test_consume_food_cuts_the_food(self):
        c = Consumer()
        c.consume_food()
        self.assertTrue(c.apple.been_cut,
                        "Expected apple to be cut")

    def test_pick_food_always_selects_the_apple(self):
        c = Consumer()
        food = c.pick_food()
        self.assertEquals(c.apple, food,
                          "Expected apple to have been picked")


if __name__ == '__main__':
    unittest.main()