断言一个整数在范围内

Posted

技术标签:

【中文标题】断言一个整数在范围内【英文标题】:Assert an integer is within range 【发布时间】:2014-12-19 19:29:43 【问题描述】:

我正在 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 个断言的示例相比,这有什么好处吗?

【问题讨论】:

你使用 1 个断言还是 2 个断言取决于你真正想了解和交流的内容。如果您只关心my_integer 是否在限制之间,那么一个断言是一种更简洁、更简洁的方法来测试并将其传达给下一个查看代码的人(可能在 3 个月内)。相反,如果有充分的理由分别知道 my_integer 是否低于 1000 以及知道 my_integer 是否高于 998,那么使用 2 个断言更有意义。 【参考方案1】:

Python 有一个 built in function,您可以使用它:assertAlmostEqual

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

可选参数 delta 指定与您正在测试的值的允许距离。

【讨论】:

【参考方案2】:

我认为在内部使用 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
----------------------------------------------------------------------

或者使用assertLessEqualassertGreaterEqual

如果您不想要自定义断言(它确实添加了另一条回溯记录和几行代码):

...
def test_no_custom_assert(self):
    my_integer = 100
    self.assertGreaterEqual(my_integer, 998)
    self.assertLessEqual(my_integer, 1000)
...

这比assertTrue(998 &lt;= my_integer &lt;= 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

【讨论】:

如果您将自定义断言方法放在具有 _unittest 全局的模块中,则将省略回溯,并且您将获得使用内置 TestCase.assertX 方法的漂亮干净的回溯。跨度> 【参考方案3】:
self.assertTrue(998 <= my_integer <= 1000)

【讨论】:

【参考方案4】:

您可以使用“chained comparison”:

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

【讨论】:

@Yep_It's_Me:你问这两个单独的条件是否有任何好处。是的。它更简洁、更清晰、更高效(一个函数调用而不是两个)。 @JohnZwinck 虽然我同意这更短,但我不认为这是我推荐的,因为它与两个assertTrues 具有相同的缺点。您失去了 FAIL 消息的冗长性。使用assertTrue,您将获得AssertionError: False is not true,这不是很有帮助。我更喜欢看看哪里出了问题,所以我宁愿使用assertGreaterEqual(my_integer, 998); assertLessEqual(my_integer, 1000) - 这样你就会立即知道哪里出了问题(例如:AssertionError: 100 not greater or equal to 998)。 带有此断言的错误消息不会说明my_integer 的值或限制(通常您没有像这样的硬编码限制)。所以我更喜欢@JanSpurny 回答中的 assertBetween 方法。

以上是关于断言一个整数在范围内的主要内容,如果未能解决你的问题,请参考以下文章

如何检查一个整数是不是在 PHP 中的数字范围内?

如何检查整数是不是在范围内?

在VB中,如何生成某个范围内的随机整数?

在 Julia 中生成范围内的随机整数

从整数范围内搜索

如何在私有范围内测试功能?