使用装饰器和元类跳过所有单元测试,但在 Python 中只有一个 [英] Skipping all unit tests but one in Python by using decorators and metaclasses

查看:41
本文介绍了使用装饰器和元类跳过所有单元测试,但在 Python 中只有一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 MCU 编写单元测试,该 MCU 通过 USB 端口传输命令并检查其响应.如果一个单元测试失败,我在 MCU 中进行一些调试是有意义的.因此,除了我想在 MCU 端调试的单元测试之外,我想禁用所有单元测试,因为如果我在某处设置断点,它可能会被另一个具有不同命令的单元测试触发.

I am writing unit tests for an MCU that communicates commands through the USB port and checks their response. If one unit test fails it makes sense for me to do some debugging in the MCU. Therefore I would like to disable all unittests except for the one that I would like to debug on the MCU side because if I set a breakpoint somewhere it might get triggered by another unittest with different commands.

我去了 python 文档,发现这段代码是一个装饰器,它会跳过所有没有属性的单元测试.

I went to the python docs and found this code which is a decorator that will skip all unittests that don't have an attribute.

def skipUnlessHasattr(obj, attr):
    if hasattr(obj, attr):
        return lambda func: func
return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))

为了使它更简单,我删除了 attr 参数并将其静态更改为StepDebug",这是一个我只想在一个单元测试中设置以进行调试的属性.

In order to make it more simple I deleted the attr argument and statically changed it to 'StepDebug' which is an attribute that I want to set in only one unittest in order to debug it.

所以下一步是我将它自动应用于我所有的类方法.在网上阅读后,我发现以下代码使用元类来使用上述装饰器装饰所有方法.https://stackoverflow.com/a/6308016/3257551

So the next step is for me to apply this for all my class methods automatically. After reading around on the webs I found the following code that uses a metaclass in order to decorate all methods with the above decorator. https://stackoverflow.com/a/6308016/3257551

def decorating_meta(decorator):
class DecoratingMetaclass(type):
    def __new__(self, class_name, bases, namespace):
        for key, value in list(namespace.items()):
            if callable(value):
                namespace[key] = decorator(value)
        return type.__new__(self, class_name, bases, namespace)

return DecoratingMetaclass

所以我的最小工作示例是

So my minimum working example is

import unittest

def decorating_meta(decorator):
    class DecoratingMetaclass(type):
        def __new__(self, class_name, bases, namespace):
            for key, value in list(namespace.items()):
                if callable(value):
                    namespace[key] = decorator(value)
            return type.__new__(self, class_name, bases, namespace)

    return DecoratingMetaclass

def skipUnlessHasattr(obj):
    if hasattr(obj, 'StepDebug'):
        return lambda func : func
    return unittest.skip("{!r} doesn't have {!r}".format(obj, 'StepDebug'))

class Foo(unittest.TestCase):
    __metaclass__ = decorating_meta(skipUnlessHasattr)
    def test_Sth(self):
        self.assertTrue(False)

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

我得到的错误是:

AttributeError: 'Foo' object has no attribute '__name__'

据我所知,当您拥有一个实例而不是类时会发生这种情况,但我不太明白如何使用这些信息来解决我的问题.

From what I read this is something that happens when instead of a class you have an instance but I don't quite understand how I can use this information to solve my problem.

有人可以帮忙吗?

推荐答案

好的,我找到了一种方法来获得我想要的功能.我将装饰器更改为:

Ok I found a way to have the functionality that I want. I changed the decorator to:

def skipUnlessHasattr(obj):
    if hasattr(obj, 'StepDebug'):
        def decorated(*a, **kw):
            return obj(*a, **kw)
        return decorated
    else:
        def decorated(*a, **kw):
            return unittest.skip("{!r} doesn't have {!r}".format(obj, 'StepDebug'))
        return decorated

现在我跳过了所有测试,除了添加了属性 StepDebug 的测试.

Now I get all tests skipped except the ones that I have added an attribute StepDebug.

唯一的小问题是输出不会将所有其他测试报告为已跳过,而是报告为成功.

The only minor thing with this is that the output doesn't report all the other tests as skipped but rather as a success.

..F..
======================================================================
FAIL: test_ddd (__main__.Foo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./Documents/programs/Python/mwe.py", line 23, in     decorated
    return obj(*a, **kw)
  File "./Documents/programs/Python/mwe.py", line 39, in     test_ddd
    self.assertTrue(False)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 5 tests in 0.014s

FAILED (failures=1)

附言为什么在缩进 4 个空格后复制输出时它不会进入代码块?我也尝试了 8 个空格,但它不起作用.最终我在每行中添加了 4 个空格.有没有更聪明的方法?

P.S. Why when copying the output after indenting 4 spaces it doesn't go into a code block? I tried 8 spaces as well and it wouldn't work. Eventually I added 4 spaces to each line. Is there a smarter way?

这篇关于使用装饰器和元类跳过所有单元测试,但在 Python 中只有一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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