OK (1 tests)
这说明我们一共进行了1个测试,并且都通过了。如果我们人为地把"return mFileName;"改成"return mFileName + 'a';"以制造一个错误,那么测试的结果就会变成:
!!!FAILURES!!!
Test Results:
Run: 1 Failures: 1 Errors: 0
1) test: (F) line: 31 c:unittestunittest.cpp
equality assertion failed
- Expected: a.data
- Actual : a.dat
这个结果告诉我们我们的实现出现了问题。前面说到, CPPUNIT_ASSERT_EQUAL在两个参数不等时会抛出异常,可是这里为什么没有异常退出了?这是因为,我们执行每一个TestCase的 run的时候,它使用了一种特殊的机制把函数包起来,任何异常都会被捕获。具体细节请参考我的CppUnit代码简介一文。
如果我们把#include "CppUnit/TextOutputter.h"替换成#include "CppUnit/CompilerOutputter.h",并且把TextOutputter替换成CompilerOutputter,输出就变成:
c:unittestunittest.cpp(32) : error : Assertion
Test name:
equality assertion failed
- Expected: a.data
- Actual : a.dat
Failures !!!
Run: 1 Failure total: 1 Failures: 1 Errors: 0
这个输出,在编译器的信息窗口里面,可以通过双击文件名加行号的那一行来到达相应的位置。
V. 迭代开发
上面的例子中我们先针对需求的一部分写了测试用例,然后就实现了相应的功能。我们可以在这些功能被测试后,继续实现别的功能的测试用例,然后继续实现相应的功能,这是一个迭代的过程,我们不断地增加测试用例和实现代码,最后达成需求。还有一种方法是,先写好所有的测试用例(这个时候通常会编译不通过),然后再添加能够让编译通过所需要的实现(这个时候通常运行测试会有很多错误),接着通过正确实现使得没有任何测试错误,最后,对代码作优化和更新,并且不断的保证测试通过。在这里我们着重介绍第二种方法。首先我们先写下所有的测试用例,在这里,由于有很多测试用例,我们不再使用TestCase,因为TestCase通常用在单一测试任务的情况下。这次我们从 TestFixture派生我们的测试类:
class MyTestCase:public CPPUNIT_NS::TestFixture
{
public:
void testCtorAndGetName()
{
const std::string fileName( "a.dat" );
FileStatus status( fileName );
CPPUNIT_ASSERT_EQUAL( status.getFileName(), fileName );
}
void testGetFileSize()
{
const std::string fileName( "a.dat" );
FileStatus status( fileName );
CPPUNIT_ASSERT_EQUAL( status.getFileSize(), 0 );//?
}
};
文章来源于领测软件测试网 https://www.ltesting.net/