如何针对大量数据测试相同的断言
我正在使用 python unittest 模块来做一些测试;然而,这是非常重复的。
我有很多数据,我想一遍又一遍地进行相同的测试,检查是否正确。然而,我必须为每个人定义一个测试。
例如我想做类似的事情。我知道我可以使用生成器来完成它(在此处的上一个线程中找到它)。但是否有替代方案,甚至可能使用不同的测试模块?
任何建议都会很棒。
import unittest
class TestData(unittest.TestCase):
def testNumbers(self):
numbers = [0,11,222,33,44,555,6,77,8,9999]
for i in numbers:
self.assertEqual(i, 33)
I am using python unittest module to do a number of tests; however, it is very repetitive.
I have a lot of data that I want to run through the same test over and over, checking if correct. However, I have to define a test for every one.
For instance I want to do something similar to this. I know I could do it using a generator (found it in a previous thread here). But are there alternatives, maybe even using a different testing module?
Any suggestions would be great.
import unittest
class TestData(unittest.TestCase):
def testNumbers(self):
numbers = [0,11,222,33,44,555,6,77,8,9999]
for i in numbers:
self.assertEqual(i, 33)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
Bill Gribble 建议的解决方案的示例代码可能如下所示:
Sample code for solution suggested by Bill Gribble could look like this:
从 Python 3.4 开始,您可以使用
unittest.TestCase.subTest(msg=None, **params)
上下文管理器 (文档)。这将允许您通过添加一条语句来实现您想要的目的。这是修改为使用
subTest()
的示例As of Python 3.4 you can use
unittest.TestCase.subTest(msg=None, **params)
context manager (documentation). This will allow you to achieve what you want by adding just one statement.Here is your example modified to use
subTest()
您可能需要考虑使用unittest.TestSuite类,它允许您动态构造一组将单独运行的unittest.TestCase实例。你的unittest.TestCase子类应该只定义一个测试方法,该类接受一个构造参数,传入值来测试该特定实例。
You may want to consider using the unittest.TestSuite class, which will allow you to dynamically construct a set of unittest.TestCase instances which will get run separately. Your unittest.TestCase subclass should define just one test method, with the class accepting a construction parameter passing in the value to test against for that particular instance.
ddt
库 的构建是为了准确解决您所要求的单元测试
[*]。例如:
当您运行它时,您会得到 4 个测试用例,而不是只有一个:
请注意,ddt 尝试为生成的 TC 提供名称。
使用 pip 安装它:
[*] pythonic
pytest
框架 (pytest.mark.parametrize
) 的相同解决方案已集成到核心工具中,值得切换到 < code>pytest 只是为了这个功能。The
ddt
library was built to solve exactly what you are asking forunittest
[*].For example:
And when you run it, you get 4 TestCases instead of just one:
Notice that ddt tries to come up with names for the generated TCs.
Install it with pip:
[*] The same solution for the pythonic
pytest
framework (pytest.mark.parametrize
) is integrated into the core tool, and is worth switching topytest
just for this feature alone.在循环中运行断言的问题是,如果其中一个断言失败,您不知道哪个值导致它(在您的示例中,它将在
0
上失败,但您不知道知道这一点直到你调试)。另一方面,重复 self.assertEqual(i, 33) 是一个更糟糕的主意,因为它会引入代码重复。我在测试中所做的就是在测试中创建一个简单的、名称简短的内部函数,并使用不同的参数调用它。因此,您的函数将如下所示:
这样,当
0
断言失败时,您会立即在unittest
模块打印的堆栈跟踪上看到它。The problem with running assertions in a loop is that, if one of the assertions fails, you don't know which value caused it (in your example, it would fail on
0
, but you don't know that until you debug). On the other hand, repeatingself.assertEqual(i, 33)
is an even worse idea, because it introduces code duplication.What I do in my test is to create a simple, shortly-named internal function inside the test and call it with different arguments. So your function would look like this:
This way, when the assertion fails for
0
, you immediately see it on the stack trace printed by theunittest
module.在另一篇文章中我偶然发现
鼻子测试
它更适合数据驱动的测试。
上面的代码与我的第一篇文章的作用完全相同。
不需要导入,只需编写一个 python 类即可。
您可以通过键入以下内容来执行测试:
nosetests filename
In another post I stumbled accross
Nose Tests
It is more suited to data driven testing.
The above code does the exact same thing as my first post.
No imports are needed, just write a python class.
You execute the tests by typing:
nosetests filename
这个答案的副产品,对我来说不太有效。在我不处理大量数据的情况下,我确实需要使用不同的输入运行相同的测试。以下测试使用我想要自定义的
create_a
和create_b
方法。要求是使用相同的自定义来运行这两个测试。
我自己实例化
TestSuite
和TestCase
绕过测试加载程序,导致错误,因为它需要一个名为runTest
的方法。结果是这样的:
Spin-off of this answer, which didn't quite work for me. Where I'm not dealing with large amounts of data, I did need to run same tests with different inputs. The following tests are using
create_a
andcreate_b
methods which I want to customize.The requirement is to run both tests with the same customization.
Instantiating
TestSuite
andTestCase
myself, bypassing the test loader, resulted in an error because it expected a single method, calledrunTest
.The result was this: