irpas技术客

前端自动化测试jest_萌萌哒の瑞萌萌

网络 5704

文章目录 持续集成和前端自动化测试前端自动化分类TDD (Test-Driven Development) 测试驱动开发BDD (Behavior Driven Development) 行为驱动开发 前端自动化工具选择端到端测试(E2E)区别工具选择环境搭建断言截屏和视频录制 jest 安装vue-cli 中使用 jestjest基础测试知识jest 文件和目录命名规范测试函数断言函数分组函数常见命令Jest 钩子函数Jest 中的 Mock jest基础测试对象等值测试异步测试定时器测试(异步测试)及断言Dom 测试snapshot 快照测试 Vue 测试安装 unit-jest基础知识hello Jest Vuevm 实例测试事件测试异步操作axios 异步测试

持续集成和前端自动化测试

? 持续集成是互联网软件开发上线流程中的核心一环,自动化测试是持续集成得以实现的核心步骤,缺乏了自动化测试,持续集成自然无从谈起。

? 在日常的开发中,前端错综复杂的变化引发的 bug 往往令开发者头疼,或多或少经历过 修完东墙西墙倒 的经历,此时前端自动化测试就显得非常重要。

? 前端的自动化测试无非也是编写测试用例,在持续集成时执行跑通全部测试用例。如果是一个短平快的小项目,引入前端自动化测试,编写测试用例,无疑只会增加开发成本,然而当项目扩大、迭代频繁、逻辑复杂、需求反复变更的情况下,回归测试的成本是巨额的,自动化测试的优势就能体现出来。

自动化测试的收益 = 迭代次数 * 全手动执行成本 - 首次自动化成本 - 维护次数 * 维护成本

? 尽早引入前端自动化测试不仅能够减少项目 bug 出现概率 (尤其是回归测试中的 bug),还能更好地进行代码组织,增强项目的可维护性,尤其对于工程质量较差的项目,收益是巨大的;如果将其应用于持续集成中,commit 触发自动执行测试脚本,还能大幅提升团队的开发效率。

前端自动化分类

? 单元测试 ? 单元测试,见名知意,可以理解为对系统的某个单元进行测试,而这个单元,可以是某个函数,某个组件,对于这种测试形式来说,我们只关注这个独立的单元的功能是否正常。测试用例以当前单元内的功能作为对象。

? 集成测试 ? 将多个单元集成到一起,进行测试,重点关注各个单元串联起来之后的系统整体功能是否正常。此时的测试用例以多个单元组成的某个独立的系统为对象。

? 前端自动化测试可以按照开发模式分两类:TDD (Test-Driven Development) 测试驱动开发、BDD (Behavior Driven Development) 行为驱动开发。

? 测试还可以按照用例粒度分为 单元测试 (Unit Test)、集成测试 (Integration Test)、端到端测试 (End to End Test)。

TDD (Test-Driven Development) 测试驱动开发

? TDD 顾名思义,开发者根据需求先编写测试用例,再逐步开发,最终满足全部测试用例的需求。

? TDD 的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。

? TDD 的重要目的不仅仅是测试软件,测试工作保证代码质量仅仅是其中一部分,而且是在开发过程中帮助客户和程序员去除模棱两可的需求。TDD 首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。

? 刚开始的时候,只有测试用例,未进行功能开发,执行测试用例,满屏是红色的测试用例不通过提示,随着测试用例被满足变绿,最终全部变绿,功能开发完成,因此前端自动化测试也被叫做 Red-Green Development。

TDD 先写测试再写代码,单位是模块,多用于 单元测试 重点在测试代码,属于 白盒测试 测试内容是模块,速度快,但是忽略模块间依赖,安全感低

? 流程

编写测试用例运行测试,测试用例无法通过测试编写代码,时测试用例通过测试优化代码,完成开发重复上述步骤

? 优势

长期减少回归 bug代码质量更好(组织,可维护性)测试覆盖率高错误测试代码不容易出现 BDD (Behavior Driven Development) 行为驱动开发

? 测试用例模拟用户的操作行为,通常在完成业务代码开发之后,以用户的操作为指导编写测试代码。当测试用例跑通之后,就可以认为系统的整体流程已经流畅。

? BDD 的模式适用于平时的业务代码开发,因为业务的需求有可能变更频繁,但操作流程有可能不会变化,当业务代码发生变化的时候,可以使用原来的测试用例继续跑代码,节省了开发时间。

