用 jest + gitlab-ci 搭建前端UI自动化测试环境
前言
下面以 github创建仓库为例 测试领域中比较麻烦的就是前端UI测试
gitlab地址: gitlab.com/yunqiangwu/…
前置要求
- 拥有gitlab账号(公司内部的也可以)
- gitlab 已经配置了 CI Runner(具体方法百度)
功能实现效果
- 修改过测试用例后push触发自动测试
- 测试完成后生成测试报告
- 测试报告部署到 git pages 上
- 发送邮件通知测试结果,以及报告查看链接
先看下我在实际项目中的效果,下面是我收到的自动化测试完成后的邮件:
预览地址
自动化测试报告
测试覆盖率报告
创建项目
mkdir devops-test
cd devops-test
npm init # 初始化 `node` 项目
# 这里会要你输入信息,节约时间,一路回车
# 下面的操作我用的是cnpm
cnpm i jest jest-report nightmare --save
cnpm i babel-jest babel-plugin-import babel-plugin-transform-class-properties babel-plugin-transform-decorators-legacy babel-plugin-transform-runtime
babel-preset-env --save-dev
#
重点依赖库介绍:
- jest 测试框架
- nightmare 浏览器运行库
- jest-report 测试报告生产库
配置jest环境
-
在
package.json
的scripts
中叫如 test 命令{ "name": "devops-test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "jest e2e.js" }, "author": "", // ... }
-
创建
jasmine
配置文件项目根目录/tests/jasmine.js
配置测试超时时间jasmine.DEFAULT_TIMEOUT_INTERVAL = 12000; // 只有这一行内容
-
在
package.json
中添加两个字段babel
和jest
,这样就能跑 es6 的代码{ "name": "devops-test", "version": "1.0.0", // ... "babel": { "presets": [ "env" ], "plugins": [ "transform-decorators-legacy", "transform-class-properties", "transform-es2015-destructuring" ] }, "jest": { "testResultsProcessor": "jest-report", "setupTestFrameworkScriptFile": "<rootDir>/tests/jasmine.js", "testMatch": [ "**/?(*.)(spec|test|e2e).js?(x)" ] }, // ... }
编写测试用例
测试github
登录功能<rootDir>/src/e2e/test-github-login.e2e.js
import Nightmare from 'nightmare';
import { helperBuilder } from 'jest-report';
describe('Login', () => {
let page;
beforeEach(() => {
page = Nightmare({ show: true }).viewport(1024, 768);
page.goto('https://github.com/login');
});
// afterEach(() => {
// if(page){
// page.halt();
// page = null;
// }
// });
it('should login with failure', async() => {
const reportHelper = helperBuilder('Login', 'should login with failure');
reportHelper.monitorPage(page);
await page
.type('#login_field', 'mockuser')
.type('#password', 'wrong_password')
.click('input[type="submit"]')
.wait('#js-flash-container > div > div'); // should display error
await page.screenshot(reportHelper.genPicturePath());
const text = await page.wait('#js-flash-container > div > div')
.evaluate(() => document.body.innerText)
.end();
await page.end();
expect(text).toContain('Incorrect username or password');
});
it('should login successfully', async() => {
const reportHelper = helperBuilder('Login', 'should login successfully');
reportHelper.monitorPage(page);
await page
.type('#login_field', '正确用户名')
.type('#password', '正确密码')
.click('input[type="submit"]')
.wait('#your_repos > div > div.boxed-group-action > a'); // should display error
await page.screenshot(reportHelper.genPicturePath());
const title = await page
.evaluate(() => document.title)
.end();
await page.end();
expect(title).toBe('GitHub');
});
});
运行测试生成测试报告
1. 执行命令npm test
,运行测试脚步
2. 生成测试报告
生成的文件路径默认是 `<rootDir>/dist/test-report`
3. 测试报告效果
添加项目到gitlab
git init
git remote add origin https://gitlab.com/yunqiangwu/devops-test.git
git add .
git commit -m "Initial commit"
git push -u origin master
添加到持续集成
自动部署测试报告 到gitlab pages 网页
cnpm i --save-dev gh-pages
在 package.json
添加scripts
"scripts": {
"test": "jest e2e.js",
"site": "gh-pages -d dist"
},
配置邮件通知工具
<rootDir>/tool/emailnotice.sh
#!/bin/bash
MAIL_FROM='supportman@yeah.net'
# [[ $MAIL_TO == "" ]] && export MAIL_TO=$1
MAIL_TO_ARR_ARG=$1
MAIL_SUBJECT=$2
shift 2
MAIL_CONTENT=$*
MAIL_CONTENT_FILE="/tmp/`/bin/date +%s`.txt"
MAIL_SMTP='smtp://smtp.yeah.net'
MAIL_USER='supportman@yeah.net'
MAIL_PASSWORD='wu950429'
OLD_IFS="$IFS"
#设置分隔符
IFS=","
MAIL_TO_ARR=($MAIL_TO_ARR_ARG)
IFS="$OLD_IFS"
split_1()
{
MAIL_TO=$1
echo "发送邮件到:"$1
# return 0;
# create mail content file
echo "From:${MAIL_FROM}
To:$MAIL_TO
Subject: $MAIL_SUBJECT
$MAIL_CONTENT
"> ${MAIL_CONTENT_FILE}
# send mail
curl -s --url "${MAIL_SMTP}" --mail-from "${MAIL_FROM}" --mail-rcpt ${MAIL_TO} --upload-file ${MAIL_CONTENT_FILE} --user "${MAIL_USER}:${MAIL_PASSWORD}"
}
for s in ${MAIL_TO_ARR[@]}
do
split_1 "$s"
done
rm -rf ${MAIL_CONTENT_FILE}
gitlab-ci.yml 配置文件 .gitlab-ci.yml
image: jonneywu/node-xvfb-cnpm
cache:
key: "$CI_REPOSITORY_URL"
paths:
- node_modules
- dist
stages:
- test
- email
test:
script:
- if [ ! -d node_modules ]; then cnpm i; fi
- if [ ! -d node_modules/nightmare ]; then cnpm i nightmare; fi
- export DISPLAY=':99.0'
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
- npm run test && echo test FAIL
- kill -9 `ps -ef | grep Xvfb| grep -v grep|awk '{print $2}'`
- npm run site
stage: test
only:
- master
artifacts:
paths:
- dist
email:
script:
- echo email
- if [[ ! -n $MAIL_TO ]]; then export MAIL_TO=842269153@qq.com,yunqiang.wu@hand-china.com ; fi
- export root_url=http://`cat CNAME`
- export test_passed_rate=$(printf "%.2f" `cat dist/test-report/testResultData.json | jq '100*.numPassedTests/.numTotalTests'`)%
- bash ./tool/emailnotice.sh $MAIL_TO '前端自动化测试' `echo -e " 测试分支: ${CI_COMMIT_REF_NAME} \r\n 提交人:${GITLAB_USER_NAME} \r\n 测试通过率:${test_passed_rate} \r\n 触发来源:${CI_PIPELINE_SOURCE} \r\n 测试环境:mockApi环境 \r\n\r\n预览地址: ${root_url}/index.html \r\n 自动化测试报告:${root_url}/test-report/reporter.html \r\n 测试覆盖率报告: ${root_url}/coverage/lcov-report/index.html \r\n"`
stage: email
only:
- master
artifacts:
paths:
- dist
注意事项
- react 开发是如果用了
css modules
的技术开发时,会把 class 名换掉 ,测试框架就无法通过css selector
找到并操作 Dom元素,在开发时,可以为主要控制的dom节点给id
,data-custom
自定义属性,比如用户名输入框、登录按钮, - 我这里的介绍的自动化测试,只是测试系统的功能交互是否能正常,如果需要靠自动化测试来判断UI界面的样式对比是符合要求,可能还是要靠人力测试,不过测试的目的保证系统功能成正常使用不出BUG。