避免猴子补丁错误的 Python 单元测试最佳实践 [英] Python unit test best practice to avoid monkey patching bug

查看:32
本文介绍了避免猴子补丁错误的 Python 单元测试最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在我的单元测试中遇到了一个错误,因为我基本上是在设置中进行猴子修补,如下所示:

def test_some_class_to_string():some_class = SomeClass()some_class.foo = 'bar'some_class.monkey_patched = 'baz'断言 str(some_class) == 'barbaz'类 SomeClass(models.Model):foo = models.CharField(max_length=100)def __str__(self):#monkey_patched 属性从模型中删除返回 '​​{0}{1}'.format(self.foo, self.monkey_patched)

我已从 SomeClass 中删除了一个属性,但由于在运行时重新添加了monkey_patched,str 方法仍在单元测试中通过.

最好在任何属性设置之前调用 str(some_class) 作为附加测试来处理这种特殊情况,还是应该始终使用关键字参数来初始化单元测试中的类?

解决方案

使用像 mock 这样的库来帮助您完成此操作.假设你有一个这样定义的类:

A 类:def __init__(self, x):自我.x = xself.y = 6

现在,不是简单地创建一个 A 的实例并用它做任何你想做的事情,而是创建一个模拟对象,它是一个版本实例>A:

<预><代码>>>>m = unittest.mock.Mock(spec_set=A)>>>m.z = 9回溯(最近一次调用最后一次):文件tmp.py",第 11 行,在 <module> 中m.z = 9文件.../unittest/mock.py",第 684 行,在 __setattr__ 中raise AttributeError("Mock 对象没有属性 '%s'" % name)AttributeError: Mock 对象没有属性z"

I have just encountered a bug with my unit test, because I was essentially monkey patching in the set up like so:

def test_some_class_to_string():
    some_class = SomeClass()
    some_class.foo = 'bar'
    some_class.monkey_patched = 'baz'
    assert str(some_class) == 'barbaz'

class SomeClass(models.Model):
    foo = models.CharField(max_length=100)

    def __str__(self):
        #monkey_patched property removed from model
        return '{0}{1}'.format(self.foo, self.monkey_patched)

I had removed a property from SomeClass but the str method was still passing in the unit test due to re-adding monkey_patched at runtime.

Is it best to deal with this particular situation by calling str(some_class) before any property setup as an additional test, or should I always use keyword arguments to initialise classes in unit tests?

解决方案

Use a library like mock to assist you with doing this. Say you have a class defined like this:

class A:
    def __init__(self, x):
        self.x = x
        self.y = 6

Now, instead of simply creating an instance of A and doing whatever you want with it, create a mock object that is an instrumented version of an instance of A:

>>> m = unittest.mock.Mock(spec_set=A)
>>> m.z = 9
Traceback (most recent call last):
  File "tmp.py", line 11, in <module>
    m.z = 9
  File ".../unittest/mock.py", line 684, in __setattr__
    raise AttributeError("Mock object has no attribute '%s'" % name)
AttributeError: Mock object has no attribute 'z'

这篇关于避免猴子补丁错误的 Python 单元测试最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