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

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

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

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

cxxtest单元测试框架源码分析(三):文本Listener实现_第1张图片 

在上图中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 

你可能感兴趣的:(listener)