BDD 先写代码再写测试,测试单位是功能,多用于集成测试 重点在测试 UI(DOM)功能,属于黑盒测试 测试内容是整套操作流程,速度慢,往往需要多个模块配合,安全感高

TDD 开发模式更适用于开发,类似方法函数库,对于数据的处理,对于这种显示组件,更加推荐于BDD 的开发方式,这样既有了测试,也不会增加过多的工作负担,

在平时的项目中,通常使用 TDD 和 BDD 相结合来进行测试,TDD 负责方法类、独立组件的测试。BDD 则负责整体业务模块的测试。

前端自动化工具选择

前端近几年涌现出很多优秀的测试工具:

karma – Google Angular 团队开发的测试运行平台,配置简单灵活,能够很方便在多个真实浏览器中运行测试

mocha – 很优秀的测试框架,有完善的生态系统,简单的测试组织方式,不对断言库和工具做任何限制,非常灵活

jest – facebook 出品的大而全的测试框架,React 官方推荐的单元测试框架,配置简单运行速度快

还有很多其他的前端测试框架,但大同小异,无非是对断言和测试桩等工具的集成度不同,论成熟度首推 mocha,论效率首推 jest。

jest 是 Facebook 开源的 JavaScript 测试框架,它自动集成了断言、JsDom、覆盖率报告等开发者所需要的所有测试工具,是一款几乎零配置的测试框架,而且速度很快,此处选择 jest 作为测试工具。

- Jest测试框架优点

? 比较新:喜新厌旧是人的天性,作为一个程序员,你更要有拥抱全新知识的态度。绝不能固步自封,顽固不化。

? 基础很好:框架基础好就是性能好、功能多、简单易用,Jest在这三个方面你可以完全放心。

? 速度快: 单独模块测试功能,比如说有两个模块A和B,以前都测试过了,这时候你只改动A模块,再次测试,模块B不会再跑一次,而是直接测试A模块。

API简单 :等你基础知识学完后,你就会发现API非常简单,数量也少。

? 隔离性好:Jest里会有很多的测试文件等待我们使用,Jest的执行环境都是隔离,这样就避免不同的测试文件执行的时候互相影响而造成出错。

IDE整合:Jest直接可以和很多编辑器(VSCode)进行融合,让测试变的更加简单。

? 多项目并行:比如我们写了Node.js的后台项目,用React写了一个前台项目,Jest是支持他们并行运行,让我们的效率更加提高了。

? 快出覆盖率:(测试代码覆盖率) 对于一个项目的测试都要出覆盖率的,Jest就可以快速出这样的覆盖率统计结果,非常好用。

端到端测试(E2E) 区别

在 jest 单元测试中使用快照、API-mock 和 DOM 样式状态断言已经能够实现基础的 UI 测试,但是单元测试属于白盒测试,更关注数据的流动,而端到端测试 (End To End Test) 属于黑盒测试,更关注操作结果的展示,因此测试效果自然不同。端到端测试更贴近真实用户操作,页面运行在真实的浏览器环境中,因此端到端测试是从用户角度出发的测试。

工具选择

端到端测试的工具也有不少,最为突出的是老牌 e2e 测试工具 NightWatch,根据需要安装 Selenium 或其他 Webdriver,优势是可以测试多类浏览器,兼容性好,而 Cypress 是为现代网络打造的下一代前端测试工具,安装更简单,可以测试任何在浏览器中运行的内容,测试执行效率更高,此处选用 Cypress 作为端到端测试工具。

就像官网所说,Cypress 就像一个完整的烘烤箱,他还自带电池,下面是一些其它测试框架无法做到的事情:

时间旅行: Cypress 在你运行测试的时候拍摄快照。 只要将鼠标悬停在 命令日志 上就能够清楚的了解到每一步发生了什么。 可调式能力: 你再也不需要去猜测测试为什么失败了。 调试工具 和 Chrome 的调试工具差不多。 清晰的错误原因和堆栈跟踪让调试能够更加快速。 自动等待: 在你的测试中不再需要添加等待或睡眠函数了。在执行下一条命令或断言前 Cypress 会 自动等待 异步将不再是问题. Spies, Stubs, and Clocks: 验证和 控制 函数、服务器响应或者计时器的行为。你喜欢的单元测试的功能都掌握在你的手中。 网络流量控制: 非常容易的进行 控制、保存和边缘测试,而这并不需要涉及到你的服务。你可以根据需要保留网络流量。 一致的结果: 架构不需要 Selenium 或者 WebDriver。向快速,一致和可靠的无侵入测试看齐。 屏幕截图和视频: 可以查看测试失败时候系统自动截取的图片,或者整个测试的录制视频。

