新手也能看懂的【前端自动化测试入门——1,持续更新中...】

前言

最近在网上搜索前端自动化测试相关的文档,但是发现网上的文章都是偏使用,没有把一些基础概念说清楚,导致后续一口气遇到一些karma、Jasmine、jest、Mocha、Chai、BDD等词汇的时候很容易一头雾水,这次一方面整理一下收获的知识一方面做个分享。

什么是前端自动化测试

我个人做题喜欢使用拆解法,比如什么是"前端自动化",根据这个题目可知,"前端"是在范围/领域,"自动化"是方法,通过脚本或者工具等各种方式在没有人或者很少人的协助下实现预期的目标的过程,"测试"是工作,是为了保证软件项目质量的工作。那么前端自动化测试就是在不借助人员帮助下,通过使用脚本或者工具等各种方式保证前端项目的项目质量的任务。

首先,一般人在正式工作中,往往由于工作的强度和业务的要求开发项目的时候都没有编写自动化测试脚本的环节。但是在后续过程中职业生涯中,参与一些大型项目或者一些使用人很多的第三方库中,会对代码质量和功能稳定性的要求越来越高,以及多人协作开发的开发集成交付效率,更为了提高自己的知识储备和行业竞争力,学会前端自动化测试的一些相关基础是很必要的。

前端测试分类

既然讲了什么是前端自动化测试,那么前端测试又分成哪几类呢?

首先前端测试分类往往指的是涵盖的模块大小,从最小的函数方法到整个应用的自动化测试分成了多个模块:

  1. 静态代码分析 :静态代码分析工具(如 ESLint、Stylelint、Preitter)通过静态分析源代码来检测潜在的错误、代码风格问题和安全漏洞。它们的原理是基于预定义的规则或自定义规则对代码进行扫描,并生成相应的警告或错误。这些工具帮助开发人员在编码阶段捕获问题,提高代码质量和可维护性。

    静态代码分析的工作主要是通过配置分析工具配置文件的方式,由于Eslint工具十分成熟且网上配置教程众多,这里就不展示案例,【后续如果有人要求,可详细更新这块内容】。

  2. 单元测试 :单元测试------这是在软件开发里常常听到的词,单元测试是针对软件系统中最小的可测试单元(在前端里通常是函数或方法)进行的测试。测试工具(如 Jest、Mocha、Enzyme)使用断言库来验证函数的输入和输出是否符合预期。它们通过提供的测试框架和断言库来运行和验证函数的行为,以确保各个单元(函数)的正确性。

    下面一个例子,通过mocha编写的自动化脚本去测试函数的返回是否符合预期:

js 复制代码
 // 目标函数,返回的是两数之和
 function sum(a, b) {
     return a + b;
 }
 
 describe('sum', () => {
  it('返回两数之和', () => {
    const result = sum(2, 3);
    // expect里为测试目标,入参为2和3的sum函数
    // equal里为结果,期望返回的是5
    // 如果实际执行中返回的结果不对则会报错
    expect(result).to.equal(5);
  });
});
  1. 集成测试:再封装一层,将已通过测试的单元按设计要求集成起来再进行的测试就是集成测试;集成测试用于测试多个组件或模块之间的交互和集成情况。测试工具(如 Jest、Mocha)提供了功能来组织和运行集成测试套件,并使用模拟、桩(stub)或替代(mock)等技术来模拟外部依赖。它们可确保不同组件之间的集成正常工作,并验证系统的整体功能。在前端往往是模拟组件生成到接口集成测试这部分的工作。

下面一个例子,Mock远程数据到调用组件方法来验证登陆组件是否能正常工作:

Vue 复制代码
<template>
   <Login ref="login" />
</template>
<script>
import { ref } from "vue"
const au = ref("")
Mock.mock("/login", {
  code: 200,
  msg: "成功",
  data: {
    token: "abcdefg",
  },
});

fetch("/api/data", {
  method: "POST",
})
  .then((data) => {
      au.value = data.token;
});
  
this.$refs.login.setToken({ token })
<script>
  1. 端到端测试:咱们继续往上游链路走,当我们把集成好的应用放到不同应用终端中进行实际运行测试就是端到端测试;端到端测试(End-to-End Testing)是模拟真实用户环境中用户操作和行为的测试。测试工具(如 Cypress、Puppeteer、Playwright)通过控制浏览器或模拟用户操作来执行测试。它们可以模拟用户在浏览器中的交互行为、检查页面元素和状态,并验证整个应用程序的功能和用户体验。 下面一个例子,模拟用户在浏览器中页面正常打开并表单正常渲染:
js 复制代码
// 在Cypress测试脚本中,可以使用describe和it来组织测试用例
describe('模拟用户提交表单', () => {
  // 在每个测试用例之前执行的操作可以放在beforeEach中
  beforeEach(() => {
    // 打开网页
    cy.visit('https://www.example.com')
  })

  // 编写测试用例
  it('展示页面标题', () => {
    // 断言页面标题是否正确
    cy.title().should('include', 'Example')
  })

  it('模拟表单提交', () => {
    // 定位并填写表单
    cy.get('#name').type('Xiaoyou Xin')
    cy.get('#email').type('XinXiaoYou@example.com')
    cy.get('#submit').click()

    // 断言表单提交后的结果
    cy.get('#result').should('contain', 'Success!')
  })
})
  1. 性能测试:锦上添花,当页面的主流程和功能都测试完成以后我们还需要对页面的性能有所追求,这个时候对应用程序的各项性能特征,包括加载速度、资源使用、响应时间等进行测试评估就是性能测试,相关的性能测试工具有如 Lighthouse、WebPageTest等。它们模拟和测量应用程序在不同网络条件和硬件环境下的性能表现,并提供有关性能瓶颈和优化建议的报告。

通过在chromium中集成chrome拓展程序实现模拟应用程序报告,提供一个Lighthouse插件的页面性能测试方法

单元化测试入门

现在我们开始正式的开始了解具体的单元测试的几个概念:

断言------断言是在编程中用于检查代码行为是否满足预期的一种机制或语句。它用于验证代码的某个条件是否为真,并在条件不满足时触发错误或异常。

通俗易懂地说,断言就像是一个自动化的检查员,它会在你编写的代码中的特定位置进行判断,以确保代码的一些假设或预期是正确的。如果断言的条件为真,那么一切正常,代码会继续执行。但是,如果断言条件为假,也就是代码行为和预期不符,断言会触发一个错误或异常,指示代码存在问题。

举个例子,当我们想要验证sum函数是否按照我们的预期返回结果的时候,我们就可以通过断言机制:

js 复制代码
// 一个相加求和的函数
function sum(a, b) {
  return a + b;
}

// 使用Node中的assert断言模块验证 sum 函数的输出是否符合预期
/**
 *  用于程序调试、单元测试中比较前后值是否相同的方法
 *  @params {any} actual 实际返回值
 *  @params {any} expected 期望返回值
 *  @params {string} actual 结果错误时的提示信息
 */
assert.equal(sum(2, 3), 5, 'sum函数计算错误');

而基于该机制,延伸出了很多断言库以及断言编码风格,现在我列举几个比较主流的断言库以及其特点。

  1. Chai: Chai 是一个灵活且可扩展的断言库,它提供了多种风格和接口供选择。Chai断言库本身支持断言风格包括断言式(assert-style)、BDD 风格(expect-style)和应用链式风格(should-style)三种断言风格供用户选择(需要注意的是每种风格的实现原理也并不相同,比如should-style使用到了Es6的Object.getPrototypeOf函数,所以它并不支持IE浏览器)。这里给大家展示一下三种风格在写法上的区别:

断言式(assert-style)

断言式风格比较接近NodeJs,使用方法接近Node中的模块概念,通过暴露assert模块,然后调用其中的interface接口方法进行使用。

js 复制代码
const assert = require('chai').assert
const foo = 'bar'

assert.typeOf(foo, 'string') // without optional message
assert.typeOf(foo, 'string', 'foo is a string') // with optional message
assert.equal(foo, 'bar', 'foo equal `bar`') 

BDD 风格(expect-style)

BDD风格有两种风格:expect-style和should-style。整体风格可以感觉像是在模仿人类正常进行运算行为,从左到右链式调用。

js 复制代码
import { expect } from 'chai'
const foo = 'bar'
    , beverages = { tea: [ 'chai', 'matcha', 'oolong' ] }


expect(foo).to.be.a('string')
expect(foo).to.equal('bar')
expect(foo).to.have.lengthOf(3)
expect(beverages).to.have.property('tea').with.lengthOf(3)

应用链式风格(should-style)

js 复制代码
import { should } from 'chai'
const foo = 'bar'
    , beverages = { tea: [ 'chai', 'matcha', 'oolong' ] }

foo.should.be.a('string')
foo.should.equal('bar')
foo.should.have.lengthOf(3)
beverages.should.have.property('tea').with.lengthOf(3)

完整的API文档和断言库介绍可以去官网:Chai官方入口
ps:我觉得学习一个工具最好的方式之一就是查阅官方文档,因为任何第三方文章解读都有可能出现信息错误或者版本过时等问题存在,后续我也会贴出对应官网入口。

  1. PowerAssert :PowerAssert 是一个基于表达式值的断言库,它能够根据表达式的值自动生成详细的断言信息。这使得在断言失败时能够更容易地理解断言失败的原因。 PowerAssert 官方入口

  2. Jest :Jest是一款由FaceBook推出的开源项目,它本身其实是一个功能强大的测试框架,并且内建了断言库。Jest 提供了丰富的断言方法,如 expect,它的整体风格 的 expect 语法类似,但是不提供链式调用,而是直接调用一个方法进行使用,使用 expect 函数和一系列的匹配器(matchers),可用于编写简洁易读的测试用例,并且与 Jest 的其他功能集成良好。

