实验简介
所谓TDD,是指测试驱动开发,英文全称为:Test-Driven Development。从字面意思,不难理解,就是利用基于测试用例驱动的一种开发过程,通俗一点来说,就是我们在设计一段程序和一个功能之前,先思考和设计测试用例,进而反射促进代码的开发。那么什么时候代码的开发工作算是完成了呢?那就是,只要所有的事先设计的测试用例都执行通过了,则代码就算完成开发,完成验收。开发人员就可以继续下一个功能的测试和开发。
本节将基于ArrayCompare程序中的StringHandle类中的isNumber()方法进行TDD实践。
实验目的
(1) 掌握TDD测试驱动开发的实践过程。
(2) 理解测试技术在软件研发过程中的重要价值。
实验流程
1. TDD实施过程
2. TDD遵循的基本原则
(1) 独立测试:不同代码的测试应该相互独立,一个类对应一个测试类(对于C代码或C++全局函数,则一个文件对应一个测试文件),一个函数对应一个测试函数。用例也应各自独立,每个用例不能使用其他用例的结果数据,结果也不能依赖于用例执行顺序。 一个角色:开发过程包含多种工作,如:编写测试代码、编写产品代码、代码重构等。做不同的工作时,应专注于当前的角色,不要过多考虑其他方面的细节。
(2) 测试列表:代码的功能点可能很多,并且需求可能是陆续出现的,任何阶段想添加功能时,应把相关功能点加到测试列表中,然后才能继续手头工作,避免疏漏。
(3) 测试驱动:即利用测试来驱动开发,是TDD的核心。要实现某个功能,要编写某个类或某个函数,应首先编写测试代码,明确这个类、这个函数如何使用,如何测试,然后在对其进行设计、编码。
(4) 先写断言:编写测试代码时,应该首先编写判断代码功能的断言语句,然后编写必要的辅助语句。
(5) 可测试性:产品代码设计、开发时的应尽可能提高可测试性。每个代码单元的功能应该比较单纯,"各家自扫门前雪",每个类、每个函数应该只做它该做的事,不要弄成大杂烩。尤其是增加新功能时,不要为了图一时之便,随便在原有代码中添加功能。
(6) 及时重构:对结构不合理,重复等"味道"不好的代码,在测试通过后,应及时进行重构。
(7) 小步前进:软件开发是复杂性非常高的工作,小步前进是降低复杂性的好办法。
3. 梳理isNumber()方法的需求点
根据功能要求,我们可以列举如下一些规则,进而更清晰,更全面覆盖各种可能的输入:
(1) 有效的数字必须只能包含0-9的数字,小数点和负号。
(2) 如果有小数点和负号,小数点最多只能有一个,负号最多只能有一个。
(3) 如果是负数,则负号必须在第一位。
(4) 如果是负小数,小数点必须在第二位之后。
(5) 如果不是小数,则不能以0开头。如果是负整数,则第二位不能为0.
4. 设计测试用例
根据上术对功能需求和检查规则的整理,我们可以设计如下一些测试用例:
(1) 有效的值:"12345", "-12345", "123.45", "-123.45", "0.123", "-0.12345", "-.123", "123.", ".12345"。
(2) 无效的值:"012345", "1-23", "0.-123", "12345-", "123T", "00000", "-1.23-", "123.45.56", "123*5","-0123", "12中3 ","12#3 "。
上述的有效值和无效值便可以作为我们的测试用例用于对被测试方法进行测试。
5. 让isNumber()方法可运行
最开始,我们只需要设计一个简单的isNumber(),有参数,有返回值,无任何处理逻辑,仅仅只是简单的保证代码可以运行,代码如下:
// 设计实现代码isNumber方法 public boolean isNumber(String source) { return true; } |
6. 开发测试驱动程序
package com.woniuxy.test; public class TDDDemo { public static void main(String[] args) { TDDDemo tdd = new TDDDemo(); tdd.testIsNumber("12345", true); tdd.testIsNumber("-12345", true); tdd.testIsNumber("123.45", true); tdd.testIsNumber("-123.45", true); tdd.testIsNumber("0.123", true); tdd.testIsNumber("-0.12345", true); tdd.testIsNumber("-.123", true); tdd.testIsNumber("123.", true); tdd.testIsNumber(".12345", true); tdd.testIsNumber("012345", false); tdd.testIsNumber("12-3", false); tdd.testIsNumber("0.-123", false); tdd.testIsNumber("12345-", false); tdd.testIsNumber("123T", false); tdd.testIsNumber("00000", false); tdd.testIsNumber("-1.23-", false); tdd.testIsNumber("123.45.56", false); tdd.testIsNumber("123*5", false); tdd.testIsNumber("-0123", false); tdd.testIsNumber("12中3", false); } // 测试接口isNumber()的测试驱动程序 public void testIsNumber(String source, boolean expect) { boolean actual = this.isNumber(source); if (actual == expect) { System.out.println("StringHandle-isNumber: 测试成功."); } else { System.out.println("StringHandle-splitString: 测试失败: " + source); } } // 设计实现代码isNumber方法 public boolean isNumber(String source) { return true; } }