断言整数在范围内

38 投票
5 回答
38122 浏览
提问于 2025-04-29 09:29

我正在用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)

这样做相比我用两个断言的例子有什么好处吗?

暂无标签

5 个回答

0

另一种解决方案是下面这个类,如果你想在一个 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

dict 中比较数字:

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
2

在编程中,有时候你会遇到一些问题,比如代码运行不正常或者出现错误。这种情况下,很多人会去StackOverflow这个网站寻求帮助。这个网站就像一个大型的问答社区,程序员们可以在这里提问,也可以回答别人的问题。

当你在这个网站上提问时,最好把你的问题描述得清楚明白。比如,你可以告诉大家你在做什么,遇到了什么问题,错误信息是什么,甚至可以把相关的代码贴出来。这样,其他人才能更好地理解你的问题,并给出有效的建议。

如果你看到别人提问时没有提供足够的信息,可能会导致他们得不到帮助。所以,记得在提问时尽量详细,这样大家才能更快地帮到你。

总之,StackOverflow是一个很有用的地方,能帮助你解决编程中的各种问题,只要你提问得当,大家都会乐意帮忙。

self.assertTrue(998 <= my_integer <= 1000)
18

我觉得在使用 assertTrue 时直接进行比较并不是个好主意——这样会让失败信息变得不清楚:

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
----------------------------------------------------------------------

或者使用 assertLessEqualassertGreaterEqual

如果你不想使用自定义断言(虽然自定义断言会增加另一个错误追踪记录和几行代码):

...
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
29

Python里面有一个内置的函数可以用来做这个事情:assertAlmostEqual

self.assertAlmostEqual(myinteger, 999, delta=1)
# is equivalent to
self.assertTrue(998 <= myinteger <= 1000)
# ... but gives better error messages.

这个函数有一个可选的参数叫做delta,它用来指定你测试的值和期望值之间允许的差距。

49

你可以使用一种叫做“链式比较”的方法:

self.assertTrue(998 <= my_integer <= 1000)

撰写回答