Python Decorator适用于函数,但不适用于类

Python Decorator适用于函数,但不适用于类,python,python-2.7,python-unittest,python-decorators,Python,Python 2.7,Python Unittest,Python Decorators,需要一些帮助来纠正unittest的装饰程序。我不确定如何满足单元测试的要求此装饰程序的想法是,如果传入True,则将测试标记为预期失败。否则,只允许测试运行。此修饰符适用于测试函数,但不适用于类定义 import unittest def expectedFailureIf(expFailure): if expFailure: return unittest.expectedFailure return lambda func: func @expect

需要一些帮助来纠正unittest的装饰程序。我不确定如何满足单元测试的要求此装饰程序的想法是,如果传入True,则将测试标记为预期失败。否则,只允许测试运行。此修饰符适用于测试函数,但不适用于类定义

import unittest

def expectedFailureIf(expFailure):
    if expFailure: 
        return unittest.expectedFailure
    return lambda func: func

@expectedFailureIf(GetCurrentOS() == kPlatMac)  # Fails on Class
class someClass(unittest.TestCase):
    #@expectedFailureIf(GetCurrentOS() == kPlatMac) # Works on Function
    def test_sometestA(self):
        assert True

    def test_sometestB(self):
        assert False
我得到的错误是test\u sometest()只接受一个参数。删除decorator允许运行测试。将decorator移到函数顶部可以运行测试


历史。。。我的一个平台可以正常工作,而另一个平台不能。我希望允许一个平台运行所有测试,而另一个平台将被标记为预期失败。当然,我不想使用skip或skip if。因为这将不允许有效的平台运行。将它们标记为预期失败也不起作用,因为一个平台将返回意外的成功。使用expectedFailureIf()后,每个平台都将正确地报告,一旦问题得到解决,这些测试将报告为意外成功。事情解决后会通知我的。为了我。。。这似乎是一个更好的结果。

在Python3上,您的代码运行良好。在那里更好,并且在类或函数上进行装饰时可以正常工作

在Python2上

这里有一个在Python2上工作的替换

import inspect
import types
import unittest

def expectedFailureIf(condition):
    if callable(condition):
        condition = condition()
    if not condition:
        # return identity function for no-op
        return lambda x: x
    def patch(func_or_class):
        if isinstance(func_or_class, types.FunctionType):
            return unittest.expectedFailure(func_or_class)
        for name, member in inspect.getmembers(func_or_class):
            if name.startswith('test') and isinstance(member, types.MethodType):
                setattr(func_or_class, name, unittest.expectedFailure(member))
        return func_or_class
    return patch

@expectedFailureIf(True)
class MyTest(unittest.TestCase):

    def test_that_passes(self):
        assert 2 + 2 == 4

    def test_that_fails(self):
        assert 2 + 2 == 5

if __name__ == "__main__":
    unittest.main(verbosity=2)
结果:

test_that_fails (__main__.MyTest) ... expected failure
test_that_passes (__main__.MyTest) ... unexpected success

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK (expected failures=1, unexpected successes=1)
警告 在Python中,意外的成功不会使测试运行失败这一事实是一个错误!早在2014年1月(Python3.4)就解决了这个问题,但由于向后兼容性问题,这个错误修复没有合并到2.7的分支中(请参见上的评论)。不幸的是,这就是Python2


如果这是对你的一个协议,请考虑升级到更多和/或使用.< /p>你不需要使用<代码>=Trime< /Cord>。这不是你有问题的原因,但这是你需要做的一切。在其他方面,您的装饰程序与@wim:跳过与预期失败完全相同。跳过表示不运行测试。预期失败运行测试,然后断言测试失败(报告意外成功)。SkipIf可能具有相同的功能,但不同。我希望测试在两个平台上运行。我希望在修复当前故障平台时收到通知。此外,我还为unittest的其他装饰者提供了一些想法,这将使我更好地跟踪“应该”修复的事情。单元测试修饰符有点限制。这是我想学的。好了,我现在明白了。当测试失败被修复并且测试意外通过该平台时,您希望出现测试失败。非常复杂,但现在有意义了。@wim:

skipIf()
条件修饰符的作用与此修饰符的作用完全相同,因此如果OP对此修饰符有问题,那么
skipIf
也是一个问题。您使用的是Python 3.x还是2.7?我从您的代码中得到的信息是:在0.000中运行了0个测试如果测试运行,那么测试应该在虚线和状态报告之前返回“test\u some\u test(main.SomeClassTest)…expected failure”。所以测试没有运行。修改您的代码,使其在If条件下包含print“Marked”:并将assert与math替换为assert False。运行测试并发现正在调用和标记装饰程序。不幸的是,测试本身没有运行。错误的是,测试正在运行。把一份打印的声明放进去,或者你自己看看。好的,这太棒了。完全适用于课堂案例。将decorator移到pass函数的顶部会显示:AttributeError:“MyTest”对象对于传递的函数没有属性“name”,而传递的函数的测试通过(main.MyTest)。。。输出顶部的错误语句。太棒了!!这适用于类调用和函数调用。我相信,我理解你在这里所做的,并且应该能够写一些对我的团队有用的其他装饰。