您的位置:首页 > 运维架构 > Linux

Linux 强大的文件查找工具之find

2014-03-11 16:25 357 查看
Test driver develop

什么时候重构?
重构是一种书写代码的方式,或习惯,重构时时刻刻有可能发生。在TDD中,除去编写测试用例和实现测试用例之外的所有工作都是重构,所以,没有重构任何设计都不能实现。
实现测试用例时重构代码,完成某个特性时重构设计,产品的重构完成后还要重构一下测试用例。

什么时候设计
自己把握,不要受到TDD的束缚,不要事先确定的事一定不要事先确定。

什么时候应该将全部测试都运行一遍?
Good Question!大师们要求我们每次重构之后都要完整的运行一遍测试用例。这个要求可以理解,因为重构很可能会改变整个代码的结构或设计,从而导致不可预见的后果,但是如果我正在开发的是一个ERP怎么办?运行一遍完整的测试用例可能将花费数个小时,况且现在很多重构都是由工具做到的,这个要求的可行性和前提条件都有所动摇。所以我认为原则上你可以挑几个你觉得可能受到本次重构影响的TestCase去run,但是如果运行整个测试包只要花费数秒的时间,那么不介意你按大师的要求去做。

关于单元测试
单元测试的目标是
Keep the bar green to keep the code clean
这句话的含义是,事实上我们只做两件事情:让代码奏效(Keep the bar green)和让代码洁净(Keep the code clean),前者是把事情做对,后者是把事情做好,两者既是TDD中的两顶帽子,又是xUnit架构中的因果关系。
单元测试作为软件测试的一个类别,并非是xUnit架构创造的,而是很早就有了。但是xUnit架构使得单元测试变得直接、简单、高效和规范,这也是单元测试最近几年飞速发展成为衡量一个开发工具和环境的主要指标之一的原因。正如Martin Fowler所说:“软件工程有史以来从没有如此众多的人大大收益于如此简单的代码!”而且多数语言和平台的xUnit架构都是大同小异,有的仅是语言不同,其中最有代表性的是JUnit和NUnit,后者是前者的创新和扩展。一个单元测试框架xUnit应该:1)使每个TestCase独立运行;2)使每个TestCase可以独立检测和报告错误;3)易于在每次运行之前选择TestCase。下面是我枚举出的xUnit框架的概念,这些概念构成了当前业界单元测试理论和工具的核心:
测试方法/TestMethod
测试的最小单位,直接表示为代码。
测试用例/TestCase
由多个测试方法组成,是一个完整的对象,是很多TestRunner执行的最小单位。
测试容器/TestSuite
由多个测试用例构成,意在把相同含义的测试用例手动安排在一起,TestSuite可以呈树状结构因而便于管理。在实现时,TestSuite形式上往往也是一个TestCase或TestFixture。
断言/Assertion
断言一般有三类,分别是比较断言(如assertEquals),条件断言(如isTrue),和断言工具(如fail)。
测试设备/TestFixture
为每个测试用例安排一个SetUp方法和一个TearDown方法,前者用于在执行该测试用例或该用例中的每个测试方法前调用以初始化某些内容,后者在执行该测试用例或该用例中的每个方法之后调用,通常用来消除测试对系统所做的修改。
期望异常/Expected Exception
期望该测试方法抛出某种指定的异常,作为一个“断言”内容,同时也防止因为合情合理的异常而意外的终止了测试过程。
种类/Category
为测试用例分类,实际使用时一般有TestSuite就不再使用Category,有Category就不再使用TestSuite。
忽略/Ignored
设定该测试用例或测试方法被忽略,也就是不执行的意思。有些被抛弃的TestCase不愿删除,可以定为Ignored。
测试执行器/TestRunner
执行测试的工具,表示以何种方式执行测试,别误会,这可不是在代码中规定的,完全是与测试内容无关的行为。比如文本方式,AWT方式,swing方式,或者Eclipse的一个视图等等。
实例:Fibonacci数列
下面的Sample展示TDDer是如何编写一个旨在产生Fibonacci数列的方法。
(1)首先写一个TC,断言fib(1) = 1;fib(2) = 1;这表示该数列的第一个元素和第二个元素都是1。
public void testFab() {
assertEquals(1, fib(1));
assertEquals(1, fib(2));
}
(2)上面这段代码不能编译通过,Great!——是的,我是说Great!当然,如果你正在用的是Eclipse那你不需要编译,Eclipse会告诉你不存在fib方法,单击mark会问你要不要新建一个fib方法,Oh,当然!为了让上面那个TC能通过,我们这样写:
public int fib( int n ) {
return 1;
}
(3)现在那个TC亮了绿灯,wow!应该庆祝一下了。接下来要增加TC的难度了,测第三个元素。
public void testFab() {
assertEquals(1, fib(1));
assertEquals(1, fib(2));
assertEquals(2, fib(3));
}
不过这样写还不太好看,不如这样写:
public void testFab() {
assertEquals(1, fib(1));
assertEquals(1, fib(2));
assertEquals(fib(1)+fib(2), fib(3));
}
(4)新增加的断言导致了红灯,为了扭转这一局势我们这样修改fib方法,其中部分代码是从上面的代码中Ctrl-C/Ctrl-V来的:
public int fib( int n ) {
if ( n == 3 ) return fib(1)+fib(2);
return 1;
}
(5)天哪,这真是个贱人写的代码!是啊,不是吗?因为TC就是产品的蓝本,产品只要恰好满足TC就ok。所以事情发展到这个地步不是fib方法的错,而是TC的错,于是TC还要进一步要求:
public void testFab() {
assertEquals(1, fib(1));
assertEquals(1, fib(2));
assertEquals(fib(1)+fib(2), fib(3));
assertEquals(fib(2)+fib(3), fib(4));
}
(6)上有政策下有对策。
public int fib( int n ) {
if ( n == 3 ) return fib(1)+fib(2);
if ( n == 4 ) return fib(2)+fib(3);
return 1;
}
(7)好了,不玩了。现在已经不是贱不贱的问题了,现在的问题是代码出现了冗余,所以我们要做的是——重构:
public int fib( int n ) {
if ( n == 1 || n == 2 ) return 1;
else return fib( n - 1 ) + fib( n - 2 );
}
(8)好,现在你已经fib方法已经写完了吗?错了,一个危险的错误,你忘了错误的输入了。我们令0表示Fibonacci中没有这一项。
public void testFab() {
assertEquals(1, fib(1));
assertEquals(1, fib(2));
assertEquals(fib(1)+fib(2), fib(3));
assertEquals(fib(2)+fib(3), fib(4));
assertEquals(0, fib(0));
assertEquals(0, fib(-1));
}
then change the method fib to make the bar grean:
public int fib( int n ) {
if ( n <= 0 ) return 0;
if ( n == 1 || n == 2 ) return 1;
else return fib( n - 1 ) + fib( n - 2 );
}
(9)下班前最后一件事情,把TC也重构一下:
public void testFab() {
int cases[][] = {
{0, 0}, {-1, 0}, //the wrong parameters
{1, 1}, {2, 1}}; //the first 2 elements
for (int i = 0; i < cases.length; i++)
assertEquals( cases[i][1], fib(cases[i][0]) );
//the rest elements
for (int i = 3; i < 20; i++)
assertEquals(fib(i-1)+fib(i-2), fib(i)); }
(10)打完收工。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: