上线前测试代码复杂度上去后修改越来越小心翼翼项目重构需要花费大量的时间学习 不同的自动化编码方式
可以编写通过浏览器自动执行的程序可以直接调用原代码里面的函数也可以直接对比程序渲染后的截图 自动化程序的优点
尽早的发现程序的bug和不足增强程序猿对程序的健壮性和稳定性的信心改进设计快速反馈,减少调试时间促进重构 测试分类
单元测试:验证独立单元是否正常工作集成测试:验证多个单元协同工作端到端测试:从用户角度以机器人的方式在真实浏览器环境验证应用交互快照测试:验证程序的UI变化 单元测试 单元测试的优点
提高代码质量,减少bug快速反馈,减少调试时间让代码维护更容易有助于代码的模块化设计代码覆盖率高 单元测试的缺点
由于单元测试是独立的,所以无法保证多个单元运行到一起是否正确 集成测试
主要测试用户的操作,用户输入了什么,输出想要的结果,具体什么实现用户是不关心的。
测试代码
describe("todo集成测试", () => {
test("todo测试", async () => {
const wrapper = mount(TodoApp);
const todoInput = wrapper.find('[data-testid="todo-input"]');
const text = 'hello world';
await todoInput.setValue(text);
await todoInput.trigger('keyup.enter');
const todoText = wrapper.find('[data-testid="todo-text"]');
expect(todoText.text()).toBe(text)
})
})
集成测试的优点
由于是从用户的使用角度出发,更容易获得软件使用过程中的正确性集成测试相对于写了软件的说明文档由于不关注底层代码实现细节,所有更有利于快速重构相比于单元测试,集成测试的开发速度要更快一些 集成测试的缺点
测试失败的时候无法快速定位问题代码覆盖率较低速度比单元测试要慢 端到端测试(E2E)
在前端应用程序中,端到端的测试可以从用户的视角通过浏览器自动检查应用程序是否正常工作。
测试代码
decribe('我的测试', () => {
it('访问页面根路径', () => {
cy.visit("http://localhost:8080/");
cy.contains('h1', 'todos);
})
it('访问页面根路径', () => {
cy.visit('http://localhost:8080/')
const text = 'Hello World'
cy.get('[data-testid="todo-input"]').type(`${text}{enter}`)
cy.contains(text)
})
})
端到端测试的优点
真实的测试环境,更容易获得程序的信心 缺点
端到端测试运行不够快端到端测试的另一个问题是调试起来比较困难 流行的端到端的测试框架
CypressNightwatchWebdriverIOplaywright 快照测试
测试代码
describe('快照测试', () => {
const wrapper = shallowMount(TodoHeader);
expect(wrapper.html()).toMatchSnapshot()
})
测试金字塔
金字塔模型
UI测试(UI Tests)集成测试(Service Tests)单元测试(Unit Test) 奖杯模型
静态测试:在编写代码逻辑阶段是进行报错提示(ESLint、Flow、Typescript)单元测试:Jest、Mocha集成测试:Jest、Vue Testing Librarye2e测试:Cypress、Nitghtwatch 不同的应用场景
如果是开发纯函数库,建议写更多的单元测试+少量的集成测试如果是开发组件库,建议写更多的单元测试、为每个组件编写快照测试、写少量的集成测试+端到端测试如果是开发业务系统,建议写更多的继承测试、为工具类库、算法写单元测试、写少量的端到端测试 测试覆盖率
代码覆盖率测试覆盖率(test coverage)是衡量软件测试完整性的一个重要指标。掌握测试覆盖率数据,有利于客观认识软件质量,正确了解测试状态,有效改进测试工作。
被执行的代码数量与代码总量之间的比值,就是代码覆盖率。
代码粒度不同可以分为源文件覆盖率、函数覆盖率、分支覆盖率、语句覆盖率
需求覆盖率度量测试所覆盖的需求数量与总需求量的比值。
测试开发的方式测试开发的两个流派
TDD:测试驱动开发,先写测试后实现功能BDD:行为驱动开发,先实现功能后写测试 TDD
TDD(Test-driven development),测试驱动开发,是敏捷开发中的一项核心实践和技术,也是一种软件设计方法论。
编写测试用例运行测试编写代码使测试通过重构、优化代码新增功能,重复代码
TDD的原则
独立测试:不同代码的测试应该相互独立,一个类对应一个测试类,一个函数对应一个测试函数测试列表:应把相关功能点加到测试列表中测试驱动先写断言可测试性及时重构小步前进 TDD的优缺点
优点
保证代码质量,因为先编写测试,所以可能出现的问题都被提前发现了促进开发人员思考,有利于程序的模块设计测试覆盖率搞,因为后编写代码,因此测试用例基本都有覆盖到
缺点
代码量增多,大多数情况下测试代码是功能代码的两倍甚至更多业务耦合度高,测试用例中使用业务中模拟的数据,当业务代码变更的时候,要去重新组织测试用例关注点过于独立,由于单元测试只关注一个单元的健康状况,无法保证多个单元组成的整体是否正常
TDD更适合开发纯函数库,TDD最终做出来的东西有可能和实际需求相偏离。
BDDBDD(Behavior-driven development)行为驱动开发,是测试驱动开发延伸出来的一种敏捷软件开发技术。
BDD的核心目的是为了解决TDD模式下开发和实际功能需求不一致而诞生的。BDD不需要在面向细节设计测试,取而代之的是面向行为来测试从产品的角度触发,鼓励开发人员和非开发人员之间的协作由于BDD的核心是关注软件的功能测试,所以BDD更多的是结合集成测试进行,是黑盒的。 BDD的开发流程
- 开发人员和非开发人员一起讨论确认需求以一种自动化的方式将需求建立起来,并确认是否一致实现每个文档示例的描述行为,并从自动化测试开始指导代码的开发
优点
由于侧重于需求功能的完整度,所以能给开发人员增加更多的信心由于仅关注功能,不关注实现细节,有利于测试代码和实际代码解耦由于大多数为编写集成测试,相比TDD有更好的开发效率
缺点
因为以功能性的集成测试为主,因此不是那么关注每个函数功能,函数覆盖率比较低没有TDD那么严格的保证代码质量 TDD vs BDD
| 功能 | TDD | BDD |
|---|---|---|
| 定义 | 测试驱动开发 | 行为驱动开发 |
| 思想 | 从代码的角度出发,以完成高质量代码为目的 | 从用户角度出发,以完成用户功能需求为目的 |
| 开发流程 | 需求分析;编写单元测试;运行测试;编写代码;运行测试;重构优化;重复上述步骤; | 开发人员与产品、测试、客户等人员沟通并确认客户需求;使用统一格式文档描述功能需求文档;根据功能需求文档建立测试用例;运行测试;编写代码实现功能;运行测试通过;重构优化;重复上述步骤; |
| 代码覆盖率 | 高 | 一般 |
| 软件安全感 | 一般 | 高 |
| 测试类型 | 单元测试 | 集成测试 |
| 代码解耦 | 一般 | 高 |
| 开发效率 | 一般 | 高 |
| 代码质量 | 高 | 一般 |
| 测试代码量 | 高 | 低 |
开发功能函数库建议使用TDD方案;开发业务系统建议使用BDD方案; 自动化测试的权衡 适合使用自动化测试的场景
需要长期维护的项目较为稳定的项目、或项目中比较稳定的部分被多次复用的部分,比如一些通用组件和库函数