环境搭建

安装非常简单:

$ npm install cypress --save-dev

配置文件修改:

// baseUrl: "http://localhost:8080", // 测试域名 fixturesFolder: 'tests/e2e/fixtures', // 外部静态数据,如网络请求或存放模拟上传或读取的文件 integrationFolder: 'tests/e2e/specs', // 测试用例文件夹 screenshotsFolder: 'tests/e2e/screenshots', // 屏幕快照 // videoRecording: true, videosFolder: 'tests/e2e/videos', // 录制后的文件夹 supportFile: 'tests/e2e/support/index.js', // 配置自定义命令全局注入 viewportHeight: 768, // 测试浏览器视口高度 viewportWidth: 1366 // 测试浏览器视口宽度

然后,可以将命令写到 package.json 中,如果使用 vue-cli,可以看到已经存在 “test:e2e”: “vue-cli-service test:e2e”,直接执行即可启动测试,在这之前需要先启动项目和 mock 服务。

$ npm run test:e2e

?

断言

在 Cypress 中有两种断言写法:

隐式: 使用 .should() 或者 .and(),.and() 只是 .should() 的别名,它链接多个断言使代码更易读 显式: 使用 expect

// 隐式 cy.get('#header a') .should('have.class', 'active') .and('have.attr', 'href', '/users') // 显式 cy.get('tbody tr:first').should(($tr) => { expect($tr).to.have.class('active') expect($tr).to.have.attr('href', '/users') }) // 常用断言 cy.get(':checkbox').should('be.disabled') cy.get('form').should('have.class', 'form-horizontal') cy.get('input').should('not.have.value', 'US') cy.request('/users/1').its('body').should('deep.eq', { name: 'Jane' }) // 默认断言 /* cy.visit() 预期这个页面是状态为200的 text/html内容页 cy.request() 预期远程服务器存在并提供响应 cy.contains() 预期包含内容的元素最终存在于DOM中 cy.get() 预期元素最终存在于 DOM中 .find() 预期元素最终存在于 DOM 中 .type() 预期元素最终为 可输入 状态 .click() 预期元素最终为 可操作 状态 .its() 预期最终找到当前主题的一个属性 截屏和视频录制

屏幕录制截屏是 Cypress 的一大特色,在 Test Runner 中单击项目的 Runs 选项卡,登录账号,再根据提示执行指令,即可完成屏幕录制和自动截屏。

$ ./node_modules/cypress/bin/cypress run --record --key xxxxxxxx

还可以在用例中主动截屏,存储在 screenshots 目录下。

jest 安装

jest 需要自动运行测试脚本,node 环境是必不可少的,如果从头搭建,首先得初始化项目 package.json 并安装 jest:

$ npm init $ npm install jest -D

jest 默认不支持 es6,需要使用 babel 来支持 es6,安装 babel:

$ npm install @babel/core @babel/preset-env -D

配置 babel,修改 .babelrc 文件:

{ "presets": [ ["@babel/preset-env", { "targets": { "node": "current" } }] ] } vue-cli 中使用 jest

? 现实项目中,往往不会从零搭建 jest 项目,更多的情况是,需要在一个脚手架已经搭建好的项目中引入自动化测试,此处在 vue-cli 基础上修改 jest 配置,安装好 jest 后需要修改项目根目录下的配置文件 jest.config.js,重点关注 testMatch 和 testPathIgnorePatterns 两个属性,testMatch 指定了匹配的测试用例文件的路径,而 testPathIgnorePatterns 则可以忽略指定文件,因此使用两个属性可以精确匹配到项目中所有的测试用例。

