我认为Python 的 doctests的概念很棒,作为实时商店的 C++ 程序员,我非常嫉妒。我们基本上没有单元测试能力,这是一个严重的障碍。我见过 C++Unit 等,但是有什么东西可以从 Python 的 doctests 之类的注释中提取测试用例,而不是直接将它们放入代码中?
6 回答
我刚刚发布了doctest - 最轻量级的功能丰富的 C++ 单头测试框架。
它不是用于在注释中编写测试 - 而是用于直接在生产代码中编写测试。它不能完全满足您的需求,但它仍然是 C++ 中的最佳选择,无需预处理步骤
您可能会发现这很有用。在我自己的代码中需要它之后,我开始开发它。
http://github.com/panyam/DocTestPlusPlus
它是一个 Python 脚本,它会检查您的评论并提取测试并生成测试文件。
仍在开发和测试中。感谢任何和所有反馈。
干杯斯里
我刚刚看了一下doctest,它确实很棒。Python 语言的易用性方法也是如此。
但是,对于 C++,您可能找不到这样的工具。
如果其中一项测试失败,您可能需要调试发生的情况。从评论中生成测试用例的来源并不是那么容易。相反,在现有的 C++ 单元测试框架中,您拥有具有特殊语法的测试源,该语法经过编译且易于调试。此外,从评论中生成源代码将是另一个额外的(预)编译步骤,这只会让生活变得更加困难。
您应该接受 C++ 中的编码不像 Python 中那样快速,因此单元测试同样有些困难。另一方面,你有更多的工具,你可以为类型关系放置静态断言,例如,这在 Python 中是不可能的。
简而言之,我认为 C++ 的 Python doctest 的类似物与现有工具相比会有很多缺点,以至于没有人开始实施它。
如果您真的相信它可以比现有工具更好,请提供一些示例。我几乎不相信在现实生活中它可以更有用。
我正在考虑从评论中生成CxxTest文件。我没有使用过那个框架,但它看起来很有希望。从他们的手册中,单元测试文件看起来像这样:
// MyTestSuite.h
#include <cxxtest/TestSuite.h>
class MyTestSuite : public CxxTest::TestSuite
{
public:
void testAddition( void )
{
TS_ASSERT( 1 + 1 > 1 );
TS_ASSERT_EQUALS( 1 + 1, 2 );
}
};
我的建议是一个解析器,它可以从注释中提取那些 testX 函数的内容,而不必编写整个内容。例如(我只是在这里编写注释语法,可能有一种更简洁的方式来编写它):
// MyRegularCode.cpp
/// Description of the function here
/// Then test case below that gets extracted
/// and turned into CxxTest .h files
/**testAddition
MyClass mc;
mc.MyFunction();
TS_ASSERT( mc.m_value > 1 );
TS_ASSERT_EQUALS( mc.m_value, 3 );
**/
void MyClass::MyFunction()
{
m_value = 3;
};
我不确定 CxxTest 更强大的方面将如何实现,例如创建固定装置,但这样的事情可能会在 C++ 世界中提供 python 文档字符串和文档测试的共同性。
我知道将东西放入真实代码注释中的旧技巧(IIRC,这是编程实践的一部分)。但是,将单元测试简单地放在#ifdef
块中可能更容易。对于这类事情,您通常可以自行运行预处理器。
再说一次,我知道有一个项目使用 Perl 作为超级预处理器。
Fost附带的测试框架确实处理了一些非常相似的事情。测试不会嵌入到文档中,但它们可以与测试的代码并排放置。在结构上,测试看起来与 cxxtest 代码非常相似。
#include "myclass.hpp"
#include <fost/test>
FSL_TEST_SUITE( myclass );
/*
Your documentation
*/
FSL_TEST_FUNCTION( constructors ) {
fostlib::test::default_constructable< myclass >();
}
myclass::myclass() {
}
FSL_TEST_FUNCTION( some_method ) {
myclass instance;
FSL_CHECK_NOTHROW( instance.some_method(0) );
FSL_CHECK_EQ( instance.some_method(2), 2 );
FSL_CHECK_NEQ( instance.some_method(-2), 0 );
}
int myclass::some_method( int arg ) {
// implementation
}
所有这些都是用嵌入的测试编译的(你可以通过#define 从构建中删除它们——没有实现,但很容易做到)。然后通过一个单独的程序运行测试,该程序加载已构建的 .DLL 或 .so,找到测试并运行它们。
我们还没有尝试过,但它应该可以与静态库一起使用,并且可以在 Windows 上的 .EXE 文件中动态加载和运行测试,但我不太确定它是否可以在 Linux 或 Mac 上完成。