使用 CppUnit 参数化测试
我的组织正在使用 CppUnit,我正在尝试使用不同的参数运行相同的测试。 在测试中运行循环不是一个好的选择,因为任何失败都会中止测试。 我已经查看了 TestDecorator
和 TestCaller
但似乎都不适合。 代码示例会很有帮助。
My organization is using CppUnit and I am trying to run the same test using different parameters. Running a loop inside the test is not a good option as any failure will abort the test. I have looked at TestDecorator
and TestCaller
but neither seems to really fit. Code samples would be helpful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
在 CppUnit 中似乎不可能直接参数化测试用例(请参阅 此处和此处 )。 但是,您确实有几个选择:
使用
RepeatedTest
您也许可以巧妙地利用内置的
RepeatedTest
装饰器。 这允许测试用例运行多次(尽管没有参数化)。我承认我自己从未使用过这个,但也许您可以让
RepeatedTest
驱动一些看门人函数,这将(也许使用类静态变量?)在每次运行时选择不同的输入。 它会依次调用您想要测试的 true 函数,并使用该值作为输入。使用
TestCase
子类一个人 CppUnit 的 SourceForge 页面上声称已编写了
TestCase
的子类,它将运行特定测试任意次数,尽管与RepeatedTest
类提供的方式略有不同。 遗憾的是,发帖者只是描述了创建该类的动机,但没有提供源代码。 不过,有人提议联系该人以了解更多详细信息。使用简单的辅助函数
最直接(但自动化程度最低)的方法是创建一个辅助函数,该函数接受您想要传递给“真实”函数的参数,然后进行大量单独的测试案例。 每个测试用例都会使用不同的值调用您的辅助函数。
如果您选择上面列出的前两个选项中的任何一个,我很想听听您的经历。
It does not appear possible in CppUnit to parameterize a test case directly (see here and here). However, you do have a few options:
Use a
RepeatedTest
You may be able to make some clever use of the built-in
RepeatedTest
decorator. This allows a test case to be run multiple times (though without parameterization).I'll admit to never having used this myself, but perhaps you could have the
RepeatedTest
drive some gatekeeper function, which would (using a class static variable, perhaps?) pick a different input with every run. It would in turn call the true function you'd like to test with that value as input.Use a
TestCase
subclassOne person on CppUnit's SourceForge page claims to have written a subclass of
TestCase
that will run a particular test an arbitrary number of times, although in a slightly different manner than theRepeatedTest
class offers. Sadly, the poster simply described the motivation for creating the class, but did not provide the source code. There was, however, an offer to contact the individual for more details.Use a simple helper function
The most straight-forward (but least automated) way to do this is to create a helper function that takes the parameter you'd like to pass on to your "real" function, and then have lots of individual test cases. Each test case would call your helper function with a different value.
If you choose either of the first two options listed above, I'd be interested in hearing about your experience.
我不知道这是否符合 CppUnit 的“首选做事方式”,但这就是我现在正在采取的方法。
I don't know if that's considered kosher as per CppUnit's "preferred way of doing things" but that's the approach I'm taking now.
根据 Marcin 的建议,我实现了一些宏来帮助定义参数化 CppUnit 测试。
使用此解决方案,您只需在类的头文件中替换旧的宏 CPPUNIT_TEST_SUITE 和 CPPUNIT_TEST_SUITE_END:
在实现文件中,您需要将旧的 CPPUNIT_TEST_SUITE_REGISTRATION 宏替换为:
这些宏要求您实现以下方法:
详细说明可以在这里找到:http://brain-child.de/engineering/parameterizing -cppunit-tests
德语版本可以在这里找到:http://brain -child.de/engineering/parametrierbare-tests-cppunit
Upon of the suggestion of Marcin i've implemented some macros aiding to define parameterized CppUnit tests.
With this solution you just need to replace the old macros CPPUNIT_TEST_SUITE and CPPUNIT_TEST_SUITE_END within the class's header file:
In the implementation file you need to replace the old CPPUNIT_TEST_SUITE_REGISTRATION macro with:
These macros require you to implement the methods:
A detailed explanation can be found here: http://brain-child.de/engineering/parameterizing-cppunit-tests
The german version can be found here: http://brain-child.de/engineering/parametrierbare-tests-cppunit
我不是 C++ 程序员,但我可以帮助您了解单元测试概念:
测试用例旨在独立运行且不依赖于外部参数。 此外,您应该将测试用例的数量保持在最低限度,以覆盖大部分代码。 然而,在某些情况下(我已经处理过一些),一些测试看起来是相同的,仅在一些次要参数上有所不同。 最好的选择是编写一个fixture,它接受您正在讨论的参数,然后为每个参数提供一个测试用例,并用它调用该fixture。 一个通用的例子如下:
否则你就不会编写真正的测试用例,因为它们应该是可重现的,而无需执行它们的人太多知识。 我想有一些参数作为测试的输入都很重要。 那么为什么不在自己的测试用例中明确每一项呢? 这也是最好的记录方式,而不是编写单独的文档来指导程序员几年后阅读代码。
I'm not a C++ programmer but I can help with the unit-test concept:
Test-cases are meant to run isolated and with no dependency on external parameters. Additionally you should keep the number of test-cases down to the minimum which covers most of your code. There are cases, however (and I have already dealt with some), where some tests look the same, differing only by some minor parameters. The best bet then is to write a fixture which takes the parameter you're talking about, and then have one test-case for each of the parameters, calling the fixture with it. A generic example follows:
Otherwise you're not writing true test-cases, because they're supposed to be reproducible without much knowledge from the one who is executing them. I imagine there are a handful of parameters which are all important as input to the tests. Then why not make each one explicit inside its own test-case? That's also the best way to document then, instead of writing a separate document to guide the programmer which will read the code years later.
这是一个非常古老的问题,但我只需要做类似的事情并提出以下解决方案。 我对它不是 100% 满意,但它似乎很好地完成了这项工作
为测试方法定义一组输入参数。 例如,假设这些是字符串,那么让我们这样做:
实现一个通用测试器函数,每次调用都会从测试数组中获取下一个参数,例如:
在测试中 addTestToSuite() 方法声明(由 CPPUNIT 宏隐藏)而不是(或在旁边)使用 CPPUNIT_TEST 宏定义方法,添加与此类似的代码:
这样我们就可以注册 genericTester()多次,每个参数一次,并指定名称。 这似乎对我来说很有效。
希望这对某人有帮助。
This is a very old question, but I just needed to do something similar and came up with the following solution. I'm not 100% happy with it, but it seems to do the job quite well
Define a set of input parameters to a testing method. For example, let's say these are strings, so let's do:
Implement a generic tester function, which with each invocation will take the next parameter from the test array, e.g.:
In the test addTestToSuite() method declaration (hidden by the CPPUNIT macros) instead of (or next to) defining methods with the CPPUNIT_TEST macros, add code similar to this:
This way we register genericTester() multiple times, one for each parameter, with a name specified. This seems to work for me quite well.
Hope this helps someone.
根据consumerwhore的回答,我最终得到了一种非常好的方法,我可以使用单行注册宏和我想要的尽可能多的参数来创建多个测试。
只需定义一个参数类:
让您的测试装置将其用作“非类型模板参数”(我认为这就是它的名称):
使用一个小宏创建参数并注册一个新的测试装置:
最后,添加尽可能多的测试想要这样:
执行这个测试会给你:
Based on consumerwhore answer, I ended up with a very nice approach where I can create multiple tests using a one-line registration macro with as many parameters I want.
Just define a parameter class:
Make your test fixture use it as "non-type template parameter" (I think that's how it's called):
Have a small macro creating a parameter and registering a new test fixture:
Finally, add as many tests you want like that:
Executing this test will give you:
以下类/帮助器宏对适用于我当前的用例。 在您的 TestFixture 子类中,只需定义一个接受一个参数的方法,然后使用 PARAMETERISED_TEST(method_name, argument_type, argument_value) 添加测试。
The following class/helper macro pair works for my current use-cases. In your
TestFixture
subclass, just define a method which accepts one parameter and then add the test withPARAMETERISED_TEST(method_name, argument_type, argument_value)
.我也看过这个主题。
使用旧的代码库并添加额外的测试。
我的方法是之前描述的一些想法的混合。
目标之一是要编写的实际测试代码简单且易于阅读。
创建宏 TEST_METHOD_ARG(f, mark, ...)
请注意,mark 用于扩展 f 的基本测试函数名称。
创建一个基本测试f
基本测试接受多个参数,具体取决于测试详细信息。
使用宏 TEST_METHOD_ARG(f, mark, ...) 创建测试序列
这将导致许多测试均以基本测试名称开头
每个人都会使用其参数调用基本测试。
编译器:VS2015,应该可以与此后的任何 VS 版本一起使用。
I had a look at this subject too.
Working with an old code base and adding extra tests.
My approach is a mix of some of the ideas described before.
One of the goals is that the actual test code to write is simple and easy to read.
create a macro TEST_METHOD_ARG(f, mark, ...)
Note that mark is used to extend the base test function name of f.
Create a base test f
The base test accepts a number of arguments depending on test details.
Create a sequence of tests using marcro TEST_METHOD_ARG(f, mark, ...)
This will result in a number of tests all beginning with the base test name
each one will call the base test with the arguments for it.
Compiler: VS2015, should work with any VS version from this one on.