module.exports = { moduleFileExtensions: [ 'js', 'jsx', 'json', 'vue' ], transform: { '^.+\\.vue$': 'vue-jest', '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', '^.+\\.jsx?$': 'babel-jest' }, collectCoverageFrom: ['**/*.{vue}', '!**/node_modules/**'], transformIgnorePatterns: [ '/node_modules/' ], moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1' }, snapshotSerializers: [ 'jest-serializer-vue' ], testMatch: [ '**/__tests__/unit/*.test.(js|jsx|ts|tsx)' ], testPathIgnorePatterns: [ '/.eslintrc/.js' ], testURL: 'http://localhost/', watchPlugins: [ 'jest-watch-typeahead/filename', 'jest-watch-typeahead/testname' ] }

最后还需要在 package.json 中添加测试指令

{ "test:unit": "vue-cli-service test:unit --watch" }

执行对应指令即可在项目中执行测试

$ npm run test:unit

项目目录结构 项目的目录结构组织如下:

├── src │ ├── assets │ ├── containers │ │ └── TodoList │ │ ├── __mocks__ 测试mocks文件 │ │ ├── __tests__ 测试用例文件 │ │ │ ├── unit 单元测试 │ │ │ │ └── TodoList.test.js │ │ │ └── integration 集成测试 │ │ │ └── store.test.js │ │ ├── components 子组件 │ │ │ ├── Header.vue │ │ │ └── UndoList.vue │ │ │ │ │ └── TodoList.vue TodoList父vue组件 │ │ │ ├── utils │ │ └── testUtils.js 存放测试工具公共工具 │ ├── App.vue vue-App │ └── main.js 入口文件 │ ├── public ├── jest.config.js jest配置文件 ├── ... └── package.json jest基础测试知识 jest 文件和目录命名规范

待测试文件: hello.js 测试脚本文件取名:hello.test.jsorhello.spec.js 测试目录:testsor__tests__

测试函数 test("测试用列描述信息",()=>{ }) // or it("测试用例描述信息",()=>{ }) 断言函数

测试即运行结果是否与我们预期结果一致 断言函数用来验证结果是否正确

exspect(运行结果).toBe(期望的结果); //常见断言方法 expect({a:1}).toBe({a:1})//判断两个对象是否相等 expect(1).not.toBe(2)//判断不等 expect({ a: 1, foo: { b: 2 } }).toEqual({ a: 1, foo: { b: 2 } }) expect(n).toBeNull(); //判断是否为null expect(n).toBeUndefined(); //判断是否为undefined expect(n).toBeDefined(); //判断结果与toBeUndefined相反 expect(n).toBeTruthy(); //判断结果为true expect(n).toBeFalsy(); //判断结果为false expect(value).toBeGreaterThan(3); //大于3 expect(value).toBeGreaterThanOrEqual(3.5); //大于等于3.5 expect(value).toBeLessThan(5); //小于5 expect(value).toBeLessThanOrEqual(4.5); //小于等于4.5 expect(value).toBeCloseTo(0.3); // 浮点数判断相等 expect('Christoph').toMatch(/stop/); //正则表达式判断 expect(['one','two']).toContain('one'); //不解释 分组函数 describe("关于每个功能或某个组件的单元测试",()=>{ // 不同用例的单元测试 }) 常见命令 { "nocache": "jest --no-cache", //清除缓存 "watch": "jest --watchAll", //实时监听 "coverage": "jest --coverage", //生成覆盖测试文档 "verbose": "npx jest --verbose" //显示测试描述 } Jest 钩子函数

beforeAll:在所有测试用例执行前调用

afterAll:在所有测试用例执行后调用

beforeEach:在每一个测试用例执行前调用

afterEach:在每一个测试用例执行后调用

describe: 分组测试

每个describe都有自己的作用域且互不影响。

对于其执行的逻辑一定要放在钩子函数中

Jest 中的 Mock

生成mock函数

const func = jest.fn()

mock 函数作用

1、 捕获函数的调用和返回结果,以及this和调用顺序

2、 可以让我们自由的设置返回结果

3、 改变函数的内部实现

API:

mockReturnValue

mockReturnValueOnce

mockImplementation

mockImplementationOnce

mockResolvedValue

mockResolvedValueOnce

mockReturnThis

jest.mock 发现 util 是一个类,会自动把类的构造函数和方法变成 jest.fn()

mock的输出格式

对于单元测试,外部 class 的实现无需关心,使用 jest.fn 生成一个 mock 类,例如测试 mock.js

输出的 mock 为:

{ calls: [ [ 123 ], [ 123 ], [ 123 ] ], instances: [ undefined, undefined, undefined ], invocationCallOrder: [ 1, 2, 3 ], results: [ { type: 'return', value: 456 }, { type: 'return', value: 789 }, { type: 'return', value: undefined } ] } jest基础测试 对象等值测试 describe('对象测试', () => { it("是否同一个对象", () => { const foo = { a: 1 } expect(foo).toBe(foo) }) it("对象值是否相等", () => { expect({ a: 1, foo: { b: 2 } }).toEqual({ a: 1, foo: { b: 2 } }) }) test('对象赋值', () => { const data = { one: 1 }; data['two'] = 2; expect(data).toEqual({ one: 1, two: 2 }); }); }); 异步测试

异步测试脚本执行完,单元测试就结束了,如果需要延时才能断言的结果,单元测试函数需要设置 done 形参,在定时回调函数中调用,显示的通过单元测试已完成。

describe('异步操作测试', () => { function foo(callback) { console.log('foo...') setTimeout(() => { callback && callback(); }, 1000) } it('异步测试', (done) => { function bar() { console.log('bar..') done(); } foo(bar); }); }); 定时器测试(异步测试)及断言

基于 jest 提供的两个方法 jest.useFakeTimers 和 jest.runAllTimers 可以更优雅的对延时功能的测试。

jest.useFakeTimers()避免定时器等待时间

jest.runAllTimers() 执行所有的timers

jest.runOnlyPendingTimers() 只执行当前队列中的timers

jest.advanceTimersByTime(msToRun) 时间快进多少

describe('定时器相关测试', () => { // 开启定时函数模拟 jest.useFakeTimers(); function foo(callback) { console.log('foo...') setTimeout(() => { callback && callback(); }, 1000) } it('断言异步测试', () => { //创建mock函数,用于断言函数被执行或是执行次数的判断 const callback = jest.fn(); foo(callback); expect(callback).not.toBeCalled(); //快进,使所有定时器回调 jest.runAllTimers(); expect(callback).toBeCalled(); }) }); Dom 测试

测试 DOM 要记得把测试环境设为浏览器环境,jest 在底层模拟了一套 dom api

jest 提供了一套 node 环境下的 dom,在获取到指定的 dom 元素后,可以对 dom 元素执行各种操作:

const input = findTestWrapper(wrapper, ‘input’) input.exists() // 获取dom存在性 input.setValue(‘csxiaoyao’) // 给dom赋值 input.trigger(‘keyup.enter’) // 触发dom方法 input.trigger(‘change’) // 触发dom方法

实现 dom 渲染测试,以及点击事件等交互功能测试。

describe('Dom测试', () => { it('测试按钮是否被渲染 ', () => { document.body.innerHTML = ` <div> <button id='btn'>小按钮</button> </div> ` console.log(document.getElementById('btn'), document.getElementById('btn').toString()) expect(document.getElementById('btn')).not.toBeNull(); expect(document.getElementById('btn').toString()).toBe("[object HTMLButtonElement]"); }); it('测试点击事件', () => { const onclick = jest.fn(); document.body.innerHTML = ` <div> <button id='btn'>小按钮</button> </div> ` const btn = document.getElementById('btn'); expect(onclick).not.toBeCalled(); btn.onclick = onclick; btn.click(); expect(onclick).toBeCalled(); expect(onclick).toHaveBeenCalledTimes(1); btn.click(); btn.click(); expect(onclick).toHaveBeenCalledTimes(3); }); }); snapshot 快照测试

toMatchSnapshot 生成快照文件夹__snapshots__

toMatchInlineSnapshot 行内快照

对于变化的配置量 Snapshot({ time2: expect.any(Date)})

同样可以接收 Date | String | Number

test('should generateAnotherConfig 函数', () => { expect(generateAnotherConfig()).toMatchSnapshot({ time2: expect.any(Date) }) }) Vue 测试 安装 unit-jest

? 如果创建的项目没有安装 unit-jest 依赖包,可以通过 vue add @vue/unit-jest 命令添加。否则通过脚手架手动模式创建一个包含 unit-jest 的项目。

基础知识 import { mount, shallowMount } from '@vue/test-utils’

不同的是,mount 方法会渲染完整的组件,包括子组件,适合 BDD 和集成测试,而 shallowMount 方法只会渲染当前组件,因此速度更快,效率更高,更加适合 TDD 和单元测试。

mount 和 shallowMount 的区别 - shallowMount 只挂载指定组件,不挂载子组件 - mount 挂载所有组件

为了方便获取测试需要的 DOM 元素,可以将获取 DOM 元素的方法进行封装,在 testUtils.js 中定义 findTestWrapper 方法如下:

export const findTestWrapper = (wrapper, tag) => { return wrapper.find(`[data-test="${tag}"]`) }

Vue 的渲染机制 默认情况下 Vue 会异步地批量执行更新 (在下一轮 tick),以避免不必要的 DOM 重绘或者是观察者计算

异步测试需要在 nextTick () 之后执行

hello Jest Vue

vue 组件渲染测试

it('挂载countBtn组件', () => { const wraper = shallowMount(CountBtn); const btn = wraper.find("button"); expect(wraper.html()).toBe(`<button>点击次数0</button>`); }); vm 实例测试

大部分的自动化测试,都是通过 vm 实例上的 data 变化来测试的,可以获取对应的 data 值,也可以通过 vm 调用相关方法。

wrapper.vm. d a t a . i n p u t V a l u e / / 获 取 i n p u t V a l u e w r a p p e r . v m . a d d U n d o I t e m ( ′ c s x i a o y a o ′ ) / / 执 行 a d d U n d o I t e m 方 法 w r a p p e r . v m . data.inputValue // 获取 inputValue wrapper.vm.addUndoItem('csxiaoyao') // 执行 addUndoItem 方法 wrapper.vm. data.inputValue//获取inputValuewrapper.vm.addUndoItem(′csxiaoyao′)//执行addUndoItem方法wrapper.vm.emit(‘add’, content) // 触发外部 add 方法

事件测试

vue 组件点击事件测试

it('测试countBtn组件点击', (done) => { const wraper = shallowMount(CountBtn); const btn = wraper.find("button"); expect(wraper.html()).toBe(`<button>点击次数0</button>`); btn.trigger('click'); setTimeout(() => { expect(wraper.html()).toBe(`<button>点击次数1</button>`); done(); }, 1000); }); it('优雅的测试点击事件', async () => { const wraper = shallowMount(CountBtn); const btn = wraper.find("button"); expect(wraper.html()).toBe(`<button>点击次数0</button>`); btn.trigger('click'); await wraper.vm.$nextTick(); expect(wraper.html()).toBe(`<button>点击次数1</button>`); }); 异步操作

定时器测试,可以借助 vm.$nextTick 方法和 jest 定时器操作实现

beforeEach(() => { jest.useFakeTimers() }) it(` 1. 用户进入页面时,等待 3s 2. 列表应该展示远程返回的数据 `, (done) => { const wrapper = mount(TodoList, { store }) // 传入 store jest.runAllTimers() wrapper.vm.$nextTick(() => { const listItems = findTestWrapper(wrapper, 'list-item') // 不能直接判断,因为异步操作在 mounted 之后 expect(listItems.length).toBe(2) done() }) }) axios 异步测试

本地去模拟axios请求

实现方法

1.直接 使用创建的 __mock__ 模拟

2.打开jest.config.js Line 6 automock: true

模拟异步请示,测试渲染结果是否一致

<!-- User.vue --> <template> <table> <tr v-for="item in list" :key="item.id"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.age}}</td> </tr> </table> </template> <script> export default { data() { return { list: [] } }, created() { this.$http.get('/user').then(({ data }) => { this.list = data }) } } </script> // User.spec.js import { mount } from '@vue/test-utils'; import User from '@/components/User'; it('测试用户组件', async() => { const wrapper = mount(User,{ mocks:{ $http:{ get: url=>Promise.resolve({data:[{id:1,name:'xxxx',age:18},{id:2,name:'yyyy',age:19}]}) } } }) console.log(wrapper.html()) // 渲染前 expect(wrapper.html()).toBe('<table></table>'); //对于异步请求,可以使用 vue 的 vm.$nextTick 方法实现异步数据的渲染。 await wrapper.vm.$nextTick(); // 渲染后 // console.log(wrapper.html()) // console.log(wrapper.find('tr')) expect(wrapper.findAll('tr').length).toBe(2) expect(wrapper.findAll('td').at(2).html()).toBe('<td>18</td>') });


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #前端自动化测试 #BUG #往往令开发者头疼或多或少经历过 #修完东墙西墙倒