【问题标题】:Python unittest call function when assertion fails断言失败时的Python unittest调用函数
【发布时间】:2016-12-07 19:47:15
【问题描述】:

目标:只有在测试失败时,我才需要调用一堆步骤(因此是一个函数)。

我尝试了什么:

1) 尝试传递不带参数的函数。

观察:如果测试通过,函数不会被调用。但是如果测试失败,我会得到一个错误。 (AssertionError: <bound method TestAuto.func1 of <test_fail.TestAuto testMethod=test_fail>>)

class TestAuto(unittest.TestCase):
    def test_fail(self):
        self.assertEqual(1, 1, self.func1)
    def func1(self):
        print 'We are inside'
if __name__ == '__main__':
    unittest.main()

test_fail (test_fail.TestAuto) ... ok

----------------------------------------
Ran 1 test in 0.001s

OK

2) 尝试使用参数调用函数。

class TestAuto(unittest.TestCase):
    def test_fail(self):
        self.assertEqual(1, 1, self.func1('message'))
    def func1(self, msg):
        print msg

观察:无论测试通过还是失败都会调用函数。

结果:

test_fail (test_fail.TestAuto) ... 消息 好的


在 0.001 秒内运行 1 次测试

好的

【问题讨论】:

  • 它不会因为没有理由1等于1 assertEqual(first, second, msg="message!")第三个参数是消息。还有更多:在第一个中,您不使用 ->() 调用该函数

标签: python unit-testing


【解决方案1】:

您可以使用序号try/except 声明:

from exceptions import AssertionError as AE

class TestAuto(unittest.TestCase):
    def test_not_fail(self):
        # won't call func1
        try:
            self.assertEqual(1, 1)
        except AE:
            self.func1()
            raise

    def test_fail(self):
        # will call func1
        try:
            self.assertEqual(1, 9)
        except AE:
            self.func1()
            raise

    def func1(self):
        print 'We are inside'

可以实现为装饰器,方便使用:

from exceptions import AssertionError as AE

def run_if_test_fails(call_on_fail):
    def deco(f):
        def inner(*args, **kwargs):
            try:
                f(*args, **kwargs)
            except AE:
                # test failed - run callback
                call_on_fail()
                # reraise Error to mark it in result
                raise
        return inner
    return deco

def func1():
    print('We are inside')

class TestAuto(unittest.TestCase):

    @run_if_test_fails(func1)
    def test_not_fail(self):
        # won't call func1
        self.assertEqual(1, 1)

    @run_if_test_fails(func1)
    def test_fail(self):
        # will call func1
        self.assertEqual(1, 9)

【讨论】:

    【解决方案2】:

    各种断言方法的“消息”参数旨在作为描述测试失败的字符串。在您的第一个示例中,您传递了一个函数。如果断言成功,则不使用它,如果测试失败,则打印它(因为这就是消息所发生的事情)。

    在您的第二个示例中,您已经进行了函数调用以准备参数 - 这发生在 assertEquals 被调用之前。 'message' 被打印是因为您在 func1 中调用 print。

    【讨论】:

    • 我同意你的观点。这解释了观察到的行为。我虽然找到了解决问题的方法(在此处发布)。告诉我你是否同意。
    【解决方案3】:

    msg=None 期望显示某些内容。所以如果我们想使用一个函数,我们需要返回一些东西。现在我只尝试了字符串并且它有效。

    class TestAuto(unittest.TestCase):
        def test_fail(self):
            self.assertEqual(1, 1, msg=self.func1('2 msg'))
        def func1(self, mesg=None):
            if mesg:
                return mesg
            else:
                return 'Just an error'
    

    1) 案例一:测试失败时

    ==============================================================
    FAIL: test_fail (test_fail.TestAuto)
    --------------------------------------------------------------
    Traceback (most recent call last):
      File "test_fail.py", line 5, in test_fail
        self.assertEqual(1, 2, msg=self.func1('2 msg'))
    AssertionError: 2 msg
    
    --------------------------------------------------------------
    Ran 1 test in 0.002s
    
    FAILED (failures=1)
    

    2) 案例2:测试通过时

    self.assertEqual(1, 1, msg=self.func1('2 msg'))
    
    test_fail (test_fail.TestAuto) ... ok
    
    --------------------------------------------------------------
    Ran 1 test in 0.001s
    
    OK
    

    【讨论】:

    • self.func1('2 msg') 不管测试是否失败都会被调用
    • @GennadyKandaurov ..你是对的。我刚刚发现了。我正在尝试捕获测试的状态并在调用的函数中使用它。
    猜你喜欢
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多