如何测试设置和检查取决于未经测试的方法的方法?

时间:2018-06-17 16:58:15

标签: python unit-testing

我创建了一个示例类(一个位掩码类),它有4个非常简单的函数。我还为这个班级创建了一个单元测试。

import unittest

class BitMask:

    def __init__(self):
        self.__mask = 0

    def set(self, slot):
        self.__mask |= (1 << slot)

    def remove(self, slot):
        self.__mask &= ~(1 << slot)

    def has(self, slot):
        return (self.__mask >> slot) & 1

    def clear(self):
        self.__mask = 0


class TestBitmask(unittest.TestCase):

    def setUp(self):
        self.bitmask = BitMask()

    def test_set_on_valid_input(self):
        self.bitmask.set(5)
        self.assertEqual(self.bitmask.has(5), True)

    def test_has_on_valid_input(self):
        self.bitmask.set(5)
        self.assertEqual(self.bitmask.has(5), True)

    def test_remove_on_valid_input(self):
        self.bitmask.set(5)
        self.bitmask.remove(5)
        self.assertEqual(self.bitmask.has(5), False)

    def test_clear(self):
        for i in range(16):
            self.bitmask.set(i)
        self.bitmask.clear()
        for j in range(16):
            with self.subTest(j=j):
                self.assertEqual(self.bitmask.has(j), False)

我遇到的问题是所有这些测试都需要sethas方法来设置和检查位掩码中的值,但这些方法都是未经测试的。我不能确定一个是正确的而不知道另一个是。

这个示例类不是我第一次遇到这个问题。当我需要在类中设置和检查值/状态以测试方法时,通常会发生这种情况。

我试图找到解释此问题的资源,但遗憾的是他们的示例只有use pure functions或更改的属性可以是read {{3} }。我可以通过将方法提取为纯函数或使用返回属性__mask的只读属性来解决问题。

但这是首选方法吗?如果没有,我如何测试需要使用未经测试的方法设置和/或检查的方法?

2 个答案:

答案 0 :(得分:2)

不确定这会回答您的问题,因为它涉及更改初始课程设计, 但它就在这里。

你创建一个没有构造函数或属性的惰性类,它隐藏了你的状态 宾语。它不是未经测试的sethas方法,而是问题 对象的状态未知。您是否有.value属性要透露 self.__mask,这将解决测试.set()和has()的问题。

此外,我强烈考虑构造函数中的默认值,这使它看起来更好看 即时化并允许更容易的测试(关于在python is here中避免setter的一些建议)。

def __init__(self, mask=0):
    self.__mask = mask

如果有任何设计考虑因素阻止您拥有.value属性, 如果__init__接受一个值,也许可以使用`__eq__方法。

 a = BitMask(0)     
 b = BitMask(5)     
 a.set(5)
 assert a == b     

当然,你可以挑战__eq__tested本身的方式。

最后,也许你在修补猴子修补的情况下失败了 - a 阻止被测对象内部某些东西或使其工作方式不同的技术 (例如,模仿网络响应,无需实际通话)。使用任何用于路径的库 我认为你仍然会最终执行kind of x.__mask = value分配 对于像这里一样的小型,漂亮且本地定义的类来说,这不太合理。

希望它有助于您所探索的内容。

答案 1 :(得分:0)

我会使用单个下划线而不是double,只是直接查看单元测试中的_mask

Python实际上没有私有属性或方法,甚至可以在您的实例上访问双下划线属性,如下所示:obj._BitMask__mask。 如果希望子类不覆盖超类的属性,则使用双下划线。要表示“私人”,您应该使用单个下划线。

允许访问私有字段是python设计的一部分,因此使用此功能responsibly并不被认为是错误的,如果您正在访问您自己的类,则更是如此。

背后的理由&#34;不要触摸私人领域&#34;是因为你作为开发人员可以搞乱类的内部,s库的私有接口可以随时改变并破坏你的代码。 当你编写单元测试时,你不怕搞乱你自己的课程,并且如果你改变你的课程就接受你必须改变单元测试,所以这个编程习惯对你来说没用。