cxxtest单元测试框架源码分析(三):文本Listener实现

    本文主要分析CxxTest的文本执行跟踪的实现,其他的打印跟踪还包括图形、XML、只简单返回YesNo跟踪。

    在CxxTest中,所有接受测试执行过程都继承CxxTest:TestListener类,主要用于输出测试结果。这里的输出包括xml文件输出、在图形界面上输出以及以文本的形式输出。

    本文主要分析文本形式的输出测试过程信息,首先我们看看相关类的关系。

 

在上图中1描述了文本Listener的继承关系,2描述了图形Listener的继承关系,3是一种即向文本Listener又向图形Listener发送执行过程信息(在CxxTest自带的例子中就是使用的该Listern)。

首先:我们来看下CxxTest:TestListener的代码定义

  1 namespace CxxTest

 2 {   
 3     class TestListener //定义为抽象类,除了构造函数外,其他都定义为虚函数
 4     {
 5     public:
 6         TestListener() {}
 7         virtual ~TestListener() {}
 8 
 9         //改函数用于解析命令行传入的执行控制参数
10         virtual void process_commandline(int& /*argc*/char** /*argv*/) {}
11         
12         //下面的三个函数分别对应的进入三个层级的执行控制,一个是全局的(对所有的测试套有效),一个是测试套,一个是测试用例
13         virtual void enterWorld( const WorldDescription & /*desc*/ ) {}
14         virtual void enterSuite( const SuiteDescription & /*desc*/ ) {}
15         virtual void enterTest( const TestDescription & /*desc*/ ) {}
16 
17         //下面的这些函数分别对应CxxTest对外提供的功能实现,如:TS_TRACE、TS_WARN等
18         virtual void trace( const char * /*file*/, unsigned /*line*/,
19                             const char * /*expression*/ ) {}
20         virtual void warning( const char * /*file*/, unsigned /*line*/,
21                               const char * /*expression*/ ) {}
22         virtual void failedTest( const char * /*file*/, unsigned /*line*/,
23                                  const char * /*expression*/ ) {}
24         virtual void failedAssert( const char * /*file*/, unsigned /*line*/,
25                                    const char * /*expression*/ ) {}
26         virtual void failedAssertEquals( const char * /*file*/, unsigned /*line*/,
27                                          const char * /*xStr*/const char * /*yStr*/,
28                                          const char * /*x*/const char * /*y*/ ) {}
29         virtual void failedAssertSameData( const char * /*file*/, unsigned /*line*/,
30                                            const char * /*xStr*/const char * /*yStr*/,
31                                            const char * /*sizeStr*/const void * /*x*/,
32                                            const void * /*y*/, unsigned /*size*/ ) {}
33         virtual void failedAssertDelta( const char * /*file*/, unsigned /*line*/,
34                                         const char * /*xStr*/const char * /*yStr*/,
35                                         const char * /*dStr*/const char * /*x*/,
36                                         const char * /*y*/const char * /*d*/ ) {}
37         virtual void failedAssertDiffers( const char * /*file*/, unsigned /*line*/,
38                                           const char * /*xStr*/const char * /*yStr*/,
39                                           const char * /*value*/ ) {}
40         virtual void failedAssertLessThan( const char * /*file*/, unsigned /*line*/,
41                                            const char * /*xStr*/const char * /*yStr*/,
42                                            const char * /*x*/const char * /*y*/ ) {}
43         virtual void failedAssertLessThanEquals( const char * /*file*/, unsigned /*line*/,
44                                                  const char * /*xStr*/const char * /*yStr*/,
45                                                  const char * /*x*/const char * /*y*/ ) {}
46         virtual void failedAssertPredicate( const char * /*file*/, unsigned /*line*/,
47                                             const char * /*predicate*/const char * /*xStr*/const char * /*x*/ ) {}
48         virtual void failedAssertRelation( const char * /*file*/, unsigned /*line*/,
49                                            const char * /*relation*/const char * /*xStr*/const char * /*yStr*/,
50                                            const char * /*x*/const char * /*y*/ ) {}
51         virtual void failedAssertThrows( const char * /*file*/, unsigned /*line*/,
52                                          const char * /*expression*/const char * /*type*/,
53                                          bool /*otherThrown*/ ) {}
54         virtual void failedAssertThrowsNot( const char * /*file*/, unsigned /*line*/,
55                                             const char * /*expression*/ ) {}
56     virtual void failedAssertSameFiles( const char* , unsigned , const char* , const char*const char* ) {}
57 
58      //下面的三个函数分别对应的离开三个层级的执行控制,和上面的enterXXX对应
59         virtual void leaveTest( const TestDescription & /*desc*/ ) {}
60         virtual void leaveSuite( const SuiteDescription & /*desc*/ ) {}
61         virtual void leaveWorld( const WorldDescription & /*desc*/ ) {}
62     };
63 }

