GitLab-CIでAngularのテストを動かしてみる

GitLab-CI使うとテストとか自動化できるらしい、というのは知っていたんですがいままでRunnerの準備とか自分でしなきゃなくてハードル高いなーと思っていました。
でも、よくよく調べてみるとShared Runnerというものが用意されており、それを使えば設定ファイルを作るだけでGitLab-CIが使えるとのことです。
今回はangular-cliで作成したプロジェクトをGitLab-CIでテストをするまでの手順を書いていきます。
デプロイも自動でできるらしいですが、そこまではやらないです。
テストブラウザとしてはChromeのheadlessを使います。

# プロジェクトの作成
とりあえず、angular-cliでプロジェクトを作ります。
バージョンは以下の通り

- angular-cli 6.0.8
- angular:6.0.3

今回はgitlab-ci-testという名前でプロジェクトを作成。

```
ng new gitlab-ci-test
```

# テスト設定の変更
デフォルトだとテストブラウザはchromeを使うようになっているので、Chromeのheadlessモードを使うように変更します。
また、Docker上で実行するときに`--no-sandbox`オプションもつける必要があるので、そちらも設定します。

## 単体テスト
```gitlab-ci-test/src/karma.conf.js
    browsers: ['ChromeHeadlessNoSandbox'], // browsersを変更
    customLaunchers: { // browserの下に追加
      ChromeHeadlessNoSandbox: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox']
      }
    }
```

## e2eテスト
```gitlab-ci-test/e2e/protractor.conf.js
  capabilities: { // capabilitiesを変更
    'browserName': 'chrome',
    'chromeOptions': {
      'args': ['--headless', '--no-sandbox']
    }
  },
```

# .gitlab-ci.ymlの作成
GitLab-CIに実行させたいコマンドを.gitlab-ci.ymlで記述します。

```yml
image: thompsnm/nodejs-chrome:latest

stages:
  - lint
  - test
  - e2e

before_script:
  - npm install

lint:
  stage: lint
  script:
    - ./node_modules/@angular/cli/bin/ng lint

test:
  stage: test
  script:
    - ./node_modules/@angular/cli/bin/ng test --watch=false --progress=false

e2e:
  stage: e2e
  script:
    - ./node_modules/@angular/cli/bin/ng e2e
```

`image`でdockerのイメージを指定します。
イメージは[Docker Hub](https://hub.docker.com/)で探せば見つかると思います。
今回はnodejsとchromeが入っていればよいので、`thompsnm/nodejs-chrome`というイメージを使いました。

`stages`で実行するジョブのステージ名を指定します。
今回はlint、test、e2eの3つを実行します。
それぞれのジョブの定義は後述。

`before_script`では、各ジョブの前に実行するコマンドを記述します。
今回はnpm installを実行させています。

`lint`、`test`、`e2e`はジョブの定義で`stage`にステージ名、`script`にコマンドを記述します。
`test`のコマンドでは`--watch=false`はテスト後に実行が終了するようにつけています。
`--progress=false`はコマンドラインに進捗状況が流れて結果画面が長くなるのでfalseにしています。

# GitLab-CIの実行
ここまでできたら、GitLabにプッシュしてあげるとGitLab-CIが動きはじめます。
プッシュしたプロジェクトのCI/CDのところを開くと一番上の行のstagesという部分が以下のようになっていると思います(青い欠けた〇が出ていれば実行中なので終わるまでお待ちください)。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/c9c94541-f301-1449-8e5f-ec2309556fc0.png)

この〇は左から`stages`で定義されたジョブの結果になっています。
1つめは`lint`なのでこれは成功しています。
2つめは`test`ですが、失敗しています。
3つめは`e2e`ですが、2つめのジョブが失敗しているのでそれ以降のジョブがスキップされています。
ジョブが失敗すると、自動で登録アドレスにメールが送られます。

この〇をクリックして表示されるジョブ名をクリックするとそのジョブの詳細画面が開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/d09f89be-eeb9-3a03-14b0-6acb6322c644.png)

実行時のコマンドラインが表示されるので、それを解析します。
今回の場合、以下の部分がエラーの原因でした。

```
HeadlessChrome 67.0.3396 (Linux 0.0.0) AppComponent should have as title 'gitlab-ci-test' FAILED
	Expected 'app' to equal 'gitlab-ci-test'.
```

これは、[別記事](https://qiita.com/frost_star/items/e18565f446b7e05bc6e4)でも書きましたがangular-cliでプロジェクトを作るとテストが通らない状態のものが生成されるためです。
以下の2箇所を修正します。

```js:src/app/app.component.ts/9行目
title = 'gitlab-ci-test'; // appから変更
```

```js:src/app/app.component.spec.ts/19行目
expect(app.title).toEqual('gitlab-ci-test'); // appから変更
```

修正後、再度プッシュすると今度はすべてのジョブが成功するかと思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/4548a0a2-101e-8666-fdda-f859f684000f.png)

# 残った課題
`e2e`のコマンド実行時にコマンドラインにいろいろ出力されてしまって長くなってしまうので、`test`コマンドの`--progress=false`みたいなのがあるといいんですが見つからず。