Jenkinsを用いた自動テストの導入メモ

## やりたいこと

Jenkinsを利用して、Javaプロジェクトに自動テストを導入します。
・masterブランチにプッシュした時点、テストを自動に実施します。
・テスト結果として、カバレッジ率を表示されます。

## 環境
macOS Big Sur 11.1
Homebrew 2.7.1-56-gff931c2
Jenkins 2.273
Java 1.8
ngrok 2.3.35



この記事に利用するサンプルは、Githubに置いてあります。
https://github.com/koyi2016/JenkinsDemo

## Jenkinsのインストール
macのターミラルを開いて、コマンドを実行します。

```
brew install jenkins
```

すぐにインストールされるので、Jenkinsを起動します。

```
java -jar /usr/local/opt/jenkins/libexec/jenkins.war
```

正常に起動できたら、以下のようなメッセージが表示されます。

```
Running from: /usr/local/Cellar/jenkins/2.273/libexec/jenkins.war
webroot: $user.home/.jenkins
2020-12-30 04:38:41.989+0000 [id=1]	INFO	org.eclipse.jetty.util.log.Log#initialized: Logging initialized @1700ms to org.eclipse.jetty.util.log.JavaUtilLog
2020-12-30 04:38:42.407+0000 [id=1]	INFO	winstone.Logger#logInternal: Beginning extraction from war file
2020-12-30 04:38:47.104+0000 [id=1]	WARNING	o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath
2020-12-30 04:38:47.309+0000 [id=1]	INFO	org.eclipse.jetty.server.Server#doStart: jetty-9.4.35.v20201120; built: 2020-11-20T21:17:03.964Z; git: bdc54f03a5e0a7e280fab27f55c3c75ee8da89fb; jvm 1.8.0_271-b09
2020-12-30 04:38:48.529+0000 [id=1]	INFO	o.e.j.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2020-12-30 04:38:48.744+0000 [id=1]	INFO	o.e.j.s.s.DefaultSessionIdManager#doStart: DefaultSessionIdManager workerName=node0
2020-12-30 04:38:48.744+0000 [id=1]	INFO	o.e.j.s.s.DefaultSessionIdManager#doStart: No SessionScavenger set, using defaults
2020-12-30 04:38:48.756+0000 [id=1]	INFO	o.e.j.server.session.HouseKeeper#startScavenging: node0 Scavenging every 600000ms
2020-12-30 04:38:50.356+0000 [id=1]	INFO	hudson.WebAppMain#contextInitialized: Jenkins home directory: /Users/user/.jenkins found at: $user.home/.jenkins
2020-12-30 04:39:01.536+0000 [id=1]	INFO	o.e.j.s.handler.ContextHandler#doStart: Started w.@4e9658b5{Jenkins v2.273,/,file:///Users/user/.jenkins/war/,AVAILABLE}{/Users/user/.jenkins/war}
2020-12-30 04:39:01.752+0000 [id=1]	INFO	o.e.j.server.AbstractConnector#doStart: Started ServerConnector@798162bc{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2020-12-30 04:39:01.753+0000 [id=1]	INFO	org.eclipse.jetty.server.Server#doStart: Started @21464ms
2020-12-30 04:39:01.754+0000 [id=23]	INFO	winstone.Logger#logInternal: Winstone Servlet Engine running: controlPort=disabled
2020-12-30 04:39:05.365+0000 [id=30]	INFO	jenkins.InitReactorRunner$1#onAttained: Started initialization
2020-12-30 04:39:05.425+0000 [id=34]	INFO	jenkins.InitReactorRunner$1#onAttained: Listed all plugins
2020-12-30 04:39:10.521+0000 [id=34]	INFO	jenkins.InitReactorRunner$1#onAttained: Prepared all plugins
2020-12-30 04:39:10.537+0000 [id=31]	INFO	jenkins.InitReactorRunner$1#onAttained: Started all plugins
2020-12-30 04:39:10.605+0000 [id=30]	INFO	jenkins.InitReactorRunner$1#onAttained: Augmented all extensions
2020-12-30 04:39:12.522+0000 [id=28]	INFO	jenkins.InitReactorRunner$1#onAttained: System config loaded
2020-12-30 04:39:12.522+0000 [id=35]	INFO	jenkins.InitReactorRunner$1#onAttained: System config adapted
2020-12-30 04:39:12.523+0000 [id=28]	INFO	jenkins.InitReactorRunner$1#onAttained: Loaded all jobs
2020-12-30 04:39:12.532+0000 [id=28]	INFO	jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated
2020-12-30 04:39:12.552+0000 [id=48]	INFO	hudson.model.AsyncPeriodicWork#lambda$doRun$0: Started Download metadata
2020-12-30 04:39:12.568+0000 [id=48]	INFO	hudson.util.Retrier#start: Attempt #1 to do the action check updates server
2020-12-30 04:39:13.625+0000 [id=34]	INFO	jenkins.install.SetupWizard#init: 

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

68fc731c3b5f457ab6e7731dc7ce1215

This may also be found at: /Users/user/.jenkins/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

2020-12-30 04:39:35.353+0000 [id=34]	INFO	jenkins.InitReactorRunner$1#onAttained: Completed initialization
2020-12-30 04:39:35.377+0000 [id=22]	INFO	hudson.WebAppMain$3#run: Jenkins is fully up and running
2020-12-30 04:39:35.936+0000 [id=48]	INFO	h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
2020-12-30 04:39:35.938+0000 [id=48]	INFO	hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1
2020-12-30 04:39:35.950+0000 [id=48]	INFO	hudson.model.AsyncPeriodicWork#lambda$doRun$0: Finished Download metadata. 23,396 ms
```

