使用装饰器和元类跳过所有单元测试,但 Python 中的一个单元测试

Skipping all unit tests but one in Python by using decorators and metaclasses

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

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

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' 这是我只想在一个单元测试中设置的属性,以便对其进行调试。

所以下一步是我将它自动应用于我所有的 class 方法。 在网上阅读后,我发现以下代码使用 metaclass 来使用上述装饰器装饰所有方法。

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

所以我的最小工作示例是

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__'

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

有人可以帮忙吗?

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

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 的测试。

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

..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)

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

使用装饰器,通过环境参数初始化

MCU = os.getenv('MCU', False)

和装饰测试 类 and/or 方法通过 f.ex.

排除
@unittest.skipIf(MCU)

这可以称为

MCU=1 python # test file etc

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

这会将跳过的测试标记为 s