Cypress Web Automate Test

背景

最近项目越来越多, 测试压力也增大了, 于是酝酿很久的自动化测试也提上议程了.

框架选择

常见的项目脚手架中其实应该都自带了测试框架, 一般直接使用npm test脚本, 内置的往往是jest框架, 但是用的人却很少, 归根结底是不方便开发, 项目中的组件不是单一的, 页面逻辑也很复杂, 出bug的往往涉及到后端接口. 单独针对某个组件的测试确实意义不大, 所以调研后选择使用cypress框架, 来实现真正的模拟用户场景的端到端测试.

cypress

原理

cypress通过调用chrome并模拟用户行为, 这意味着所有在开发中能使用到的chrome的功能, 在开发测试用例的时候都能用上, 包括脚本断点/网络请求/浏览器状态等, 这对测试开发是十分重要的

安装

cypress提供create-react-app的支持版, 但实际上是依赖侵入性修改的, 实际上直接使用通用的安装方式更好

1
2
cd /home/project/
npm install -D cypress

虽然我们将cypress安装在当前项目下, 但cypress实际上还是在全局安装了它自己的chrome和调用方式, 方便多个项目共享.

启动

可以修改package.json里加上script.cypress-open: "cypress open"来启动cypress, 也可以直接使用npx来启动

1
npx cypress open

第一次启动时, 会提示首次运行, 然后初始化cypress/文件夹到项目目录下, 并生成cypress.json文件, 以后相关配置只需要修改这两块内容, 最后会自动打开cypress控制台, 可以看到里面自带的一些写好的测试用例demo. 点击某个spec.js后, 就会自动打开浏览器, 运行测试脚本了.

ts支持

准备好环境后, 就来开发第一个测试脚本, 一开始就碰见了问题:

按官方实例开发一个app.spec.js后, eslint提示'cy' is not defined.eslintno-undef不存在

查了下文档, 发现cypress也有完善的typescript支持, 只需要配置一下即可

首先修改app.spec.js后缀为ts, 然后在cypress目录下添加tsconfig.json文件

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"types": ["cypress", "../node_modules/@types/node"]
},
"include": ["**/*.ts"]
}
1
2
3
4
5
6
// app.spec.ts
describe('First Test', () => {
it('Visit the app', () => {
cy.visit('/');
});
});

完成后, 就可以很轻松的使用typescript来开发了

覆盖率报告

一般使用jest的项目能使用npm run test -- --coverage生成覆盖率报告, 在cypress中同样也有相关功能, 直接参考官方文档配置即可

在开发这块时突然很好奇是如何在浏览器中生成原始代码覆盖率的, 查了Istanbul的工作原理后, 发现它实际上是在编译时注入运行次数信息实现收集的
      
function App() {
  cov_26lgl7ul30().f[0]++;
  cov_26lgl7ul30().s[0]++;
  return /*#__PURE__*/(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
  })
}
      
    

babel-plugin-istanbul

既然是编译时注入的, 那就需要babel插件了, 注意只有在非生产环境下才需要加上这个插件

1
2
3
4
// npm i -D babel-plugin-istanbul
if (!isEnvProduction) {
config = addBabelPlugin(['istanbul'])(config);
}

cypress-plugin

此处直接按照文档内容配置

1
2
3
4
5
6
7
8
9
// cypress/plugins/index.js
module.exports = (on, config) => {
require('@cypress/code-coverage/task')(on, config);
// include any other plugin code...

// It's IMPORTANT to return the config object
// with any changed environment variables
return config;
};
1
2
// cypress/support/index.js
import '@cypress/code-coverage/support';

生成覆盖率报告

插件配置完成后, 运行一次测试用例, 就可以在coverage文件夹下看到html版的覆盖率报告了. 如果需要文本格式的报告, 可以使用npx nyc report --reporter=text-summary生成

全链路覆盖率

cypress可以实现从后端到前端同时收集覆盖率并合并到同一个报告中, 在某些独立项目中其实也是很有意义的, 可以参考官方例子

测试用例

鉴权

内部系统测试往往要鉴权, 下策是用自己的账号密码登录, 上策是直接获取测试账号token写入cookie即可

1
2
3
4
5
6
7
describe('Web Test', () => {
it('Visit Web', () => {
cy.setCookie('TOKEN', 'my-token');
cy.visit('/');
cy.get('.App-header .ant-btn').children().first().should('have.text', 'Ant Design').invoke('prop', 'tagName').should('be.equal', 'SPAN');
});
});

url跳转

某些操作后需要检测url是否生效和一致, 可以使用url()来检测

1
cy.url().should('include', '/index');

其他

最后在ci中配上npm start &npx cypress run, 就可以实现全流程自动化测试了. 虽然由于时间关系只覆盖了最重要的几个页面和组件, 但是框架已经搭建完成, 后续在开发业务的时候都能同步开发测试内容了

作者

Mosby

发布于

2021-06-28

许可协议

评论