现在为什么不在测试中使用 python 的 assert 语句呢?
Why not use python's assert statement in tests, these days?
在Python测试中,为什么要使用断言方法:
self.assertEqual(response.status_code, 200)
self.assertIn('key', my_dict)
self.assertIsNotNone(thing)
与直接断言相反:
assert response.status_code == 200
assert 'key' in my_dict
assert thing is not None
根据 docs:
These methods are used instead of the assert statement so the test runner can accumulate all test results and produce a report
然而,这似乎是假的,测试运行者可以累积结果并生成报告。在 related post 中,unutbu 表明 unittest 将引发一个 AssertionError
,就像 assert 语句一样,那是 7 年多以前的事了,所以它也不是一个闪亮的新功能。
对于像 pytest 这样的现代测试运行器,由断言辅助方法生成的失败消息不再具有可读性(可以说 unittest 的驼峰命名风格 less 可读) . 那么,为什么不在你的测试中使用 assert 语句呢? 有哪些明显的缺点,为什么 CPython 等重要项目还没有离开 unittest?
您找到的文档的 link 是正确答案。如果您不喜欢这种编写测试的风格,我强烈建议您使用 pytest:
pytest 已经完成了大量工作,允许您按照自己的方式使用 assert 语句。它还具有许多其他非常好的功能,例如它们的固定装置。
使用 assert
关键字或专用方法的主要区别在于输出报告。请注意,assert
后面的语句始终是 True
或 False
,不能包含任何额外信息。
assert 3 == 4
只会在报告中显示一个 AssertionError
。
然而,
self.assertTrue(3 == 4)
提供一些额外信息:AssertionError: False is not true
。不是很有帮助,但请考虑:
self.assertEqual(3, 4)
更好,因为它告诉你 AssertionError: 3 != 4
。你读了报告,你知道它是什么类型的断言(平等检验)和涉及的价值。
假设您有一些功能,并且想要断言它的值 returns。
您可以通过两种方式进行:
# assert statement
assert your_function_to_test() == expected_result
# unittest style
self.assertEqual(your_function_to_test(), expected_result)
如果出现错误,第一个除了断言错误之外不提供任何信息,第二个告诉您断言的类型(相等性测试)以及涉及的值(返回值和预期值)。
对于小型项目,我从不使用 unittest 样式,因为它的输入时间更长,但在大型项目中,您可能想了解更多有关错误的信息。
我认为在大多数情况下,您可以使用当前的 pytest 版本 assert
,因为上下文是由测试框架 (pytest 2.9.2) 重建的:
def test_requests(self):
...
> self.assertEqual(cm.exception.response.status_code, 200)
E AssertionError: 404 != 200
看起来类似于
def test_requests(self):
...
> assert cm.exception.response.status_code == 200
E AssertionError: assert 404 == 200
E -404
E +200
理论上,使用 self.assertXxx()
方法将允许 pytest 计算 未 失败的断言的数量,但 AFAIK 没有这样的指标。
我不完全确定我理解这个问题。标题是“这些天为什么不在测试中使用pythons断言语句”。
正如您所指出的,事实上 如果您使用像 pytest 这样的 test-framework,则 您可以使用普通断言。 但是 pytest 做了一些非常特别的事情来让它工作。它 re-writes 在运行测试之前 test-code 中的简单断言。
参见 https://docs.pytest.org/en/stable/writing_plugins.html#assertion-rewriting 其中指出:
One of the main features of pytest is the use of plain assert statements and the detailed introspection of expressions upon assertion failures. This is provided by “assertion rewriting” which modifies the parsed AST before it gets compiled to bytecode.
单元测试框架不实现这种额外的复杂性。 (而且它 是 额外的复杂性。Pytest re-writes 只有测试用例中的断言,它不会 re-write 其他 python 库中的断言你的 test-code 使用。所以你有时会发现 pytest 在你的 test-code 中遇到断言错误,但是没有关于为什么断言失败的详细信息,因为它没有 re-written 那一点你的代码。因此你只得到一个普通的 AssertionError
,没有任何关于失败原因的信息。)
相反,unittest 提供了类似 assertEqual
的方法,因此它可以:
- 知道这是一个失败的测试断言,而不是其他一些 unhandled/unexpected 异常;和
- 它可以提供有关为什么不满足断言的信息。 (python 中的一个普通断言除了引发 AssertionError 什么都不做。它没有说,例如
AssertionError because 1 != 2
)
Pytest 在运行 test-code 之前通过 re-writing 抽象语法树执行编号 1 和编号 2。 Unittest 采用更传统的方法,即要求开发人员使用特定方法。
所以基本上答案是:它是 test-frameworks 之间的 实现差异。换句话说,Python 的 in-built assert
语句不提供有关故障发生原因的调试信息。因此,如果您需要更多信息,则需要决定如何实施它。
Unittest比pytest简单多了。 Pytest 很棒,但也复杂得多。
在Python测试中,为什么要使用断言方法:
self.assertEqual(response.status_code, 200)
self.assertIn('key', my_dict)
self.assertIsNotNone(thing)
与直接断言相反:
assert response.status_code == 200
assert 'key' in my_dict
assert thing is not None
根据 docs:
These methods are used instead of the assert statement so the test runner can accumulate all test results and produce a report
然而,这似乎是假的,测试运行者可以累积结果并生成报告。在 related post 中,unutbu 表明 unittest 将引发一个 AssertionError
,就像 assert 语句一样,那是 7 年多以前的事了,所以它也不是一个闪亮的新功能。
对于像 pytest 这样的现代测试运行器,由断言辅助方法生成的失败消息不再具有可读性(可以说 unittest 的驼峰命名风格 less 可读) . 那么,为什么不在你的测试中使用 assert 语句呢? 有哪些明显的缺点,为什么 CPython 等重要项目还没有离开 unittest?
您找到的文档的 link 是正确答案。如果您不喜欢这种编写测试的风格,我强烈建议您使用 pytest:
pytest 已经完成了大量工作,允许您按照自己的方式使用 assert 语句。它还具有许多其他非常好的功能,例如它们的固定装置。
使用 assert
关键字或专用方法的主要区别在于输出报告。请注意,assert
后面的语句始终是 True
或 False
,不能包含任何额外信息。
assert 3 == 4
只会在报告中显示一个 AssertionError
。
然而,
self.assertTrue(3 == 4)
提供一些额外信息:AssertionError: False is not true
。不是很有帮助,但请考虑:
self.assertEqual(3, 4)
更好,因为它告诉你 AssertionError: 3 != 4
。你读了报告,你知道它是什么类型的断言(平等检验)和涉及的价值。
假设您有一些功能,并且想要断言它的值 returns。 您可以通过两种方式进行:
# assert statement
assert your_function_to_test() == expected_result
# unittest style
self.assertEqual(your_function_to_test(), expected_result)
如果出现错误,第一个除了断言错误之外不提供任何信息,第二个告诉您断言的类型(相等性测试)以及涉及的值(返回值和预期值)。
对于小型项目,我从不使用 unittest 样式,因为它的输入时间更长,但在大型项目中,您可能想了解更多有关错误的信息。
我认为在大多数情况下,您可以使用当前的 pytest 版本 assert
,因为上下文是由测试框架 (pytest 2.9.2) 重建的:
def test_requests(self):
...
> self.assertEqual(cm.exception.response.status_code, 200)
E AssertionError: 404 != 200
看起来类似于
def test_requests(self):
...
> assert cm.exception.response.status_code == 200
E AssertionError: assert 404 == 200
E -404
E +200
理论上,使用 self.assertXxx()
方法将允许 pytest 计算 未 失败的断言的数量,但 AFAIK 没有这样的指标。
我不完全确定我理解这个问题。标题是“这些天为什么不在测试中使用pythons断言语句”。
正如您所指出的,事实上 如果您使用像 pytest 这样的 test-framework,则 您可以使用普通断言。 但是 pytest 做了一些非常特别的事情来让它工作。它 re-writes 在运行测试之前 test-code 中的简单断言。
参见 https://docs.pytest.org/en/stable/writing_plugins.html#assertion-rewriting 其中指出:
One of the main features of pytest is the use of plain assert statements and the detailed introspection of expressions upon assertion failures. This is provided by “assertion rewriting” which modifies the parsed AST before it gets compiled to bytecode.
单元测试框架不实现这种额外的复杂性。 (而且它 是 额外的复杂性。Pytest re-writes 只有测试用例中的断言,它不会 re-write 其他 python 库中的断言你的 test-code 使用。所以你有时会发现 pytest 在你的 test-code 中遇到断言错误,但是没有关于为什么断言失败的详细信息,因为它没有 re-written 那一点你的代码。因此你只得到一个普通的 AssertionError
,没有任何关于失败原因的信息。)
相反,unittest 提供了类似 assertEqual
的方法,因此它可以:
- 知道这是一个失败的测试断言,而不是其他一些 unhandled/unexpected 异常;和
- 它可以提供有关为什么不满足断言的信息。 (python 中的一个普通断言除了引发 AssertionError 什么都不做。它没有说,例如
AssertionError because 1 != 2
)
Pytest 在运行 test-code 之前通过 re-writing 抽象语法树执行编号 1 和编号 2。 Unittest 采用更传统的方法,即要求开发人员使用特定方法。
所以基本上答案是:它是 test-frameworks 之间的 实现差异。换句话说,Python 的 in-built assert
语句不提供有关故障发生原因的调试信息。因此,如果您需要更多信息,则需要决定如何实施它。
Unittest比pytest简单多了。 Pytest 很棒,但也复杂得多。