我正在用 python 编写一些单元测试,测试我是否收到一个整数。然而有时这个整数可能会偏离 1 或 2,我并不关心。本质上我希望能够断言接收到的整数在一定范围内,例如:
self.assertBetween(998, 1000, my_integer)
有公认的方法吗?或者我必须做这样的事情:
self.assertTrue(998 <= my_integer)
self.assertTrue(my_integer <= 1000)
编辑 到目前为止的答案表明:
self.assertTrue(998 <= my_integer <= 1000)
与我的带有 2 个断言的示例相比,这有什么好处吗?
您可以使用“链式比较”:
self.assertTrue(998 <= my_integer <= 1000)
Python 有一个 内置函数,您可以使用它:
assertAlmostEqual
。
self.assertAlmostEqual(myinteger, 999, delta=1)
# is equivalent to
self.assertTrue(998 <= myinteger <= 1000)
# ... but gives better error messages.
可选参数 delta 指定与您正在测试的值的允许距离。
我认为使用
assertTrue
并进行内部比较并不是一个好主意 -
这样您就会丢失 FAIL 消息中的任何信息:
AssertionError: False is not true
这根本没有帮助,你基本上回到了“原始”
assert
,并且你失去了很多unittest
方法的好处。
我会推荐:
您可以在其中打印更有意义的消息。例如:
import unittest
class BetweenAssertMixin(object):
def assertBetween(self, x, lo, hi):
if not (lo <= x <= hi):
raise AssertionError('%r not between %r and %r' % (x, lo, hi))
class Test1(unittest.TestCase, BetweenAssertMixin):
def test_between(self):
self.assertBetween(999, 998, 1000)
def test_too_low(self):
self.assertBetween(997, 998, 1000)
def test_too_high(self):
self.assertBetween(1001, 998, 1000)
if __name__ == '__main__':
unittest.main()
然后你将得到以下输出(缩短):
======================================================================
FAIL: test_too_high (__main__.Test1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "example.py", line 19, in test_too_high
self.assertBetween(1001, 998, 1000)
File "example.py", line 8, in assertBetween
raise AssertionError('%r is not between %r and %r' % (x, lo, hi))
AssertionError: 1001 is not between 998 and 1000
======================================================================
FAIL: test_too_low (__main__.Test1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "example.py", line 16, in test_too_low
self.assertBetween(997, 998, 1000)
File "example.py", line 8, in assertBetween
raise AssertionError('%r is not between %r and %r' % (x, lo, hi))
AssertionError: 997 is not between 998 and 1000
----------------------------------------------------------------------
assertLessEqual
和 assertGreaterEqual
如果您不需要自定义断言(这会添加另一个回溯记录和几行代码):
...
def test_no_custom_assert(self):
my_integer = 100
self.assertGreaterEqual(my_integer, 998)
self.assertLessEqual(my_integer, 1000)
...
比
assertTrue(998 <= my_integer <= 1000)
稍长一些(如果只使用一次,它可能比添加自定义断言要短),但您仍然会得到很好的失败消息(也没有额外的回溯记录):
======================================================================
FAIL: test_no_custom_assert (__main__.Test1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "example.py", line 23, in test_no_custom_assert
self.assertGreaterEqual(my_integer, 998)
AssertionError: 100 not greater than or equal to 998
self.assertTrue(998 <= my_integer <= 1000)
另一个解决方案是下面的类,如果您想轻松比较
dict
中的数字,它会非常方便:
@dataclass
class IsBetweenOrEqual:
lower_bound: float
upper_bound: float
def __eq__(self, actual) -> bool:
return self.lower_bound <= actual <= self.upper_bound
正在执行的课程:
3 == IsBetweenOrEqual(2, 3)
>>> True
3 == IsBetweenOrEqual(2, 2.5)
>>> False
比较字典中的数字:
allowed_dict = {"num1": IsBetweenOrEqual(0, 2), "num2": 2}
test_dict1 = {"num1": 1, "num2": 2}
test_dict2 = {"num1": 10, "num2": 2}
test_dict1 == allowed_dict
>>> True
test_dict2 == allowed_dict
>>> False