什么是对python类进行单元测试的正确方法?

时间:2015-05-26 06:56:48

标签: python unit-testing

我不确定在python类的方法上构建独立单元测试的最佳方法是什么。这是一个简单的例子:

class MyClass(object):
  def __init__(self, data):
    self.data = data

  def myMethod(self):
    #do something
    return True

我正在构建像这样的单元测试:

class TestMyClass(unittest.TestCase):
  def test_init(self):
    mydata = mock.Mock()
    c = MyClass(mydata)
    self.assertEqual(c.data, mydata)

  def test_myMethod(self):
    mydata = mock.Mock()
    c = MyClass(mydata)
    self.assertTrue(c.myMethod())

好的,这非常简单......但重点是:test_myMethod()取决于__init__,因为我必须实例化对象本身:它并不是真正孤立的。解决这个问题的唯一方法就是模拟对象本身...但是如何在模拟对象上测试一个真实的方法呢?

我知道在现实世界中,完全隔离是不可能的,但我很想知道是否有更好的方法。

1 个答案:

答案 0 :(得分:2)

归结为您要测试的内容以及粒度。例如,c.data等于您在上一行中刚刚分配的数据实际测试的断言究竟是什么?它测试了一行实用代码,并测试了一个相当不重要的实现细节。这可能太精细了,不会打扰。

您希望确保您的对象的整体行为。这意味着你想测试你可以实例化它,然后断言

  1. 如果使用数据A对其进行实例化,然后调用方法B,则结果为C
  2. 如果用数据D实例化它,然后调用方法B,结果将是E
  3. 如果您尝试使用错误的数据实例化它,则会引发错误
  4. 您的测试应该关注对象行为,而不是测试实现细节。编写测试,以便在不破坏测试的情况下,以不同的方式插入实现相同行为的替代对象。您正在编写该类以完成某些指定的任务;测试您的实现是否可以完成这些任务,而不是如何完成任务。

    Exemptigratia:

    def test_worksWithDataA(self):
        c = MyClass({'some': 'data'})
        self.assertTrue(c.myMethod())
    
    def test_worksWithDataB(self):
        c = MyClass({'other': 'data'})
        self.assertFalse(c.myMethod())
    
    def test_rejectsDataC(self):
        with self.assertRaises(SomeException):
            MyClass(None)
    

    如果需要传递依赖项,则只需要模拟某些内容,但为了测试,该依赖项太复杂而无法实例化。只要您的数据只是dict,就没有必要嘲笑它。如果您的数据本身就是一个复杂的类型,那么您可能想要模拟它以便测试MyClass,而不必纠结于必须同时测试其他类。再次模拟时,模拟该类的预期行为;根据经验,你声称你的类使用单元测试的所有行为都可以在别处嘲笑。