单元测试

不管是开发还是重构, 这个过程都会涉及到重构的概念 , 看看这个概念要怎么进行处理? 如何简历更好的单元测试;

使用书籍: 《单元测试的艺术》




我们通过系统的公共API和行为就可以光差到一个可见的最终结果, 无需查看系统的内部装填。
一个最终结果可以是一下任何一种形式:
1》 被掉员工公公公方法返回一个值(一个放回不为空的函数)
2》在方法调用的前后, 系统的装填或系统有可见的变化,,或者一个状态机系统的舒心发生变化
3》调用了一个不受测试控制的第三方系统, 这个第三方系统不返回任何值。 或者返回的值是被忽略的。 (eg: 调用一个第三方日志系统, 这个系统不是你编写的, 而且你也没有源代码。)

这个表示赞同, 因为我们输入的简单,但是里面过程复杂, 返回的也简单,输入的简单是以为时输入的范围在较小的有限范围内

单元测试 、 工作单元、 优秀单元测试【保证代码治质量很重要】

QR : 什么是单元测试?? 什么不是单元测试?

集成测试:相对比较慢,
集成测试的另一个问题:一次测试的东西踏跺


与自动化单元测试相比, 非自动化集成测试的缺点:
1) 一段时间之后,该测试不同通过。 定义:回归是以前运行良好但是现在不通过的一个或多个工作单元
2)当我们改动代码的 时候,不会破坏别人的代码。 不直达搜系统修改后的状态是否稳定。


1)能在几分钟内跑完我写过的所有单元测试吗?
2)我一键运行我写过的额所有单元测试吗?
3)在几分钟内写出一个基本的测试吗?

QR: 什么是优秀的单元测试



QR: 如何编写单元测试? 在开发过程中应该何时编写单元测试。

1.6 测试驱动开发
编写结构化、可维护 和 可靠的测试。

很多人觉得为软件编写单元测试的最佳时机是软件编码完成以后, 但是越来越多的人选择在产品代码编写之前写单元测试。 —— 测试优先或测试驱动开发 (test driveen development , TDD )



我们必须意识到, TDD并不能够保证项目一定成功、或者测试都健壮、可维护。

TDD技术:
1)编写一个会失败的测试, 以证明产品中代码或者功能的缺失
2) 编写符合测试预期的产品代码, 使测试通过。 —— 产品代码尽量简单
3)重构代码 —— 写下一个单元测试或者重构代码

重构可以编写多个测试之后进行,也可以在每个测试后都进行。 重构确保 —— 代码容易读、更好维护、通过编写的所有测试。

TDD一个最大的有点:
(1)如果一个测试失败了,没有经过修改再次运行又成功了,你其实是在测试这个测试本身。
(2) 如果你预期一个测试失败了,但它却成功了,那么测试本身可能有缺陷, 或测试的对象不对。
(3)如果一个测试之前失败了,你现在预期它成功,它却依然失败,那测试可能有缺陷, 或测试预期的结构不正确。

测试两个方面: 该失败的时候失败,该成功的时候成功


1.7 成功进行TDD的三种核心技能

知道如何编写优秀的测试、在编码前编写测试、良好的测试设计
1) 仅仅做到先编写测试,并不能够保证测试是可维护、可读以及可靠的。
2)仅仅做到编写的测试可读、可维护、并不能保证你获得先编写测试的各种好处。
3)仅仅做到先编写测试,并且测试可读,可维护,并不能够保证你得到一个设计完善的系统。



第一个单元测试

QR:首先考虑一个问题: 我们需要考虑什么是单元测试框架, 用它能够做什么以前不能也不会做的事?
AS: 手工进行测试和回归测试,很容易出错、浪费时间。 单元测试框架可以帮助开发人员使用一套已知的API更快地编写测试, 自动执行这些测试,轻松查看结果。

2.1.1 单元测试框架提供什么?

  1. 不是结构化的。 每当要测试一个新功能要重新写代码。 一个测试可能看着像控制台程序,另一个测试使用UI窗体,另一个又是web表单。 没有多余的时间花费在测试上, 这些测试都没有达到“容易实现”这个要求。 —— 看看,这个和UI相关的并不是那么容易实现?
  2. 不可重复。 无法运行以前编写的测试,这个就是不可重复。
  3. 不能覆盖代码的所有重要部分。 测试没有测试到所有重要的代码。 —— 更高的重要代码的覆盖率。

—— 编写、运行和查看单元测试及其结果的框架。

单元测试 : 帮助开发人员进行单元测试的代码库和模块。 —— 作为自动编译过程的一个步骤进行测试。




像我们的iOS, 就应该先了解XCTest里面的每一个方法,具体是实现了什么东西? 然后再进行处理这个内容。