Jest官方文档入口

js 复制代码
expect(sum(1, 2)).toBe(3);
expect(sum(-1, 5)).toBe(4);
  1. ....

我们通过刚刚的学习,了解了单元测试的最基本模块,也就是断言,并且简单了解了多种风格的断言库,知道了如何通过使用对应的API和语法对一些测试对象(方法/模块)进行断言。而在介绍Jest的过程中,我们提到了一个词汇------------测试框架。那么,什么是测试框架呢?先上定义:

测试框架------是一种工具或库,用于帮助开发人员编写、组织和执行测试用例,并提供相关的工具和功能来简化测试过程和结果的分析。测试框架可以帮助开发人员编写高质量和可靠的测试用例,自动化测试执行,并提供丰富的工具和功能来简化测试过程。

简单的了解,测试框架就是集成了测试需要的相关能力,我们不需要再为了模拟环境、运行代码、配置断言库等底层能力重新开发,可以直接拿来配置好就可以使用的百宝箱。

测试框架通常提供以下功能和特点:

  1. 测试运行器 :测试框架提供测试运行器,用于自动化执行测试用例。它可以扫描测试文件或目录,并运行其中的测试代码。测试运行器负责调用测试代码,并收集和报告测试结果。其中Karma 就是有名的独立测试运行器,它可以与多个测试框架(包括 Mocha、Jasmine、QUnit 等)结合使用,需要注意的是截止于2023-4-28,该运行器已经停止维护。 karma 测试运行器入口
  2. 断言库:测试框架通常内置了断言库,用于编写断言语句来验证代码的行为是否符合预期。断言库提供了一组函数和方法,使得编写断言变得简单和直观。
  3. 测试套件和组织:测试框架提供测试套件和组织机制,用于组织测试用例。测试套件是一组相关的测试用例,可以根据功能、模块或其他逻辑关系进行分组。测试框架提供了一种结构化的方式来组织和管理测试代码。
  4. 测试报告和结果分析 :测试框架通常提供测试结果的报告和分析功能。它可以生成详细的测试报告,显示测试通过或失败的情况,以及测试覆盖率等统计信息。这些报告和统计信息帮助开发人员了解测试的状态和代码的质量。 . 模拟和依赖注入:一些测试框架提供模拟和依赖注入的功能,用于模拟外部依赖或对代码中的依赖进行替换。这使得在测试中可以轻松地模拟数据库、网络请求、文件系统等外部资源,以及对代码的单元进行隔离和测试。
  5. 异步测试支持:许多测试框架提供了对异步代码的支持。它们可以处理异步操作、Promise、回调函数和定时器等情况,以确保在测试中正确处理异步行为。

接下来就列举几个比较常见的前端测试框架:

  1. Jest :Jest 是一个流行的 JavaScript 测试框架,特别适用于前端应用的单元测试和集成测试。它提供了强大的断言库、Mocking 和 spying 功能、快照测试、异步测试支持等特性。 Jest官方文档入口

  2. Mocha :Mocha 是一个灵活的 JavaScript 测试框架,适用于前端应用的单元测试和集成测试。它提供了测试运行器和丰富的插件生态系统,支持多种断言库和报告器,并具有异步测试支持和钩子函数等功能。 mocha 官方入口

  3. Cypress:Cypress 是一个前端端到端(End-to-End)测试框架,专注于模拟用户行为和测试应用的交互性。它提供了可视化测试工具、强大的选择器和断言库,以及实时重新加载和调试功能。

  4. Enzyme:Enzyme 是一个 React 的测试工具集,用于编写和运行 React 组件的单元测试。它提供了一组实用函数和断言库,用于测试组件的渲染、交互和状态变化。

  5. Vue Test Utils:Vue Test Utils 是一个 Vue.js 的官方测试工具库,用于编写和运行 Vue.js 组件的单元测试。它提供了一组工具和 API,用于创建和操作 Vue 组件,以及进行断言和模拟。

【后续将更新------------Jest框架基础使用】

相关推荐
lovingsoft23 分钟前
Chrome Lighthouse 详解
前端·chrome
Qlly33 分钟前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝37 分钟前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦37 分钟前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡1 小时前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95271 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人1 小时前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载1 小时前
用表格模拟甘特图:项目排期的土办法
前端·低代码
葡萄城技术团队2 小时前
用 SpreadJS 数据验证实现省市区三级联动
前端