C言語によるアジャイル開発とテスト駆動開発(CI入門) ~ 4.Jenkins導入 ~

# 概要
これまでで、アジャイル開発に対するテスト駆動の必要性を解き、CUnitによるテスト実行の自動化、CMakeによるビルド工程の自動化を行ってきました。
本記事では、Jenkinsとこれまでの成果を用いて、テスト工程を自動化していきます。

## 記事の全体像
- [C言語によるアジャイル開発とテスト駆動開発(CI入門) ~ 1.概念 ~](https://qiita.com/denden14/items/a1435a225e386c32dab5)
- [C言語によるアジャイル開発とテスト駆動開発(CI入門) ~ 2.CUnit導入 ~](https://qiita.com/denden14/items/27d29735caef9b5639e0)
- [C言語によるアジャイル開発とテスト駆動開発(CI入門) ~ 3.CMake導入 ~](https://qiita.com/denden14/items/7b1729c7ff273c4165bd)
- [C言語によるアジャイル開発とテスト駆動開発(CI入門) ~ 4.Jenkins導入 ~](https://qiita.com/denden14/items/30cbe6d327a404aaa2a7)

## 環境
OS : Linux ubuntu 18.04.5 LTS
テストツール : CUnit 2.1-3

コンパイラ : gcc 7.5.0
ビルドツール：CMake 3.19.4
CIツール：Jenkins

# CIツール
## そもそもビルド自動化ツールとは
ソフトウェア開発のビルド、テスト、及びデプロイに関連する部分の自動化を支援し、継続的インテグレーション(CI)と継続的デリバリー(CD)を促進するためのツール。

これまでは、CMakeでビルドを自動化し、CUnitでテストを実行することができました。
では、誰がビルドを実際に行い、テストを実行し、報告してくれるのでしょうか？
そうです。__Jenkins__です。

CIツールでは、特定のイベントをトリガーにしてあらかじめ指定しておいた処理を実行する役割を担います。

#### 代表的なツール

- Jenkins
- Travis CI
- Circle CI 
など

# SCM導入
Jenkinsを導入する前に、SCMを導入します。
ここではgithubを導入していきます。
詳細は説明省かせていただきますので、他を参照してください。

プライベートのリポジトリで、リポジトリ名を`add_sample`とします。
空のリポジトリの作成が出来たら、今まで作ってきた環境を登録します。

```bash:Bash
$ tree
.
├── CMakeLists.txt
├── add
│   ├── include
│   │   └── add.h
│   └── src
│       └── add.c
├── main.c
└── test
    └── unitTest.c
```
この状態から、先程作ったリモートリポジトリを登録します。

```bash:Bash
git init
git add .
git commit -m "first commit"
git remote add origin [githubへのURL]
git push -u origin master
```

# Jenkins導入
### Jenkinsのインストール
```bash:Bash
sudo apt install openjdk-11-jdk
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins
```
[[Jenkins][Ubuntu] UbuntuにJenkinsをインストール](https://qiita.com/koara-local/items/268dab580346fcef59b5)
こちらに則って、初期設定を行います。

### プラグインのインストール
git, xUnit, Coberturaをインストールしていきます
ログインしてこのような画面が出るはずなので、__Jenkinsの管理__をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/09139227-5870-f647-49d3-f4340a33cdc0.png)

上段の右から2番目の__プラグインの管理__をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/3f5ad30b-af4d-db91-af18-6834eeb736cf.png)


__利用可能__ タブで __git__ と検索し、チェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/1f4384f9-02dd-4fee-8f23-84882eed2da0.png)

同様に __xUnit__ をチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/d4adf053-db15-c2bf-1518-d8b3b87a3919.png)

同様に __Cobertura__ をチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/e079fad7-7a57-1004-0bc1-da42e63f887a.png)

画面下部の __ダウンロードして再起動後にインストール__ を押し、
インストール完了後、ジョブがなければJenkinsを再起動するにチェックを押します。
※上手く再起動出来ない場合があるので、一旦タブ消し、再度ログインしたりしてみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/b6af6ee3-7f92-bbd5-47ba-f5869fc47d9d.png)

再度ログイン後、同じ画面で__インストール済み__の箇所から先程インストールしたプラグインが表示されていればインストールは完了です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/4ee9fcc0-cebc-de85-6e20-b0e378a1fb26.png)

### プロジェクト(ジョブ)の作成
Top画面に戻り、左上の__新規ジョブ作成__を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/410c4e58-394d-78da-3d9d-c0c27d1c7b22.png)

プロジェクト(ジョブ)の名前に__add_sample__と入れ、__フリースタイル・プロジェクトのビルド__を選択し、OKを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/249558b2-8b20-3a45-4f1e-c436777e3051.png)

ソースコード管理で __git__を選択し、リポジトリのURLにgithubのURLを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/ebbf1f04-0e62-3e57-b3a6-07c0d2000985.png)

認証情報の追加を押し、gitHubの__ログインユーザー名とパスワード__を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/b11b68a0-abe1-1f06-f0a4-da9d9d158d67.png)

