这三个表达式也是同一个逻辑:
判断一个数的范围是否在(0,200)区间内,也应该把这个逻辑提取到一个函数中,去掉重复的逻辑,提高代码的可重用性。
可重用性的好处:
比如,现在用户的需求改为了三条边的取值范围要改为[100,400],那么,按前面的思路来说,需要改3个地方,而现在只需要在一个函数里改1个地方,这就是代码重用的好处。
3、条件7:
a==b;条件8:
a==c;条件9:
b==c
这三个表达式的逻辑:
判断两个数是否相等。
也应该把它提取到一个函数中。
我们进一步来分析一下判断是否是等边三角形或等腰三角形的条件:
(1)前面程序的判断是从最直观的方式(a==b&&b==c&&a==c)(实际上只需要两个表达式成立即可)三条边都相等来判定是等边三角形;(a==b||b==c||a==c)只有两条边相等来判定是等腰三角形。
(2)转变一下思路:
给定三个整数,然后用一个函数来判断这三个整数有几个相等,返回相等的个数,如果返回值等于3,那么它是等边三角形,如果返回值是2,那么它是等腰三角形,否则,它是一般三角形(如果不是直角三角形的话)。
4、条件10:
a2+b2==c2条件11:
a2+c2==b2条件12:
c2+b2==a2
这三个条件的处理方式有两种:
(1)跟前面三组分析一样,把相同的逻辑提取到一个函数中,然后三次调用。
(2)根据直角三角形的特点:
斜边是最长的,所以我们可以事先写一个函数来找到最长的边,然后把它赋值给c,这样处理之后,只需要一次调用判定(a2+b2==c2)的函数了。
4.白盒测试实例之四——程序设计
程序设计对于软件的质量和软件实施过程的难易程度起着至关重要的作用。
好的设计,即使聘用没什么经验的开发人员都很容易产生出高质量的代码出来;而差的设计,即使是经验很丰富的开发人员也很容易产生缺陷,特别是可重用性、可测试性、可维护性、可扩展性等方面的缺陷。
经过以上的分析,下面来看一下如何设计。
在下图中,每个方框都使用一个函数来实现,为了跟用户界面分开,最顶上的函数不要写在main函数中。
把思路用流程图的方式表达出来,不用停留在脑袋里:
具体的函数的调用关系图:
复杂模块triangleType的流程图:
5.白盒测试实例之五——编码
1、Triangle.h
1./*
2.*Copyright(c)2008,胡添发(hutianfa@)
3.*
4.*三角形类型判断
5.*
6.*/
7.
8.#include
9.#include
10.
11./*
12.*判断一个整数是否在(0,200)区间内
13.*返回值:
true-否;false-是
14.*/
15.boolisOutOfRange(inti);
16.
17./*
18.*判断三条边是否合法(即:
判断三条边都在合法的范围内)
19.*返回值:
true-是;false-否
20.*/
21.boolisLegal(inta,intb,intc);
22.
23./*
24.*判断两条边之和是否大于第三边
25.*返回值:
true-是;false-否
26.*/
27.boolisSumBiger(inta,intb,intc);
28.
29./*
30.*判断三条边是否能够组成三角形
31.*返回值:
true-是;false-否
32.*/
33.boolisTriangle(inta,intb,intc);
34.
35./*
36.*判断两条边是否相等
37.*返回值:
true-是;false-否
38.*/
39.boolisEquals(inta,intb);
40.
41./*
42.*求三角形有几条边相等
43.*返回值:
相等边的数量
44.*/
45.inthowManyEquals(inta,intb,intc);
46.
47./*
48.*判断是否满足两边平方之和是否等于第三边的平方
49.*
50.*/
51.boolisPowerSumEquals(inta,intb,intc);
52.
53./*
54.*判断第一个数是否比第二个数大
55.*/
56.boolisGreaterThan(inta,intb);
57.
58./*
59.*判断是否是直角三角形
60.*
61.*/
62.boolisRightRriangle(inta,intb,intc);
63.
64./*
65.*判断三角形的类型,返回值:
66.*1、不能组成三角形
67.*2、等边三角形
68.*3、等腰三角形
69.*4、直角三角形
70.*5、一般三角形
71.*6、某些边不满足限制
72.*/
73.inttriangleType(inta,intb,intc);
2、Triangle.cpp
1./*
2.*Copyright(c)2008,胡添发(hutianfa@)
3.*
4.*三角形类型判断
5.*
6.*/
7.
8.#include
9.#include
10.
11./*
12.*判断一个整数是否在(0,200)区间内
13.*返回值:
true-否;false-是
14.*/
15.boolisOutOfRange(inti)
16.{
17.if(0
18.{
19.returnfalse;
20.}
21.else
22.{
23.returntrue;
24.}
25.};
26.
27./*
28.*判断三条边是否合法(即:
判断三条边都在合法的范围内)
29.*返回值:
true-是;false-否
30.*/
31.boolisLegal(inta,intb,intc)
32.{
33.if(isOutOfRange(a)||isOutOfRange(b)||isOutOfRange(c))
34.{
35.returnfalse;
36.}
37.returntrue;
38.}
39.
40./*
41.*判断两条边之和是否大于第三边
42.*返回值:
true-是;false-否
43.*/
44.boolisSumBiger(inta,intb,intc)
45.{
46.if(a+b>c)
47.{
48.returntrue;
49.}
50.returnfalse;
51.}
52.
53./*
54.*判断三条边是否能够组成三角形
55.*返回值:
true-是;false-否
56.*/
57.boolisTriangle(inta,intb,intc)
58.{
59.if(isSumBiger(a,b,c)&&isSumBiger(a,c,b)&&isSumBiger(b,c,a))
60.{
61.returntrue;
62.}
63.returnfalse;
64.}
65.
66./*
67.*判断两条边是否相等
68.*返回值:
true-是;false-否
69.*/
70.boolisEquals(inta,intb)
71.{
72.if(a==b)
73.{
74.returntrue;
75.}
76.returnfalse;
77.}
78.
79./*
80.*求三角形有几条边相等
81.*返回值:
相等边的数量
82.*1:
没有边相等2:
只有两条边相等3:
三条边相等
83.*
84.*/
85.inthowManyEquals(inta,intb,intc)
86.{
87.intcount=1;
88.if(isEquals(a,b))
89.{
90.count++;
91.}
92.if(isEquals(b,c))
93.{
94.count++;
95.}
96.if(isEquals(a,c))
97.{
98.count++;
99.}
100.if(count>3)//如果三条边都相等,则count多加了一次
101.{
102.count=3;
103.}
104.
105.returncount;
106.}
107.
108./*
109.*判断是否满足两边平方之和是否等于第三边的平方
110.*
111.*/
112.boolisPowerSumEquals(inta,intb,intc)
113.{
114.if(a*a+b*b==c*c)
115.{
116.returntrue;
117.}
118.returnfalse;
119.}
120.
121./*
122.*判断第一个数是否比第二个数大
123.*/
124.boolisGreaterThan(inta,intb)
125.{
126.if(a>b)
127.{
128.returntrue;
129.}
130.returnfalse;
131.}
132.
133./*
134.*判断是否是直角三角形
135.*
136.*/
137.boolisRightRriangle(inta,intb,intc)
138.{
139.intmax=0;
140.if(isGreaterThan(a,b))
141.{
142.max=a;
143.a=b;
144.b=max;
145.}
146.if(isGreaterThan(b,c))
147.{
148.max=b;
149.b=c;
150.c=max;
151.}
152.returnisPowerSumEquals(a,b,c);
153.}
154.
155./*
156.*判断三角形的类型,返回值:
157.*1、不能组成三角形
158.*2、等边三角形
159.*3、等腰三角形
160.*4、直角三角形
161.*5、一般三角形
162.*6、某些边不满足限制
163.*/
164.inttriangleType(inta,intb,intc)
165.{
166.inttype=0;
167.if(isLegal(a,b,c))
168.{
169.if(isTriangle(a,b,c))
170.{
171.intnum=howManyEquals(a,b,c);
172.if(3==num)
173.{
174.type=2;
175.}
176.elseif(2==num)
177.{
178.type=3;
179.}
180.elseif(isRightRriangle(a,b,c))
181.{
182.type=4;
183.}
184.else
185.{
186.type=5;
187.}
188.}
189.else
190.{
191.type=1;
192.}
193.}
194.else
195.{
196.type=6;
197.}
198.returntype;
199.}
6.白盒测试实例之六——单元测试的步骤
白盒测试与黑盒测试的过程和方法是有一些区别的。
单元测试的步骤:
1、理解需求和设计
理解设计是很重要的,特别是要搞清楚被测试模块在整个软件中所处的位置,这对测试的内容将会有很大的影响。
需要记住的一个原则就是:
好的设计,各模块只负责完成自己的事情,层次与分工是很明确的。
在单元测试的时候,可以不用测试不属于被测试模块所负责的功能,以减少测试用例的冗余,集成测试的时候会有机会测试到的。
举例:
1./*
2.
3.*判断三条边是否能够组成三角形
4.
5.*返回值:
true-是;false-否
6.
7.*/
8.
9.boolisTriangle(inta,intb,intc);
测试该函数的时候,只需要测试三条边(在合法的取值范围内的整数)是否能够满足两边之和是否大于第三边的功能,而不需要测试三条边是否在合法的范围(0,200)之间的整数,因为调用该函数之前,一定要先通过下面函数的检查,要是检查不通过,就不会执行isTriangle函数。
1./*
2.
3.*判断三条边是否合法(即:
判断三条边都在合法的范围内)
4.
5.*返回值:
true-是;false-否
6.
7.*/
8.
9.boolisLegal(inta,intb,intc);
所以,单元测试主要是关注本单元的内部逻辑,而不用关注整个业务的逻辑,因为会有别的模块去完成相关的功能。
2、概览源代码
浏览一下源代码,主要任务:
(1)初步检查源代码的编码风格与规范
(2)大致估算测试工作量,比如:
需要多少的测试用例、需要写多少的驱动模块和装模块等。
(3)确定模块的复杂程度,初步制定测试的优先级等。
3、精读源代码
认真阅读和分析代码,主要任务:
(1)理解代码的业务逻辑。
(2)检查代码与设计是否相符,如果详细设计没有该模块的流程图的话,先去画出流程图。
(3)仔细研究逻辑复杂的模块
(4)可以采用一些检查列表来检查程序可能会出现的问题。
如果没有检查列表,那么,可以根据程序的特点,有针对性地检查容易出问题的地方(记得把经验总结下来供下次使用)。
4、设计测试用例
综合运用白盒测试方法(和结合黑盒测试方法)来设计测试用例,包括功能测试、性能测试等,要达到一定的测试覆盖率。
在设计测试用例的过程中,流程图或控制流图是分析的好帮手。
5、搭建单元测试环境
使用XUnit或自己写的框架将有助于单元测试的实施。
在这个阶段主要就是写桩模块和驱动模块,第4步所设计的测试用例是通过驱动模块传递给被测试模块的,然后驱动模块想办法获取被测试模块对数据的处理结果,并判定返回的实际结果与测试用例的预期结果是否一致,通过测试框架来记录执行的结果,对于出现的错误,还需要统计错误的信息,供执行完之后分析。
搭建单元测试环境要避免在main函数中使用printf和scanf函数来跟测试人员交互来达到获取测试用例数据的信息。
这样的测试还是没有摆脱手工测试方式,效率是低下的。
同时,对于测试结果是否通过测试也不要使用printf方式打印被测试函数的返回结果值,