本文主要分析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
*
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