次に、ビルド・トリガの__SCMをポーリング__を選択し、`* * * * *`を入力します。
これは、SCM(Source Control Management ※今回はgitHub)をポーリング(定期的に問い合わせ)するということです。
gitHubがPushを受け取った際に、Jenkinsに知らせるイベントドリブン的なやり方もありますが、
これは、固定IPが必要になるのと、ルーターの設定等やらなければならないので今回はパスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/1610294a-8711-fbb6-f33d-805058b2c7e2.png)

次に、ビルドで、__シェルの実行__を選択し、下記のスクリプトを入力します。
ほとんどこれまでやってきたとおりですので、最後の行の箇所だけ説明します。
-r : ルートディレクトリ(gcovrはソースファイルを含む必要があるので、bulidフォルダの上の階層を指定する)
-x : XMLファイルを出力させる
-o : outputファイル名
です

```sh
echo TEST START

rm -rf build
mkdir build

cd build
cmake ..
cmake --build .

./UnitTest

gcovr -x -r .. -o gcovr_report.xml
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/8422c379-5ffc-b518-480f-cfb807e8a2ca.png)

一旦保存して下記の画面(以降プロジェクト画面と言う)に推移したら、__ビルド実行__を押して実行を確認しましょう。
するとビルド履歴が表示されます。青色であればビルドが成功しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/bd47532c-859d-dba3-f389-e31c66ba3063.png)

エラーが出ている場合は、
ビルドの履歴部分(#1とか)をクリックし、ビルドの詳細に飛びます。
コンソール出力をクリックすると、コンソール画面が表示されますので、
この画面でどのようなエラーが出ているか確認しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/566d7d6f-2ec9-8f1e-a368-f0fbcef9c532.png)

プロジェクト画面に戻り、設定をクリックします。
一番下のビルド後の処理の追加で__Coberturaカバレッジ・レポートの集計__選択し、`build/gcovr_report.xml`を入力します
(表示されない方:[プラグインのインストール](#プラグインのインストール))
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/2c5ff0e0-0df9-662e-739d-04738c0d34c1.png)


さらにビルド後の処理の追加から__Publish xUnit test result report__選択します
__Report Type__ を __CUnit-2.1(default)__を選択し、__Includes Pattern__から`build/CUnitAutomated-Results.xml`を入力します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/301e3b83-936b-5a86-3488-1c0efd186411.png)

保存を押して、再度ビルド実行します。
ビルドの履歴部分をクリックし、ビルドの詳細に飛ぶと、
__Cobertura カバレッジ・レポート__と__テスト結果__が表示されていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/0162141a-656b-b5a0-1290-245f356f5125.png)

各々クリックすると下記の様な画面が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/07b790cf-6caa-e884-6046-d27a672bfa65.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/e17aa26d-48f1-6f83-4939-49f4cffae11d.png)

これでJenkinsを用いてビルドの処理を自動化することが出来ました。

### ついにテスト自動化
やっとここまで来ました。
ここまで読んでくれる人いるのか甚だ疑問。もはや一人舞台。

でももうひと踏ん張りです。
最後に、ローカルの環境でバグを治してgitHubにプッシュしましょう。
これまで通りの設定をしていれば、
1分以内にJenkinsがgitHubの更新を確認し、ビルドを行い、テストを実行し、テストレポートを吐いてくれます。

ではバグを治します。

```c:add.c
#include <add.h>

// バグのあるadd関数(テスト対象)
int add(int x, int y) {
		return x + y; // ココ。return 0; から修正
}
```

gitHubに修正を登録します。

```bash:Bash
git commit -a -m "bug_fix"
git push
```

Jenkinsのプロジェクト画面を見張りましょう。
一分以内に新しいビルド履歴が表示されるはずです。
ついでに今回の バグフィックス でテスト結果の推移にも反映されていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/cf702270-8f56-51a0-df2e-8976c30000d9.png)

もちろん詳細を確認しても
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538059/a7b8cd10-2f21-11a2-97c4-9924efc567be.png)

# おわりに
めでたしめでたし。
もし、間違いや指摘事項等あれば、コメントしていただけると大変助かります。

# 参考文献
[JenkinsとGitHubのWebhook連携の整理](https://developer.aiming-inc.com/infra/jenkins-github-webhook-collaboration/)
[20年物のC言語で作られたシステムのテスト工程を改善しようとした話](https://qiita.com/mima_ita/items/cb94a767e9d9e5a84a2f#%E7%B6%B2%E7%BE%85%E7%8E%87%E3%81%AE%E8%A8%88%E6%B8%AC%E6%96%B9%E6%B3%95)
[開発者（個人）のためのJenkins - Git Plugin編](https://qiita.com/yasuhiroki/items/61a2be613fc7dcfc8682#commit-%E3%81%8C%E3%81%82%E3%82%8C%E3%81%B0%E8%87%AA%E5%8B%95%E7%9A%84%E3%81%AB%E3%83%93%E3%83%AB%E3%83%89%E3%81%99%E3%82%8B)