MiniCppUnit分析

MiniCppUnit是一个轻量级的CppUnit,可以用来做C++代码的单元测试。

 

MiniCppUnit一种两个核心文件:MiniCppUnit.hxx和MiniCppUnit.cxx

 

在其压缩包内,还有一个TestRunner.cxx文件,这里面有一个简单的main函数,如果用户要测试的代码片段没有主函数,则可以使用此文件。

此文件就一行代码:

return TestFixtureFactory::theInstance().runTests() ? 0 : -1;

 

TestFixtureFactory本身是一个单例,它内部有一个TestFixture的Creator列表:

std::list<FixtureCreator> _creators;

 

FixtureCreator其实是一个函数指针类型,它指向的是一个个创建TestFixture的函数的地址

 

TestFixtureFactory的runTests()函数会遍历_creators中的每一个FixtureCreator函数指针,用它创建相应的TestFixture(返回的是其基类Test的指针类型),然后调用其runTest()接口。

 

TestFixture内部又有一个Test Case的列表:

typedef std::list<Test*> TestCases;

TestCases _testCases;

 

TestFixture的runTest()函数会遍历_testCases中的每一个Test Case,并调用每个Test Case的runTest()接口。在调用每个Test Case的runTest()接口前后,分别会调用TestFixture的setUp()和tearDown()函数,这两个是虚函数,可以重载。

 

基本的调用流程已经分析清楚了,现在有两个问题:

1)TestFixture的Creator是如何添加到TestFixtureFactory的_creators列表中的?

2)每一个Test Case是如何添加到TestFixture的_testCases列表中的?

 

要回答这两个问题,先看一下它给一个一个使用的例子UsageExample.cxx

 

#include "MiniCppUnit.hxx"

class MyTestsExample : public TestFixture<MyTestsExample>

{

public:

TEST_FIXTURE( MyTestsExample )

{

TEST_CASE( testAssert );

TEST_CASE( testAssertMessage );

TEST_CASE( testAdditionInts );

TEST_CASE( testDoubles );

TEST_CASE( testFloats );

TEST_CASE( testLongDoubles );

TEST_CASE( testNotANumber );

TEST_CASE( testComparisonWithEpsilon );

TEST_CASE( testException );

TEST_CASE( testStringAddition );

}

void testAssert()

{

ASSERT(3==1+2);

}

void testAssertMessage()

{

ASSERT_MESSAGE( 2==1+1, "2 should be 1 plus 1 ");

}

void testAdditionInts()

{

ASSERT_EQUALS( 2, 1+1 );

}

void testDoubles()

{

double expected = 10.00002;

double result =   10.00001;

ASSERT_EQUALS(expected, result);

 

// Notice that minicppunit uses an scaled epsilon

// that depends on the expected value.

// So, the previous assert passes but the following,

// if descomented, should fail!

double expected2 = 0.00002;

double result2 =   0.00001;

//ASSERT_EQUALS(expected2, result2); 

}

void testFloats()

{

float expected = 0.000002;

float result =   0.000001;

ASSERT_EQUALS(expected, result);

}

void testLongDoubles()

{

long double expected = 0.000002;

long double result =   0.000001;

ASSERT_EQUALS(expected, result);

}

void testNotANumber()

{

double expected = 0.0/0.0;

double result =   0.0/0.0;

ASSERT_EQUALS(expected, result);

}

void testComparisonWithEpsilon()

{

long double expected = 0.02;

long double result =   0.01;

ASSERT_EQUALS_EPSILON(expected, result, 0.05);

}

void testException()

{

try

{

someCodeThatShouldThrowException();

FAIL( "Should have rised an exception" );

} catch (std::exception & e)

{

// maybe assert for string in e.what()

}

}

void testStringAddition()

{

std::string result("Hello");

result += " World";

ASSERT_EQUALS("Hello World", result);

}

private:

void someCodeThatShouldThrowException()

{

throw std::exception();

}

};

 

REGISTER_FIXTURE( MyTestsExample );

/////////////////////////////////////////////////////////////////////////////////////////////////
先看最后的那句:
REGISTER_FIXTURE( MyTestsExample );
对应REGISTER_FIXTURE的定义,可知,展开后代码是这样的:
Test* CreadorMyTestsExample(){return new MyTestsExample;}
class RegistradorMyTestsExample
public: 
RegistradorMyTestsExample() 
{
TestFixtureFactory::theInstance().addFixtureCreator(CreadorMyTestsExample);/
}
}; 
static RegistradorMyTestsExample estaticMyTestsExample ;

 

由此可见,在静态变量estaticMyTestsExample构造时,会将CreadorMyTestsExample加入到TestFixtureFactory的creator列表中。这就回答了第一个问题。

 

第二个问题就更简单了,将下列代码完成了Test Case的注册工作:

TEST_CASE( testAssert );

TEST_CASE( testAssertMessage );

TEST_CASE( testAdditionInts );

TEST_CASE( testDoubles );

TEST_CASE( testFloats );

TEST_CASE( testLongDoubles );

TEST_CASE( testNotANumber );

TEST_CASE( testComparisonWithEpsilon );

TEST_CASE( testException );

TEST_CASE( testStringAddition );

 

 

你可能感兴趣的:(MiniCppUnit分析)