其次:文本Listener有两个,分别为CxxTest:ParenPrinter和CxxTest:StdioPrinter。两者的区别在于前者打印编译器期望的行号(如:MSVC),后者是如果运行失败将打印类似编译失败那样的错误报告,后者使用了<stdio.h>,可以支持向文本文件里输出执行报告,默认是向stdout输出。 

        对于类CxxTest:ErrorPrinter和CxxTest:StdioFilePrinter的主要区别在于前者是使用std::cout输出,而后者使用fprintf/fputs等输出。由于CxxTest不依赖任何外部的类包括基础的输入输出类,所以它定义了一个OutPutStream类,在这两个类中都重载了输出操作符<<。由于这两部分都相对比较简单,所以这里都不详细分析代码了。

最后:我们来看下ErrorFormatter类的实现

  1 namespace CxxTest
  2 {
  3     //首先定义了一个输出流类,因为上面提到了CxxTest不依赖于外部所有的类,包括基本类,如iostreams
  4     class OutputStream
  5     {
  6     public:
  7         //下面的定义都是输出操作,包括结束符、数字、字符串的输出;这些虚函数在CxxTest::ErrorPrinter和CxxTest::StdioFilePrinter中都有实现
  8         virtual ~OutputStream() {}
  9         virtual void flush() {};
 10         virtual OutputStream &operator<<( unsigned /*number*/ ) { return *this; }
 11         virtual OutputStream &operator<<const char * /*string*/ ) { return *this; }
 12 
 13         typedef void (*Manipulator)( OutputStream & );
 14         
 15         virtual OutputStream &operator<<( Manipulator m ) { m( *this ); return *this; }
 16         static void endl( OutputStream &o ) { (o << "\n").flush(); }
 17     };
 18 
 19     class ErrorFormatter : public TestListener
 20     {
 21     public:
 22         ErrorFormatter( OutputStream *o, const char *preLine = ":"const char *postLine = "" ) :
 23             _dotting( true ),
 24             _reported( false ),
 25             _o(o),
 26             _preLine(preLine),
 27             _postLine(postLine)
 28         {
 29         }
 30         //该函数调用CxxTest:TestRunner类的runAllTests静态方法运行所有的测试用例
 31         int run()
 32         {
 33             TestRunner::runAllTests( *this );
 34             return tracker().failedTests();
 35         }
 36 
 37         //下面的函数都是在CxxTest:TestListener中定义的虚函数实现,除了进入和退出不同层级的输出外其他都是对外宏功能的具体执行输出
 38         void enterWorld( const WorldDescription & /*desc*/ )
 39         {
 40             (*_o) << "Running " << totalTests;
 41             _o->flush();  //用于在执行所有用例之前打印总的用例个数
 42             _dotting = true;
 43             _reported = false;
 44         }
 45 
 46         static void totalTests( OutputStream &o )
 47         {
 48             char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
 49             const WorldDescription &wd = tracker().world();
 50             o << wd.strTotalTests( s ) << (wd.numTotalTests() == 1 ? " test" : " tests");
 51         }
 52 
 53         void enterSuite( const SuiteDescription & )
 54         {
 55             _reported = false;
 56         }
 57 
 58         void enterTest( const TestDescription & )
 59         {
 60             _reported = false;
 61         }
 62 
 63         void leaveTest( const TestDescription & )
 64         {
 65             if ( !tracker().testFailed() ) {
 66                 ((*_o) << ".").flush();
 67                 _dotting = true;
 68             }
 69         }
 70 
 71         //改函数用于在执行完所有的用例后打印执行结果汇总:多少个Fail用例以及成功率
 72         void leaveWorld( const WorldDescription &desc )
 73         {
 74             if ( !tracker().failedTests() ) {
 75                 (*_o) << "OK!" << endl;
 76                 return;
 77             }
 78             newLine();
 79             (*_o) << "Failed " << tracker().failedTests() << " of " << totalTests << endl;
 80             unsigned numPassed = desc.numTotalTests() - tracker().failedTests();
 81             (*_o) << "Success rate: " << (numPassed * 100 / desc.numTotalTests()) << "%" << endl;
 82         }
 83 
 84         void trace( const char *file, unsigned line, const char *expression )
 85         {
 86             stop( file, line ) << "Trace: " <<
 87                 expression << endl;
 88         }
 89 
 90         void warning( const char *file, unsigned line, const char *expression )
 91         {
 92             stop( file, line ) << "Warning: " <<
 93                 expression << endl;
 94         }
 95 
 96         void failedTest( const char *file, unsigned line, const char *expression )
 97         {
 98             stop( file, line ) << "Error: Test failed: " <<
 99                 expression << endl;
100         }
101 
102         void failedAssert( const char *file, unsigned line, const char *expression )
103         {
104             stop( file, line ) << "Error: Assertion failed: " <<
105                 expression << endl;
106         }
107 
108         void failedAssertEquals( const char *file, unsigned line,
109                                  const char *xStr, const char *yStr,
110                                  const char *x, const char *y )
111         {
112             stop( file, line ) << "Error: Expected (" <<
113                 xStr << " == " << yStr << "), found (" <<
114                 x << " != " << y << ")" << endl;
115         }
116 
117         void failedAssertSameData( const char *file, unsigned line,
118                                    const char *xStr, const char *yStr,
119                                    const char *sizeStr, const void *x,
120                                    const void *y, unsigned size )
121         {
122             stop( file, line ) << "Error: Expected " << sizeStr << " (" << size << ") bytes to be equal at (" <<
123                 xStr << ") and (" << yStr << "), found:" << endl;
124             dump( x, size );
125             (*_o) << "     differs from" << endl;
126             dump( y, size );
127         }
128 
129         void failedAssertSameFiles( const char* file, unsigned line,
130                                    const char*const char*,
131                                    const char* explanation
132                                    )
133         {
134             stop( file, line ) << "Error: " << explanation << endl;
135         }
136 
137         void failedAssertDelta( const char *file, unsigned line,
138                                 const char *xStr, const char *yStr, const char *dStr,
139                                 const char *x, const char *y, const char *d )
140         {
141             stop( file, line ) << "Error: Expected (" <<
142                 xStr << " == " << yStr << ") up to " << dStr << " (" << d << "), found (" <<
143                 x << " != " << y << ")" << endl;
144         }
145 
146         void failedAssertDiffers( const char *file, unsigned line,
147                                   const char *xStr, const char *yStr,
148                                   const char *value )
149         {
150             stop( file, line ) << "Error: Expected (" <<
151                 xStr << " != " << yStr << "), found (" <<
152                 value << ")" << endl;
153         }
154 
155         void failedAssertLessThan( const char *file, unsigned line,
156                                    const char *xStr, const char *yStr,
157                                    const char *x, const char *y )
158         {
159             stop( file, line ) << "Error: Expected (" <<
160                 xStr << " < " << yStr << "), found (" <<
161                 x << " >= " << y << ")" << endl;
162         }
163 
164         void failedAssertLessThanEquals( const char *file, unsigned line,
165                                          const char *xStr, const char *yStr,
166                                          const char *x, const char *y )
167         {
168             stop( file, line ) << "Error: Expected (" <<
169                 xStr << " <= " << yStr << "), found (" <<
170                 x << " > " << y << ")" << endl;
171         }
172 
173         void failedAssertRelation( const char *file, unsigned line,
174                                    const char *relation, const char *xStr, const char *yStr,
175                                    const char *x, const char *y )
176         {
177             stop( file, line ) << "Error: Expected " << relation << "" <<
178                 xStr << "" << yStr << " ), found !" << relation << "" << x << "" << y << " )" << endl;
179         }
180 
181         void failedAssertPredicate( const char *file, unsigned line,
182                                     const char *predicate, const char *xStr, const char *x )
183         {
184             stop( file, line ) << "Error: Expected " << predicate << "" <<
185                 xStr << " ), found !" << predicate << "" << x << " )" << endl;
186         }
187 
188         void failedAssertThrows( const char *file, unsigned line,
189                                  const char *expression, const char *type,
190                                  bool otherThrown )
191         {
192             stop( file, line ) << "Error: Expected (" << expression << ") to throw (" <<
193                 type << ") but it " << (otherThrown ? "threw something else" : "didn't throw"<<
194                 endl;
195         }
196 
197         void failedAssertThrowsNot( const char *file, unsigned line, const char *expression )
198         {
199             stop( file, line ) << "Error: Expected (" << expression << ") not to throw, but it did" <<
200                 endl;
201         }
202 
203     protected:
204         //返回 CxxTest::ErrorFormatter中的私有输出类
205         OutputStream *outputStream() const
206         {
207             return _o;
208         }
209 
210     private:
211         ErrorFormatter( const ErrorFormatter & );
212         ErrorFormatter &operator=const ErrorFormatter & );
213         
214          //下面的这几个函数都是控制执行信息的输出,包括换行、控制输出Dump的执行信息等等
215         OutputStream &stop( const char *file, unsigned line )
216         {
217             newLine();
218             reportTest();
219             return (*_o) << file << _preLine << line << _postLine << "";
220         }
221 
222         void newLine( void )
223         {
224             if ( _dotting ) {
225                 (*_o) << endl;
226                 _dotting = false;
227             }
228         }
229 
230         //用于打印在每个用例执行前的输出在那个测试套以及运行那个测试用例
231         void reportTest( void )
232         {
233             if( _reported )
234                 return;
235             (*_o) << "In " << tracker().suite().suiteName() << "::" << tracker().test().testName() << ":" << endl;
236             _reported = true;
237         }
238 
239         void dump( const void *buffer, unsigned size )
240         {
241             if ( !buffer )
242                 dumpNull();
243             else
244                 dumpBuffer( buffer, size );
245         }
246 
247         void dumpNull()
248         {
249             (*_o) << "   (null)" << endl;
250         }
251         
252         void dumpBuffer( const void *buffer, unsigned size )
253         {
254             unsigned dumpSize = size;
255             if ( maxDumpSize() && dumpSize > maxDumpSize() )
256                 dumpSize = maxDumpSize();
257 
258             const unsigned char *= (const unsigned char *)buffer;
259             (*_o) << "   { ";
260             for ( unsigned i = 0; i < dumpSize; ++ i )
261                 (*_o) << byteToHex( *p++ ) << " ";
262             if ( dumpSize < size )
263                 (*_o) << " ";
264             (*_o) << "}" << endl;
265         }
266 
267         static void endl( OutputStream &o )
268         {
269             OutputStream::endl( o );
270         }
271 
272         bool _dotting;
273         bool _reported;  //记录在该用例中是否已经打印了测试套以及测试用例信息
274         OutputStream *_o;
275         const char *_preLine;
276         const char *_postLine;
277     };

278  

版权说明

转载改文章请指明出处http://www.cnblogs.com/xiaocheng,多谢!

Author: Elvis.Chen 

posted @ 2009-06-18 22:14  Elvis.Chen  阅读(1803)  评论(2编辑  收藏  举报