在iOS上面,其实就是方法给每个业务创建一个测试类,然后方法是testxxx 就可以了

Assert方法, 这个方法有很多其他的类型,不同的判断,也就是我们对结果的判断。

测试代码: 校验测试代码和业务代码,修复代码让其通过测试。

2.4.3 添加正检验 —— 也就是验证,我现在的情况是正确的。 当然,还有其他的情况排除, 这些情况排除是我们在写测试用例的时候,就应该处理掉的。

测试代码格式
1)尽量把断言和操作对象代码分开。 让测试代码更加的易读。

2.5 > 使用参数重构测试


有关测试的框架步骤以及过程:
setup & teardown 测试框架基本上都有的;

保证创建和销毁的对象的状态,这个过程可以有根据的判断。

2.6.1 > 执行的流程
setup ——> 执行代码 ——> teardown


ios 中有两个测试: 一个是基本单元测试;一个是集成测试;

2.6.2 > 检验预期的异常
一个常见的测试场景是:保证当异常应该抛出时, 被测试的方法能够抛出正确的异常。
所以,我们不仅仅使用了断言,同事我们应该也使用了异常的判断。
异常的测试: 我们可以使用try/catch 要判断出来在哪个位置

忽略测试, 看看我们iOS中有没有忽略的测试
ios 中没有忽略测试这个概念; (情况很少见,所以,iOS基本上就没有这个东西了)

断言方法的使用

设置测试类别, 看看那iOS 中有没有可以测试的类别;

2.7 测试系统状态的改变而非返回值

前面是对工作单元最简单的结果: 返回值进行测试

现在: 系统状态改变 —— 检验被测试系统在执行某个动作前后其行为发生变化。


使用存根破除依赖

简单例子里面: 测试只需啊哟检查对象的返回值,或者一个简单系统里的被测试单元状态

要测试的对象依赖另一个你无法控制(或者还未实现)的对象。 这个对象可能是web服务、系统时间、线程调度或者很多其他东西。 重要的问题是:你的测试代码不能控制这个依赖的对象放你的代码返回什么值, 不不能够控制它的行为。 —— 就可以使用 存根
:::也就是里面依赖了不可预知的变化。

定义:一个外部依赖项(external dependency) 是系统中的一个对象, 被测试代码与这个对象发生交互,但你不能控制这个对象。(常见的外部依赖项包括:文件系统、线程、内存以及时间等)

使用存根来回避外部依赖项的问题。

定义:一个存根(stub)是对系统中存在的一个依赖项(或者协作者)的可控制的替代物。 通过使用存根,你在测试代码时无需直接处理这个依赖项。

第4章中将 对 存根(stub) 、模拟对象(mock)以及伪对象(fake)的定义并讨论它们之间的关系。

存根和模拟对象的区别: 模拟对象和存根很类似,但是你会对模拟对象进行断言,而不会对存根进行断言。



破除依赖的确定模式:


3.4 重构代码设计以提高可测试性
重构: refactoring
接缝: seam


3.4.1 抽取接口使底层实现可替换


这样写,更加容易去测试这个内容

3.4.3 在构造函数层注入一个伪对象
给被测试类添加一个新的构造函数。传入一个之前抽取出来的接口类型的对象,然后在被测试类中添加一个这个接口类型的局部字段,把传入的对象赋给这个布局字段,供被测试方法或其他方法使用。


伪对象放在和测试代码同一个位置里面,会更加好维护管理;


2. 什么时候应该使用构造函数注入


3.4。4 》 用伪对象模拟异常



3.4.5 用属性的get或者set注入伪对象



3.4.6 在方法调用前注入伪对象

___ [这哪是略过]

重构技术变种:

【其他暂时略过】


第5章 隔离(模拟)框架

5.1 为什么要使用隔离框架

5.2 动态生成伪对象

5.3 模拟值

5.4 测试时间相关的活动

5.5 现有的.net 隔离框架

5.6 隔离框架的优缺点

5.7 小结


6、深入了解隔离框架

6.1 受限框架及不受限框架

6.2 优先的隔离框架的价值

6.3 支持适应未来和可用性的功能



第三部分: 测试代码



测试层次和组织

7.1 运行自动化测试的自动化构建
7.2 基于速度和类型布局测试
7.3 确保测试是源代码管理的一部分
7.4 将测试类映射到被测试代码
7.5 注入横切关注点
7.6 为应用程序构建测试API
7.7 小结:


8.优秀单元测试的支柱:

8.1 编写可靠的测试
8.2 编写可维护的测试
8.3 编写可读的测试

小结:


第4部分:设计和流程


第9章节: 在阻止中引入单元测试
第10章节:遗留代码
第11章节:设计与可测试性

你可能感兴趣的:(单元测试)