Python 如何在没有太多负担的情况下使用'assertEqual()`[或同等产品]?

Python 如何在没有太多负担的情况下使用'assertEqual()`[或同等产品]?,python,assert,python-unittest,Python,Assert,Python Unittest,我正在寻找一种方法(如果可用的话),它可以比较两个值,并在比较失败时用有意义的消息引发断言错误 如果使用assert,则失败消息不包含在断言失败时比较的值 >>> a = 3 >>> b = 4 >>> assert a == b Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError >>

我正在寻找一种方法(如果可用的话),它可以比较两个值,并在比较失败时用有意义的消息引发断言错误

如果使用
assert
,则失败消息不包含在断言失败时比较的值

>>> a = 3
>>> b = 4
>>> assert a == b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> 
请注意,这里的断言错误消息包含已比较的值。这在现实生活中非常有用,因此对我来说是必要的。普通的
断言
(见上文)不会这样做

但是,到目前为止,我只能在继承自
unittest.TestCase
的类中使用
assertEqual()
,并提供了一些其他必需的方法,如
runTest()
。我想在任何地方使用
assertEqual()
,而不仅仅是在继承的类中。可能吗

我尝试了以下方法,但都不起作用

>>> import unittest
>>> unittest.TestCase.assertEqual(a, b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method failUnlessEqual() must be called with TestCase instance as first argument (got int instance instead)
>>> 
>>> 
>>> tc = unittest.TestCase()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/unittest.py", line 215, in __init__
    (self.__class__, methodName)
ValueError: no such test method in <class 'unittest.TestCase'>: runTest
>>> 
导入单元测试 >>>unittest.TestCase.assertEqual(a,b) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:必须使用TestCase实例作为第一个参数调用未绑定方法failUnlessEqual()(改为使用int实例) >>> >>> >>>tc=unittest.TestCase() 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“/usr/lib64/python2.6/unittest.py”,第215行,在__ (self.\uuuu类\uuuuu,方法名) ValueError:在:runTest中没有此类测试方法 >>>

是否有其他软件包或库提供类似的方法,如
assertEqual()
,无需附加约束即可轻松使用?

您必须手动给出断言消息:

assert a == b, '%s != %s' % (a, b)
# AssertionError: 3 != 4

你看过numpy测试吗

其中包括: 如果两个项不等于所需精度,则assert_几乎等于(实际、所需[,…])将引发AssertionError


这个断言打印出实际的和期望的。如果提高精度,则比较任意接近==(对于浮点)

可以创建一个“助手”新模块,提供对断言函数的访问<代码>资产访问器
在这种情况下:

from unittest import TestCase

# Dummy TestCase instance, so we can initialize an instance
# and access the assert instance methods
class DummyTestCase(TestCase):
    def __init__(self):
        super(DummyTestCase, self).__init__('_dummy')

    def _dummy(self):
        pass

# A metaclass that makes __getattr__ static
class AssertsAccessorType(type):
    dummy = DummyTestCase()

    def __getattr__(cls, key):
        return getattr(AssertsAccessor.dummy, key)

# The actual accessor, a static class, that redirect the asserts
class AssertsAccessor(object):
    __metaclass__ = AssertsAccessorType
只需创建一次模块,就可以访问
unittest
包中的所有断言,例如:

AssertsAccessor.assertEquals(1, 2)
断言错误:1!=二,

或者另一个例子:

AssertsAccessor.assertGreater(1, 2)
其结果是:

断言错误:1不大于2

假设为访问者创建的模块名为
assertions
,代码中的常见用法如下:

from assertions import AssertsAccessor

def foo(small_arg, big_arg):
    AssertsAccessor.assertGreater(big_arg, small_arg)
    # some logic here

我在过去也做过类似的工作,最后编写了简短的自定义断言,它接受任何条件作为输入

import inspect

def custom_assert(condition):
    if not condition:
        frame = inspect.currentframe()
        frame = inspect.getouterframes(frame)[1]
        call_signature = inspect.getframeinfo(frame[0]).code_context[0].strip()

        import re
        argument = re.search('\((.+)\)', call_signature).group(1)
        if '!=' in argument:
            argument = argument.replace('!=','==')
        elif '==' in argument:
            argument = argument.replace('==','!=')
        elif '<' in argument:
            argument = argument.replace('<','>=')
        elif '>' in argument:
            argument = argument.replace('>','<=')
        elif '>=' in argument:
            argument = argument.replace('>=','<')
        elif '<=' in argument:
            argument = argument.replace('<=','>')

        raise AssertionError(argument)

if __name__ == '__main__':
    custom_assert(2 == 1)
导入检查
def自定义_断言(条件):
如果不是条件:
frame=inspect.currentframe()
frame=inspect.getouterframes(frame)[1]
调用\u signature=inspect.getframeinfo(框架[0])。代码\u上下文[0]。strip()
进口稀土
argument=re.search('\(.+)\'),call\u签名。组(1)
如果“!=”争论中:
参数=参数。替换(“!=”,“=”)
参数中的elif“==”:
参数=参数。替换(“==”,“!=”)
参数中的elif“”:
参数=参数。替换参数中的(“>”,“=”:

argument=argument.replace(“>=”,“assertEqual或任何其他assertXxx()方法要求第一个参数是对象引用。通常我们将该方法称为
self.assertEqual(first,second,msg=None)
。 此处
self
满足第一个预期参数。要避免这种情况,我们可以执行以下操作:

from unittest import TestCase as tc
def some_func():
    dummy_obj = tc()
    tc.assertEqual(dummy_obj, 123, 123, msg='Not Equal')

这种行为的原因是XUnit框架的遗留问题。

您是否尝试过
unittest.TestCase().assertEqual(a,b)
?@AbdulNiyasPM:它也不起作用。同样的错误:
ValueError:在:runTest中没有这样的测试方法是的。但是,这是大量的额外键入:)事实上,键入额外而不添加额外的“信息”到源代码。如果没有出来,那么我正在考虑创建我自己的小库来进行这样的包装:)。很有趣。我之前没有检查
numpy。测试
。他们也有
assert_equal()
!但是,他们没有assertXxx()这是由
unittest.TestCase
提供的。这也是一个有趣的想法。谢谢。欢迎使用。
Traceback (most recent call last):
  File "custom_assert.py", line 27, in <module>
    custom_assert(2 == 1)
  File "custom_assert.py", line 24, in custom_assert
    raise AssertionError(argument)
AssertionError: 2 != 1
from unittest import TestCase as tc
def some_func():
    dummy_obj = tc()
    tc.assertEqual(dummy_obj, 123, 123, msg='Not Equal')