タイトル通りですが、CircleCIでng serve(Angular)が必要なCypressのテストをする方法です
(ドキュメント少ないけどCypressって流行ってないのかなぁ)
なぜそんなことをしたいのか
jestとかでmock(のデータはあったほうがいいと思うが)を作って、そのmockにmockであることを振る舞わせるのはなんだかテストしているようでしていないような(jest.fn()とか)
なんか操り人形を使うことも記述しないといけないのが面倒だし結構複雑になる。。(ごめんなさい初心者です)
ので、実際にlocalhostを立ち上げて、ちゃんと振る舞うかテストするのがmockの振る舞いも記述しなくていいのでテストしやすいと思ったのが背景です
TL;DR
- Cypressでヘッドレスなテストを行う
- CircleCI上でlocalhostを立ち上げる
- CircleCIでng serveしてテストが終わったら、次のworkflowへ移る
- npmパッケージのwait-onを使う
いきなり正解の設定から
必要だと思われる部分だけです
spa(Angular)なのでpackage.jsonとcircleciのconfig.ymlです
{
"scripts": {
"ng": "ng",
"serve": "ng serve",
"start": "node server",
"build": "ng build",
"build:prod": "ng build --aot --prod",
"lint": "ng lint",
"test": "cypress run --spec 'src/app/**/*.spec.ts'",
"test:e2e": "./node_modules/.bin/cypress open",
"cypress:install": "cypress install",
"test:wait": "wait-on http://localhost:4200 && yarn test",
"postinstall": "node ./ng-add-pug-loader.js && ng build --aot --prod"
},
"dependencies": {
"@angular/core": "^6.1.1",
"typescript": "2.9.2",
"wait-on": "^3.0.1",
},
"devDependencies": {
"cypress": "^3.1.0",
}
}
version: 2
container: &container
working_directory: ~/my-template
docker:
- image: circleci/node:8.11-browsers
environment:
TZ: Asia/Tokyo
TERM: xterm
jobs:
install-and-build:
<<: *container
steps:
- checkout
- restore_cache:
name: Restore Yarn Package Cache
key: dependency-cache-{{ checksum "yarn.lock" }}
- run: yarn install
- run: yarn build:prod
- save_cache:
name: Save Yarn Package Cache
key: dependency-cache-{{ checksum "yarn.lock" }}
paths:
- ~/.cache
- ./node_modules
- persist_to_workspace:
root: .
paths:
- .
test:
<<: *container
steps:
- attach_workspace:
at: .
- run:
command: yarn serve
background: true
- run:
command: yarn cypress:install
- run:
command: yarn test:wait
master-jobs:
<<: *container
steps:
- checkout
- attach_workspace:
at: .
- run: ./scripts/create-mastertag.sh
workflows:
version: 2
build-and-test:
jobs:
- install-and-build
- test:
requires:
- install-and-build
- master-jobs:
requires:
- test
filters:
branches:
only: master
罠(勝手にハマったのかも)
config.ymlのsave_cache
で~/.cache
を保存しているのに、cypress実行時にcypressがいないのでインストールしてきて出直してきて反省してくださいって赤文字でエラーになります
インストールしてるはずなのに・・・
dockerで、「cypress:base8」というcypressが入っているはずのやつでもだめなので、yarn cypress:install
してcypressをインストールしています
誰かわかる人いましたらご指摘お願いします
大きな流れ
流れはconfig.ymlに設定として載ってますが、やりたいことはCircleCI上でlocalhostを立ち上げてテストをしたいのです。
- yarn install
- CircleCI上でng serve(localhostを立ち上げ)
- localhost立ち上がり次第、cypressでテスト実行
- テストが完了したら、次へ進む(localhostは捨てる)
ポイント① wait-onを使用する
cypressの公式ドキュメントにもあるのですがwait-onを使用します
これがないとlocalhostが立ち上がる前に、CircleCIでテストコマンドが走っててテストがコケます
ポイント② wait-onを実行するコマンドを作ろう
scripts: {
"test:wait": "wait-on http://localhost:4200 && yarn test",
こんなかんじでlocalhostが立ち上がるまで待ち、localhostが立ち上がり次第、yarn test
でテストが実行されるようにしましょう。
公式ではいきなりwait-onコマンド実行してますが、そんなコマンドはないと怒られてしまうので第二の罠です
ポイント③ サーバー立ち上げはbackgroundで行う
これはやってもやらなくてもいいですが、circleciの設定で
test:
<<: *container
steps:
- attach_workspace:
at: .
- run:
command: yarn serve
background: true
- run:
command: yarn cypress:install
- run:
command: yarn test:wait
- run:
command: yarn serve
background: true
backgroundをtrueとすると、serverの立ち上げしつつ、cypressのインストールしつつ、localhostの立ち上がりを待ちつつ、テストコマンドを実行することができます
これでテストが無事通れば、サーバーは立ち上がりっぱなしになることなく
つぎのworkflowへと移行します
Most CI providers will automatically kill background processes so you don’t have to worry about cleaning up your server process once Cypress finishes.
とあるように、テストが終わればbackgroundのプロセスは勝手に消去されるようですね
上記ポイントをおさえていれば、サーバーが立ち上がりっぱなし(CIの時間消耗)だったり、サーバーが立ち上がる前にテスト実行してコケたりということは回避できました