本文主要分析CxxTest的文本执行跟踪的实现,其他的打印跟踪还包括图形、XML、只简单返回YesNo跟踪。
在CxxTest中,所有接受测试执行过程都继承CxxTest:TestListener类,主要用于输出测试结果。这里的输出包括xml文件输出、在图形界面上输出以及以文本的形式输出。
本文主要分析文本形式的输出测试过程信息,首先我们看看相关类的关系。
在上图中1描述了文本Listener的继承关系,2描述了图形Listener的继承关系,3是一种即向文本Listener又向图形Listener发送执行过程信息(在CxxTest自带的例子中就是使用的该Listern)。
首先:我们来看下CxxTest:TestListener的代码定义
1 namespace CxxTest
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类的实现
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 * p = ( 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