## Jenkinsの初期設定
上記のインストールが完了した後、ブラウザを起動し、以下のURLを入れると、Jenkinsを開けます。
http://localhost:8080/

![Sign_in__Jenkins__png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/19dcfd67-3885-2577-79fa-41a3a3b26c47.png)

パスワードの入力欄にインストール正常した際自動生成されるパスワードを記入します。
「68fc731c3b5f457ab6e7731dc7ce1215」

次、「Install suggested plugins」を選択します。
![Setup_Wizard__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/e5519074-5f3b-a981-fd0c-37da0c0f2916.png)

プラグインがインストールできた後、管理者用ユーザーを設定します。
![Setup_Wizard__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/c97f3c9d-4691-8ec4-50c1-d5aada40bb40.png)

これで初期設定を完了しました。
![ダッシュボード__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/2b16ced5-a0ff-6bb3-539a-920a43066fbf.png)


## 自動テストための設定

### ngrokのインストール

ngrokとは、localhostで動いているサーバーを、LANの外からアクセスできるようにできるツールです。今回ローカルで構築したJenkinsをGitHubのwebhookから通信できるようにために、ngrokを入れました。

macのターミラルを開いて、コマンドを実行します。

```
brew install ngrok
```

インストールした後、以下のコマンドでJenkins側利用しているポート８０８０を公開します。有効時間が８時間そうです。

```
ngrok http 8080
```

![KO_—_ngrok_http_8080_—_142×37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/2d49bd9e-0c72-0a32-06de-8ace825a510b.png)

「http://b8dd86e8f647.ngrok.io 」のURLは外から利用できるようにしてました。このURLはGitHubのwebhooksに利用されてます。

### Githubの設定

対象リポジトリから、Settings>Webhooks>Add webhooksをクリックして、以下のように設定します。

![スクリーンショット 2021-01-03 23.32.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/b55839df-fb4f-fc9e-c80a-b2f8c7e2270e.png)

Jenkinsとうまく通信できる場合、「Recent Deliveries」のところは、レスポンスをちゃんと戻られます。
![Webhook_·_http___b8dd86e8f647_ngrok_io_github-webhook_-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/764b1ab8-81ce-c4ce-1da1-05f169dda92a.png)


