得益于最近项目上使用了jest+puppeteer来进行前端自动化,有机会进行边实践变学习,并整理出一些相关的知识,可供对此感兴趣的人儿们参考,如有出入,欢迎指正~
在整理之前,我给自己提出了以下几个问题
1、jest是什么?
2、为什么要用jest?
3、jest+puppeteer怎么使用?(在jest中把jest+puppeteer搭起来)
4、jest和puppeteer怎么结合?(分工?)
1、jest是什么?
由 Facebook 推出的一套开源的 JavaScript 测试框架,具有许多非常好的特性,譬如执行速度快、API友好、自动监控、Snapshot、测试覆盖率、Mock等各种特性,并且适用于Babel、TypeScript、Node、React、Angular、Vue等。
2、自动化:
前端:jest+puppeteer,cypress,selenium
后端:rest-assured, testNG
在这里没有探究具体的对比,大多数情况下,可能会结合项目实际情况看使用哪个更合适。
3、在jest框架中,把jest+puppeteer搭起来
(1)项目的前端小伙伴可能会用jest写他们自动的单元测试的用例,因此最好单独建立一个文件夹放e2e的测试,并在里面添加jest.config.js文件。
(2)在项目的package.json中添加跑e2e用例的命令
"scripts": {
"e2e-test": "jest --config test/jest.config.js"
},
(3)若项目内没有装puppeteer,先装puppeteer
npm i puppeteer
# or "yarn add puppeteer"
确认项目package.json里有
(可以不用puppeteer-core)
(4)安装jest-puppeteer
yarn add --dev jest-puppeteer
# or "npm install --save-dev jest-puppeteer"
or
# for jest 22~23
npm install --save-dev jest-puppeteer@3.9.0 puppeteer jest
# for jest 24+
npm install --save-dev jest-puppeteer puppeteer jest
Requires Jest v22+ TypeScript users should additionally install
@types/puppeteer,
@types/jest-environment-puppeteer,
@types/expect-puppeteer
(5)update your Jest configuration:(在test/jest.config.js内)
{
"preset": "jest-puppeteer"
}
(6)其他配置:Configure Puppeteer。在项目文件夹下添加jest-puppeteer.config.js
// jest-puppeteer.config.js
module.exports = {
launch: {
dumpio: true,
headless: process.env.HEADLESS !== 'false',
},
browserContext: 'default',
}
browserContext : By default, the browser context (cookies, localStorage, etc) is shared between all tests. The following options are available for browserContext:
default Each test starts a tab, so all tests share the same context.
incognito Each tests starts an incognito window, so all tests have a separate, isolated context. Useful when running tests that could interfere with one another. (Example: testing multiple users on the same app at once with login, transactions, etc.)
headless: 若想在跑用例是关闭headless状态,可以使用命令 HEADLESS=false npm run e2e-test
defaultViewport: 设置浏览器分辨率
server :Server options allowed by jest-dev-server
dumpio: true,据说设置为true可以解决多开页面会卡死的问题,但具体是做什么,不得而知
(7)其他配置:Configure ESLint
Jest Puppeteer exposes three new globals: browser, page, context. If you want to avoid errors, you can add them to your .eslintrc.js:
// .eslintrc.js
module.exports = {
env: {
jest: true,
},
globals: {
page: true,
browser: true,
context: true,
jestPuppeteer: true,
},
}
到这里可以试着运行脚本看是否成功(创建文件“google.jest.ts”在test文件夹下面):
describe('Google', () => {
beforeAll(async () => {
await page.goto('https://google.com')
})
it('should display "google" text on page', async () => {
await expect(page).toMatch('google')
})
})
遇到的坑:
坑1、error:Plugin/Preset files are not allowed to export objects, only functions.
原因: babel 的版本冲突,多是因为你的 babel 依赖包不兼容。在package.json内有6.0的版本也有7.0的版本
解决:把所有的包升级到7.0
方法一:你不妨把 node_modules 删掉,重新 install ,这样就可以处理一部分兼容问题(但是并没有解决我的问题。。。)
方法二:手动一个一个更改版本,然后升级
坑2、"TypeError: _asyncToGenerator is not a function"
解决办法:删除./babelrc文件就好了(黑人问号脸,不知道为什么)
(8)安装 jest-image-snapshot
npm i --save-dev jest-image-snapshot
should additionally install @types/jest-image-snapshot
在test下添加setup.ts文件,将imagesnapshot配置进去
require("expect-puppeteer");
const { toMatchImageSnapshot } = require("jest-image-snapshot");
jest.setTimeout(50000);
expect.extend({ toMatchImageSnapshot });
并在test/jest.config.ts内将setup文件路径放进去
setupFilesAfterEnv: ["<rootDir>/setup.ts"],
到这里就可以尝试使用toMatchImageSnapshot()啦
describe('Google', () => {
beforeAll(async () => {
await page.goto('https://google.com');
});
it('should be titled "Google"', async () => {
const image = await page.screenshot();
return expect(image).toMatchImageSnapshot();
});
});
生成的图片和diff_output会放在_image_snapshots_内
#其他关于jest.config.ts的设置
testRegex :定义哪些是需要跑的用例
moduleNameMapper :从正则表达式到模块名称的映射,该模块名称允许将资源(例如图像或样式)存入一个模块。(未添加它时在一个describe里存多个图片失败了?)
moduleFileExtensions : An array of file extensions your modules use. If you require modules without specifying a file extension, these are the extensions Jest will look for, in left-to-right order.
4、jest和puppeteer怎么结合?(职责划分)
- jest提供测试框架:
import { Google } from "../../pages/Google";
describe("Google test", () => {
let homePage: Google;
beforeAll(() => {
homePage = new Google(page);
});
it("google page", async () => {
xxx...
xxx...
xxx...
});
});
- 在jest内运行puppeteer:安装jest-puppeteer
(可在jest-puppeteer可对puppeteer进行相关的配置,比如浏览器大小、launch、headless等)
- puppeteer进行具体操作:
//const browser = await puppeteer.launch();
//const page = await browser.newPage();
page.goto('https://example.com');
page.waitForSelector('[aria-label="main-content"]');
page.click(selector);
page.waitFor(500);
page.type(incidentSummarySelector, "incident summary");
page.screenshot();
//page.pdf({path: 'hn.pdf', format: 'A4'});
puppeteer API: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#
- 图像对比jest-image-snapshot:
expect(image).toMatchImageSnapshot();