9^5T'tm MT0 18、每次测一个功能
0b8dp7LC&P a4@s:Rl051Testing软件测试网bFS*T'`z 在测试模式下,很容易去尝试对每个测试中的每件事都断言。这必须避免因为它使得维护更难。仅测试该测试方法的名字表明的功能。51Testing软件测试网Qvi*LV-LhwHr;a
V#WLQE7cFo4d3oI0 对于一般代码应该将测试代码尽可能少作为一个目标。
t9k6GX&zHr
M"y051Testing软件测试网PXB
d\
Es
I 19、使用显式断言51Testing软件测试网:W:|uI-S!]{
GW!ZO HD2Y,`AY0 在assertEquals(a, b)和assertTrue(a == b) (之类的)之间优先选择前者,因为它可以在测试失败的时候给出关于失败原因的更多有用的信息。 这对于上述提到的随机参数组合时输入值无法预先知道的情况尤为重要。51Testing软件测试网3g
T)T?;y
5GtP A9_;w0 20、提供负面测试51Testing软件测试网|3y-Kq7|J M
51Testing软件测试网Fr?3i%F5z 负面测试是通过故意用错代码以验证稳健性和适当的错误处理。51Testing软件测试网v6O,Gu
A.Im
51Testing软件测试网?0\;wQ|#I|Y 考虑下面这个如果传入负数就会抛出异常的方法:
@e
l}y QR#SA051Testing软件测试网"nW3HpNdRz{LvC5R"C#?0void setLength(double length) throws IllegalArgumentException; |
vM Xp uHJ,[Q4J0 可以这样来测试该特殊情况的正确行为:
o#K1j7O {4onwH051Testing软件测试网Z1z Yfm;x|z[ghV@Dz;b0try51Testing软件测试网sfV0Z!v-v%z \w1{ { fKy'Wx[?#o+I0 setLength(-1.0);51Testing软件测试网;jS,va/[/K fail(); // If we get here, something went wrong "pSi+_j"ZsY0} @/d0]~;wq8XVj?u0catch (IllegalArgumentException exception) 0i@~0LmY2x5p/a0{ q:Bp}1i1[
`4]0 // If we get here, all is fine51Testing软件测试网5j@x-s0]j:j-U}Q } |
51Testing软件测试网DuIU8S4X{Jv 21、设计代码是考虑测试
.@['y%x[%M8S fn S1G0ZYW3}2]r9b0 编写和维护单体测试的代价很高,使公开API最小化并降低代码的循环复杂度是降低成本并使得高覆盖率的测试代码更快编写和更易于维护的方式。
7phFy0c051Testing软件测试网jX$PR1HFbM 一些建议:51Testing软件测试网Ct2@
L'{g(]|9j
F(Xsm.G}4o._0 ● 通过构造时候确定状态来使得成员类不可变。这会减少对setter方法的需求。
$mE6jI0~_0@a%l5b?
X-I z)N/t$r0 ● 限制过渡使用继承和虚的公开方法。51Testing软件测试网ba;d:Nhb6nZ
51Testing软件测试网0u_s*OH6Ul ● 减少利用了友元类(C++)或包范围(Java)的公开API。
[)k8L/j'ysv_O051Testing软件测试网 N-s,v~~ ● 避免不必要的分支。
t'ThS!K'`051Testing软件测试网Ct,jK_|F ● 在分支内的代码尽可能少。51Testing软件测试网9Ev)Wa.Y`#G;?d+v
51Testing软件测试网e#?*a
\pS,i{%pi$h ● 尽可能使用异常和断言来验证分别在公开和私有API中的参数。51Testing软件测试网%pK|$V-eEX
51Testing软件测试网
y t7Ij1~[VN0? ● 限制使用帮助方法。从一个黑盒测试的角度每个方法都必须一样地测试。考虑如下这个小例子:51Testing软件测试网H*A,k|)V!~P
51Testing软件测试网*Z._4RN~.}3u:h`:L(B-G;KW6W P\0public void scale(double x0,double y0,double scaleFactor)51Testing软件测试网:k P3N%?IeE*hFXK {51Testing软件测试网/t gj(W8Z3`E // scaling logic u,S`"w5C,hx0}51Testing软件测试网 o+d6g OP;},@gMO 51Testing软件测试网Vm j)_[*Jf1{ public void scale(double x0, double y0)51Testing软件测试网H3\#U+B7J] T(lVC 51Testing软件测试网z8\|BQ5Y4xaM/O scale(x0, y0, 1.0);51Testing软件测试网Dr3z"N"U"\bU+[u6a:O } |
/S~i3l5c^&q"sUs"I0 省去后面的就可以简化测试,但代价是客户端代码会有额外的工作。51Testing软件测试网m:U;x5?-W@
51Testing软件测试网f z5Gp*EI~ 22、不要关联到预定义的外部资源51Testing软件测试网 BTO#_Z)a
51Testing软件测试网+UjW{8Vz!^4q
])U 编写测试文件的时候应该不能利用将要执行环境的上下文信息以使得他们可以在任何时间任何地方运行。为了给测试提供所需的资源,这些资源应该通过测试自身提供。
%mbLd6Q1x2qvDn0U2jC#P|ku/|0 现在考虑解析某种类型文件的类的情况。应该将文件的内容放在测试内,在测试开始前将其写入一个临时文件并在测试完成后删除掉文件,而不是从预定义的路径选择一个示例文件。51Testing软件测试网\6Q3l)`.A
W;b,Oo:VS~0 23、了解测试成本51Testing软件测试网-pI%NF O;C
51Testing软件测试网 ^,R6{^-]g$x2S 不写单体测试代价很高,写单体测试代价也很高。这是两者之间的平衡,从执行覆盖率考虑一般的行业标准是大约是80%。
]2B3] GFD%eM00sF ANH4{%y7po0 通常比较困难达到完全覆盖的区域是处理外部资源的错误或异常。在一个交易中模拟数据库崩溃是完全有可能的,但较之作为替代方法的深度代码检查通常代价过高。51Testing软件测试网h|0VY.Yy#}!t
51Testing软件测试网
g
T_c#~T-^
W+M 24、测试优先级排序51Testing软件测试网p? A0hz"]DU
-[n+UCs@+h"Y0 单体测试通常是一个至底而上的流程,如果没有测试系统所有部分所需的足够资源就应该优先考虑最底层。51Testing软件测试网V#[K'kU HX/H
51Testing软件测试网(a-^'a8}Hr 25、考虑到测试代码失败
&|0zAz/[Ch&T m:A:mQ04D$^-Yj@&~0 考虑下这个简单的实例:
R(^z&lwJ051Testing软件测试网!T;Q
vC a5K{n~ep51Testing软件测试网 dDqrEzeg9pE
51Testing软件测试网$ukvu2h Handle handle = manager.getHandle(); 7PA&V,a M0assertNotNull(handle);51Testing软件测试网\U;SgRvtL 51Testing软件测试网)W^:qaY$}'G(zQ8~String handleName = handle.getName();51Testing软件测试网GB_Lh assertEquals(handleName, "handle-01");51Testing软件测试网't*d1Tej fP |
Y\E5Q{"Ucp4U0 如果第一个断言是假的,接下来的语句就会崩溃,余下的测试也就不会被执行了。所以应该考虑单个测试代码失效不会使得这个测试套件无法执行。通常可以改写成这样:51Testing软件测试网,Z gR+Esj|.wc:z ~
bXZR2E!hd051Testing软件测试网8p9UX6}y_ L BM/yXD!f
51Testing软件测试网M4rpUh3m[h Handle handle = manager.getHandle(); :w Bh}v*W]v2I e;p0assertNotNull(handle);51Testing软件测试网Y,eilGT&N*U
W"wIE if (handle == null) return;51Testing软件测试网5z7E~nehW1x4I 51Testing软件测试网8f LS6p-Z%]]GgoString handleName = handle.getName(); 0VTZ
F"uZ2h XO0assertEquals(handleName, "handle-01");51Testing软件测试网hdh Ev2wqqJ|+e,o |
51Testing软件测试网}.x?K(T2M8rE 26、编写测试来重现缺陷51Testing软件测试网"T2r_dZ8sd:F(E
51Testing软件测试网xRi
`6d6E7YL 如果报告了一个缺陷,就应该写一个测试来重现该缺陷(比如一个失败的测试)并使用该测试作为是否成功修复代码的标准。51Testing软件测试网}|%J?Y!ZE"B W
d5u
zD/E
}0 27、认识局限性
+G9{D'Q/tOt6nDC
g051Testing软件测试网{(@b.Yu [ 单体测试永远不能证明代码的正确性!51Testing软件测试网4f,cL}aB
3^^w5S ^*F2A;{0 一个失败的测试意味着代码含有错误,而一个成功的测试不能证明任何东西。51Testing软件测试网es m;G!F3Tf!t0R(x_
m OFP7YhRL4VQP }0 单体测试的最普遍的应用就是验证和记录底层的需求以及回归测试:验证代码在变迁和重构的过程中一直保持稳定。51Testing软件测试网p
}yz PZw%w
R lD
51Testing软件测试网:iu'Y4I-KX
t,M"L 因此,单体测试永远无法替代前期设计和健全的开发流程。单体测试可以作为既有开发方法的一个宝贵补充。51Testing软件测试网 PG,o2q}4W#\w
2CkG`lMp0 后记:51Testing软件测试网Pf3Z:^wC~
u
51Testing软件测试网.Gl
\+Z)q 对于第9点”测试类和被测试类尽量近”和第14点”微不足道的类也要测试”,我不是很赞同,实践的时候也没有完全遵守。但为了忠实于原文没有做
擅自修改。大家在学习和实践的时候可能也会接触一些相悖的观点和理论,不要担心,选择最适合你尝试下就知道了。同时,欢迎说出你的故事!
B([%o0eLW0