### Jenkinsの設定

#### 必要なプラグインのインストール

Jenkinsの管理 > プラグイン管理 > 利用可能 から以下のプラグインを探してインストールします。

![Available_Plugins__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/330b0d69-f86c-9c72-2d7d-a44f175af053.png)

・GitHub Plugin（Jenkinsのインストール際既に導入済み）
　https://plugins.jenkins.io/github/

・GitHub Integration
　https://plugins.jenkins.io/github-pullrequest/

・Jacoco
　https://plugins.jenkins.io/jacoco/

プラグインをインストールした後、Jenkinsを再起動をしたほうがいいです。
ブラウザのURLに以下のURLを入力して再起動をできます。

```
http://localhost:8080/safeRestart
```

#### Jenkinのシステム設定

Jenkinsの管理 > システムの設定 から、以下のことを実施します。

・JenkinsのURLを設定します。
![システムの設定__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/803bf864-50b3-afa5-d298-07fa1a59f282.png)

・Jenkinsの「Override Hook URL」は、上記に設定したGitHubのwebhookの「Payload URL」に一致しているかを確認します。
![システムの設定__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/c601dc06-979d-af3c-e8a7-19cb5039ed8a.png)

Jenkinsの管理 > Global Tool Configuration から、JDKを設定します。
他の設定はデフォルトのままにしています。

![Global_Tool_Configuration__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/6585af22-84ef-5e02-7760-70636221cd6b.png)

#### ビルド用ジョブの作成

新規ジョブを作成します。

![新規ジョブ作成__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/954b6681-8dae-a5fe-5cc9-f8b47c368443.png)

GeneralのGitHub projectをチェックし、対象リポジトリのURLを入力します。

![Jenkins-demo_Config__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/861adecf-89f2-b559-c795-1cbd191864e6.png)

ソースコード管理でGitをチェックし、認証情報と対象ブランチを入力します。
認証情報は、GitHubにアクセスできるアカウントです。

![スクリーンショット_2021-01-04_0_17_16_png_と_Webhook_·_http___b8dd86e8f647_ngrok_io_github-webhook_-2_png_と_「Jenkinsを用いた自動テストの導入メモ」を編集_-_Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/487eb4ed-ad18-ce62-bafb-fe1af858f0a2.png)

ビルド・トリガで「GitHub hook trigger for GITScm polling
」をチェックします。

![Jenkins-demo_Config__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/2883b33c-7f4f-2973-263e-44c40eec21b3.png)

ビルドでMavenの呼び出しを選択し、`clean jacoco:prepare-agent test`を入力します。

![Jenkins-demo_Config__Jenkins__と_「Jenkinsを用いた自動テストの導入メモ」を編集_-_Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/e80c13ac-5881-ee80-62ac-c45a88f78763.png)

ビルド後の処理で「Junitテスト結果の集計」を選択します。

![Jenkin-demo_Config__Jenkins_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/d7b6d1af-9153-326c-616a-4df84a01b8de.png)


最後は、「JaCoCoカバレッジレポートを記録」を選択し、保存します。

![Jenkin-demo_Config__Jenkins_-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/e4dd0327-461e-a79d-87a5-f59e40393ef0.png)


これで、新しいジョブを作成しました。

### 自動テスト

・対象リポジトリのmasterブランチに対して、変更を実施し、プッシュを行います。

・Jenkinsからそのプッシュを検知し、自動ビルドを行います。ビルドした結果は、以下のようになります。
![スクリーンショット_2021-01-04_0_36_43_png__2558×1372_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/8c116039-6362-6488-787f-1672b61aae7b.png)

ビルド履歴の番号をクリックすると、カバレッジの詳細を確認できます。

![Jenkins.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154911/a3113d1b-ecd7-2cb5-d3ac-6f87f71eca6e.png)