一、背景
经过前期对e2e(端到端)测试框架的调研,最终确定选择使用Cypress
。
在经过2-3天的踩坑实践,终于成功将e2e测试流程集成到项目的gitlab CI
中。
现对这几天遇到的问题做一次总结。
一来可以借此反思并精进,自己在整个过程中排查和解决问题的思路方法,二来也可以作为组内e2e测试项目的实践经验供其他同学参考。
二、实践过程
2.1、Cypress安装
参考Crpress的官网(www.cypress.io),执行yarn add cypress
对Cypress
进行安装。整个安装过程很顺利。
arduino
yarn add cypress // 安装成功后执行下面一句
yarn cypress open
执行yarn cypress open
会自动打开Cypress 程序:
在调研文档里,我曾说过,Cypress
既可以做e2e测试,也可以做单元、集成测试。
这里,我们选择第一个选项: E2E Testing。
因为我们当前还没有写测试用例,点击 E2E Testing,提示需要在我们的项目中增加以下文件:(主要帮我们生成Cypress
目录,以及配置文件)。
点击continue,会在我们项目中生成Cypress
目录,并将这些文件加入到Cypress
中。
接下来,我们按照官方文档,写了一个测试用例,用来检查,Cypress
能否正常工作。
我们在Cypress
的目录e2e下新建文件:App.cy.js
scss
describe('e2e start', () => {
it('e2e test should start', () => {
expect(true).to.equal(true);
});
});
我们执行yarn cypress open
, 提示选择浏览器,选择第一个Chrome。
后面的操作也很简单,点击按钮,再点击对应的测试文件,可以看到,运行成功。
至此已经验证Cypress
可以正常工作。
那么问题来了,Cypress
每次运行测试用例都要弹出应用程序跑吗,那么怎么集成到CI
中呢。
接下来验证Cypress
另一种方式:Headless
,运行测试用例。
终端执行 cypress run
,结果如下:
以上,是Cypress
安装以及验证两种方式运行测试用例,貌似一切都很顺利。
2.2、Cypress CI 集成
既然本地运行成功,那么集成到CI中也就是在.gitlab-ci.yml
写个tag 而已,说干就干。
yaml
stages:
- node_install
- node_build
- unit_test
- e2e_test
- deploy
...
e2e_test:
stage: e2e_test
script:
- node -v
- echo "e2e test start"
- yarn test:cy
allow_failure: true
artifacts:
when: always
...
写完代码非常自信的merge
到master
。
结果却出乎意料:显示缺少依赖 Xvfb
一顿google:
通过搜索,知道Xvfb
是一个UNIX-like操作系统的in-memory
显示服务器,有三个方案,
- 第一个是直接安装这个
Xvfb
,但是不建议单独安装,因为还会报其依赖错误; - 第二个是执行
cypress run --headless
,headless browsers
不使用Xvfb
, 但是这个方案也可能会出现其它问题。 - 最推荐的是第三个了,安装
Cypress
官方镜像。
因此我修改了.gitlab-ci.yml ,
看看能否顺利通过。
yaml
...
e2e_test:
stage: e2e_test
image: cypress/browsers:node-20.9.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1
script:
- node -v
- echo "e2e test start"
- yarn test:cy
allow_failure: true
artifacts:
when: always
...
很遗憾,还是报一样的错误,也就是这个镜像并没有拉取或者是拉取不成功。
在这里,触及到了我的知识盲区,因为之前没有怎么接触过docker,出现这个问题,我的排查方向还是在配置上,认为是配置不对,在google上一通搜索。
结果是,无论是官方文档,还是其他人给出的例子(比如这个github.com)都看不出来,我这配置有什么问题。
我甚至很有耐心的看完一个介绍视频www.youtube.com,这个外国友人讲得甚至都不是英文,硬着头看他演示代码。
然而依然没有成功。
在这个过程中,只能一个一个再去排查
- 是不是
cypress/browsers
node
版本的问题,我修改了本地node
版本问题,但是CI
中node
版本需要运维同学帮忙改,这个先暂缓,看看其它问题。 - 在
script
里要也尝试安装依赖包,但是前端项目的依赖都是读取package.json, 所以也并不会安装什么我们没有配置的包。 - 再尝试直接安装
Xvfb
,但yarn 中没有这个包... - ...
- 再问问服务端同学呢,他们也不知道...
卡住了怎么呢?
既然CI
管道中执行不成功,那么我本地安装一个docker
,拉取Cypress
提供的镜像,跑一跑试试。
本地电脑按照docker官方文档,很快安装成功。
接下来执行docker
拉取镜像,显示是成功的,再用docker
执行本地测试文文件。
bash
docker pull cypress/included:10.8.0
docker run -it -v $PWD:/e2e -w /e2e cypress/included:10.8.0
也成功了!
如果docker
能运行成功,那就在CI中也配置统一的镜像包吧。
yaml
e2e_test:
stage: e2e_test
image: cypress/included:10.8.0
script:
- node -v
- echo "e2e test start"
- yarn test:cy
allow_failure: true
artifacts:
when: always
修改代码后,再次执行pipelines
,成功了!
这成功也太突然了,这时,我一直以为是新的镜像包 cypress/included:10.8.0
起的效果。
等我再次将代码合并到master
,当头一棒的事情出现了!竟然其它的tags
都运行失败了!
这是什么神奇问题,node
还整丢了呢?
通过再一次google,大概觉得应该是执行e2e的runner
和执行install
的runner
不是一个,切换错误?
我意识到这个问题应该去问问运维同学了,在群里咨询后,没多久,司贤告诉我已经解决了。
原因是他修改了runner
!
再回头发现,执行成功了的e2e 信息里都有k8s
拉取镜像的打印:
而失败的e2e测试,并没有拉取镜像的打印信息:
所以,到这样,才知道,真正使得e2e运行成功的是这个16.6.1版本的gitlab-runner
起了作用。
至于gitlab-runner 16.5.0
为什么不会拉取镜像,我现在还不知道。(有知道的小伙伴可以评论里告诉我,感激不尽!)
ok,到这里问题应该都圆满解决了吧?
别高兴得太早,问题是层出不穷的,看吧:
当然这个问题,很简单,cypress
默认生成的配置文件是.ts结尾的,修改成.js,然后代码做一些修改即可:
到这里,pipelines终于迎来了五连勾:
三、总结
3.1 通过跑通Cypress
CI 集成流程,得出一些Cypress
结论:
- 比如镜像
cypress/included:10.8.0
后面的Cypress
版本和本地Cypress
版本不需要一模一样,只要不是太大版本差异就可以。同理cypress/browsers:node-16.18.1-chrome-110.0.5481.96
中node
版本也不必一模一样; - 官方镜像比如
cypress/browsers:node-16.18.1-chrome-110.0.5481.96
,不能擅自去更改node
版本,需要去官网查看对应版本,否则没有对应的镜像,当然也会失败; Cypress
最新版13,启动测试时,需要启动项目,但是10版本不需要,本地和docker
包括CI管道都不需要。
3.2 排查思路反思
- 对
docker
不太了解,导致在一个错误的方向上排查了很长时间。这个后续需要扩展自己的知识面,往服务端,运维、虚拟化技术等底层方向多些学习; - 这次排查问题,我在
node
以及Cypress
版本上也停留了很长时间,原因是过去确实遇到过因为依赖版本不一致而出现的问题经历,所以这次也认为可能出现在版本上。-- 所以说,经验并非百分百可靠,有时候仅能作参考,对于不同的问题可能需要区分看待; - CI管道运行环境,需要进一步学习,本次排查问题时,在
script
中写错了几次命令,存在着病急乱投医的行为。 - 当然最后,我觉得遇到问题都是好事,解决问题,不断扩展自己的知识边界,自己又成长一步!
3.2 下一步计划
- 本次只是跑通了流程,后续会针对系统的各个页面和模块在去写测试用例;
- 完善测试报告配置;
- 计划可能将单元测试也改为
Cypress
,因为Jest
是模拟浏览器去运行你的测试用例,而Cypress
是在真实的浏览器里跑,当然后者更准确。