一, 详解 TDD
1.1,TDD 概念 :Test Drived Develop
测试驱动开发是敏捷开发中的一项核心实践和技术, 也是一种方法论. TDD 的原理是在开发功能代码之前, 编写单元测试用例代码, 测试代码决定先编写什么产品代码. TDD 虽是敏捷方法的核心实践, 但不只是适用于 XP, 同样可以适用于其他开发方法和过程
TDD 的基本思路就是通过测试来推动整个开发的进行, 但测试驱动开发并不只是单纯的测试工作, 而是把需求分析, 设计, 质量控制量化的过成.
TDD 的重要目的不是仅仅测试软件, 测试工作保证代码质量只是其中一部分, 而且是开发过程中帮助客户和程序员去除模棱两可的需求. TDD 首先考虑使用需求(对象, 接口, 功能, 过程, 等)
1.2 测试驱动开发的优缺点
TDD: 测试驱动开发的优点:
再任意一个开发节点都可以拿出一个可以使用, 含少量的 BUG 并具有一定的功能能够发布的产品.
TDD: 测试驱动开发的缺点:
缺点: 增加了代码工作量. 测试代码几乎是系统代码的两倍或更多, 但是同时节省了程序调试的时间以及挑错的时间.
TDD=TFD+Refactoring 第一次测试开发加上重构
TDD:Test First Development 首次测试开发
1.3,TDD 原则
1. 独立测试: 不同代码的测试应该相互独立, 一个类对应一个测试类(对于 C 代码或 C++ 全局函数, 则一个文件对应一个测试文件), 一个函数对应一个测试函数用例也应该各自独立, 每个用例不能使用其他用例的结果数据, 结果也不能依赖于例执行顺序. 一个角色开发过程中包含多种工作,(编写测试代码, 编写产品代码, 代码重构 等. 做不同工作的时候, 应专注于当前要做的事情, 不考虑其他, 比如测试的时候就做测试)
2. 测试列表: 代码的功能点很多, 不可能是所有的需求都是很明确的, 而是陆陆续续的出现新的需求, 在进行的任何阶段时想添加功能时, 应把相关的功能点 添加到测试列表中, 在继续改阶段的工作, 以避免疏漏.
3. 测试驱动: 及利用测试来驱动开发, 是 TDD 的核心. 要实现某个功能, 要编写某个类或某个函数, 应该先编写测试代码, 明确这个类, 这个函数如何使用, 如何测试, 然后对其进行设计, 编码.
4. 先写断言: 编写测试代码时, 应该首先编写判断代码功能的断言语句, 然后编写必要的辅助语句.
能应该比较单纯, 每个类, 每个函数, 只做自己的事情, 不掺杂然和功能.
6. 及时重构: 对结构不合理, 重复等不好的代码, 在测试通过后, 应及时进行重构.
7. 小步前进: 软件开发是复杂性非常高的工作, 小步前进是降低复杂性的好办法.
1.4,TDD 总结
测试驱动开发: 既可以测试框架的性能, 也可以测出业务的合理性, 也可以测试出代码的问题, 虽然开发时间会延后, 但是可以提高客户的满意度, 上线后系统比较稳定.
一个软件的产出, 需要具有详细的设计: 从开始的竞标, 到立项到设计, 开发, 交付任何一个环节都不可缺少.
举例描述:
某公司竞标后拿下了这样一个工程, 在两座山之间建造一座大桥, 产品经理把业务具体分析过后交给了公司的设计师 (架构师) 设计师根据客户对产品的质量, 美观, 使用性, 进行架构设计: 产出物如下图:
架构师设计出有几个桥墩沉重力度, 桥面宽度高度, 形状... 等.
这样整体架构就出现了, 高级工程师根据架构师的架构进行小的设计比如说用什么样的材料怎么做桥于桥之间的关联等,(在开发来说就是用什么接口, 接口怎么制定, 怎么保证安全性)剩下的就交给中级工程师了, 等到开发完后进行测试.
上面简单的描述是一般产品的产出流程, 但是一般的流程去做这样一个特殊的工程显然不够的, 比如说怎么知道这个框架是否安全, 现在的说服力一般都体现在数字和具体的有说服力的案例上面, 但是没有案例的话, 就需要我们队框架进行测试了, 在这个没有真正做施工之前, 框架设计出之后进行的测试, 大家就可以理解成 TDD 测试了, 这时候的 TDD 很显然偏向于架构的设计. 再往小点的方面来说比如测试接口的时候, 其实也是设计接口, TDD 偏向于设计, 而不是很多人认为的测试.
利用 TDD 测试驱动 举一个例子:
业务场景: 用户下订单, 订单类型 "普通订单, 批量订单, 个人订单" 判断用户是是否具有下此类订单的权限.
如果所根据这个业务让咱们设计一下咱们肯定都没有问题:
数据库创建脚本
CREATE TABLE OederTable -- 订单表
- (
- ID INT PRIMARY KEY IDENTITY (1,1), -- ID
OredrNo varchar(100), -- 订单编号
OrderTypeNo varchar(100), -- 订单类型编号
CreateBy varchar(200)-- 创建人
)
CREATE TABLE UserRights -- 用户权限表
(
OrderTypeNo varchar(100),-- 订单类型编号
UserID INT -- 用户 ID
)
CREATE TABLE UserTable -- 用户表
- (
- ID INT PRIMARY KEY IDENTITY (1,1), --ID
UserName varchar(100), -- 用户名
UserPwd varchar(200) -- 用户密码
)
CREATE TABLE TypeTable -- 订单类型表
(
OrderTypeNo varchar(100),-- 订单类型编号
OrderTypeName varchar(100)-- 订单类型名称
)
View Code
填充数据
实现测试业务流程代码具体如下:
代码中映射了四个实体类, 一个订单操作类.
订单操作类具体代码如下(代码中并没有具体实现主要以意会为主(~o~))
- // 测试代码
- public void TestMethod1()
- {
- OrderOperation OrderOperation = new OrderOperation();
- OederTable Oeder = new OederTable();
- Oeder.OredrNo = "100";
- Oeder.OrderTypeNo = "1"; // 普通订单权限
- Oeder.CreateBy = "admin";
- //1. 验证用户是否存在
- //2. 验证用户是否是否具有下订单的权限
- //3. 保存入库
- /************ 假设用户表为空时咱们已经通过用户名密码查询过并且存在该用户 *************/
- UserTable user = new UserTable();
- if (user != null)
- {
- // 通过 UserID 查询权限是否有下普通订单的权限 Oeder.OrderTypeNo = "1"; 普通订单权限
- UserRights Rights = new UserRights();
- if (Rights != null)
- {
- // 添加入库
- OrderOperation.add(Oeder);
- }
- }
- }
- View Code
其实不管用任何办法, 只要结果符合描述就行, HARD Code 也是一个很好的方法, 我们现在关注点应该放在业务流程的正确性, 数据从哪里来不重要.
如果添加成功最好有一个返回值能体业务的正确性, 比如添加成功后返回 "OK"
以上描述有部分来自于互联网:
来源: https://www.cnblogs.com/szlblog/p/9011338.html