为什么unittest的断言方法比原始断言慢?

时间:2012-07-14 16:56:25

标签: python unit-testing

unittest附带了许多断言方法。我使用内置的Python assert和比较运算符vs内置的简单unittest断言进行了时间测试。

#!/usr/bin/python
import timeit

s = """\
import unittest
class TestRepomanManExtFunctions(unittest.TestCase):
    def test1(self):
        someObj = object()
        newObj = someObj
        self.assertEqual(someObj, newObj)

    def test2(self):
        str1 = '11111111111111111111111111111111111111'
        str2 = '33333333333333333333333333333333333333'
        self.assertNotEqual(str1, str2)


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

"""
t = timeit.Timer(stmt=s)
print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

s2 = """\
import unittest
class TestRepomanManExtFunctions(unittest.TestCase):
    def test1(self):
        someObj = object()
        newObj = someObj
        assert someObj == newObj

    def test2(self):
        str1 = '11111111111111111111111111111111111111'
        str2 = '33333333333333333333333333333333333333'
        assert str1 != str2


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

"""

t = timeit.Timer(stmt=s2)
print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)

结果

yeukhon@yeukhon-P5E-VM-DO:/tests$ python t.py
1203.46 usec/pass
873.06 usec/pass
yeukhon@yeukhon-P5E-VM-DO:tests$ vim t.py
yeukhon@yeukhon-P5E-VM-DO:tests$ python t.py
1300.33 usec/pass
956.35 usec/pass
yeukhon@yeukhon-P5E-VM-DO:tests$ python t.py
1208.82 usec/pass
865.18 usec/pass

使用unittest的内置断言方法的一个优点是它告诉用户实际比较的是什么。我的实际测试的一个例子:

======================================================================
FAIL: test_000_write_to_file_directory_not_exist (__main__.TestRepomanManExtFunctions)
Test writing content to a new file whose parent directory
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 1224, in patched
    return func(*args, **keywargs)
  File "test_ext.py", line 71, in test_000_write_to_file_directory_not_exist
    self.assertNotEqual(mk_exists.call_args_list, exists_call_list)
AssertionError: [call('/tmp/test/fake/')] == [call('/tmp/test/fake/')]

这是使用简单的assert X = Y

======================================================================
FAIL: test_000_write_to_file_directory_not_exist (__main__.TestRepomanManExtFunctions)
Test writing content to a new file whose parent directory
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 1224, in patched
    return func(*args, **keywargs)
  File "test_ext.py", line 72, in test_000_write_to_file_directory_not_exist
    assert exists_call_list != mk_exists.call_args_list
AssertionError

除了这个优势之外,利用内置self.assert_*(...)还可以做些什么呢?

为什么原料更快?我知道访问属性和对类的检查通常较慢。但是我想知道发生了什么?我希望这是一个有效的问题。

由于

2 个答案:

答案 0 :(得分:1)

断言*函数可能较慢,因为调用它有开销(将参数推送到堆栈,调用,从堆栈中弹出返回地址等),与内联执行的assert关键字相比。断言*函数有一些其他很好的属性,如你所提到的,比如打印预期值和实际值。

你是出于好奇而不是这是一个真正的问题吗?我很惊讶地发现任何断言速度都是瓶颈的情况。

答案 1 :(得分:0)

当单元测试由您使用的单元测试库提供的断言时,会收集有关测试的更多信息。他们收集枯萎测试成功或失败,导致错误的原因,捕获抛出的异常以及测试的任何输出。然后将此数据集合操作为stdout或xml文件所需的任何输出。这只需要花费时间并且需要大量的功能开销才能完成,其中单个断言就像或多或少的内联一样,并且显示错误以及文件和行号。

幕后两者之间存在巨大差异。