---
title: 在 Gitlab 上建立 Java Unit Test
tags: CI/CD, Gitlab, Java, Unit Test, Gitlab Runner
description: 在 Gitlab 使用 Runner 執行 Java 的 Unit Test.
---
# 在 Gitlab 上建立 Java Unit Test
這裡我使用簡單的最簡單的範例,在 Gitlab 上實作一個 Java Unit Test,以下是我使用的環境:
* 語言: Java
* 專案管理: Maven
* 程式碼編輯器: VSCode
* Runner 作業系統: Windows10
* 最後更新日期 :2021/08/08
---
## Chapter 1. 簡單的 Java 單元測試
### Step 1. 安裝 Maven
Apache Maven,是一個軟體(特別是Java軟體)專案管理及自動構建工具,由Apache軟體基金會所提供。這裡我使用 Maven 作為我的 Java 專案管理及自動構建工具。
安裝的過程非常非常的簡單,首先先去官網 [Apache Maven Download](https://maven.apache.org/download.cgi)頁面下載<font color="red">紅框處</font>的檔案。

下載完後請解壓縮,解壓縮後會看到以下的檔案,可以將這整個資料夾放置在任何地方,只要你知道這個資料夾位置就好。以我的範例來說我放在 C 槽目錄:

接下來,進入到 bin 資料夾,把路徑複製下來,以我的範例來說就會是==C:\apache-maven-3.8.1\bin==,接下來請去**系統變數**那邊,將這個路徑新增進去,之後開啟 windows cmd,輸入 ==mvn -v==,當有看到以下訊息時,代表你安裝成功了。

---
### Step 2. 新增一個 Java 專案
開啟 Visual Studio Code,去 Extensions 裡安裝,==Java Extension Pack==,基本上裡面重要的東西都有包含到,所以直接 install 就好了。安裝完後重啟 VSCode,按 Explorer,應該就會看到左下角有個 Maven 文字,點他後會展開,再點旁邊的 ==+== 號

這裡我使用 ==Maven-archetype-quickstart== 且版本為 ==1.4== 作為範例專案,如果有其他需求可以點其他的樣板。

之後就輸入你的 Group ID、Artifical ID,輸入完後會要你選擇專案的根資料夾,放在哪裡都可以,建議路徑不要有中文、空白或特殊字元就好,之後再輸入版本號,輸入為會看到以下畫面,再輸入 Y 做專案的確認:
:::info
第一次執行會跑比較久,請耐心等候
:::

跑完後在使用 Visual Studio Code 開啟剛剛專案建立的資料夾,就會看到以下的畫面,這樣專案就算建立成功了:

---
### Step 3. 第一次推送至 Gitlab
因為剛剛新增了一個專案,接下來我們要把他推送至 Gitlab
先執行:
:::warning
請記得先 git clone 至本地,在執行以下指令。如果可以 .gitignore 也可以先加入至專案
:::
==.gitignore== 檔的內容(這個要自己手動加入)
```
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.ja
```
第一次推送至 Gitlab
```shell=
git init //初始化 git
git add -all //把專案新增的檔案加入
git commit -m "project create" //commit 檔案
```
成功後去 Gitlab 的專案就可以看到以下結果了

---
### Step 4. 執行程式
首先先在 ==App.java== 裡撰寫一些簡單的功能:
```java=
package com.devop;
/** Simple Hello World **/
public class App {
public static final String KEY = "Peko"; // 假裝是個密碼
private String keyToken;
public static void main( String[] args ){
System.out.println( "Hello World!" );
App app = new App();
System.out.prinln( "2 * (3 + 5) = " + (2 * app.sum( 3, 5 )) );
app.registerToken( "Peko" );
System.out.println( app.getKeyToken() );
}
/**
* 簡單的加法
* @param a A數字
* @param b B數字
* @return 總和結果
*/
public int sum(int a, int b){
return a + b;
}
/**
* 設定密碼金鑰
* @param input 金鑰
*/
public void registerToken(String input){
this.keyToken = input.replace("Pe", "Mi");
}
/**
* 取得註冊的 Token
* @return Token
*/
public String getKeyToken(){
return this.keyToken;
}
}
```
這時我們可以先開啟 VSCode 的 Terminal(終端機),來執行上方的程式,
並且在終端機輸入以下指令。
編譯程式:
```shell=
mvn compile
```
執行主程式:
```shell=
mvn exec:java -D"exec.mainClass"="{專案package}.App" //執行
```
上面的指令以我的範例就會變成
:::success
mvn exec:java -D"exec.mainClass"="<font color="red">com.devop</font>.App"
:::
輸入完後就會看到以下的畫面了:

---
### Step 5. 撰寫單元測試
在大多數的大型專案中,當一個專案的功能持續的增多,在測試上難免會花費不少時間,尤其是當修改 A 功能時,B 功能受到影響而產生 BUG,這個在大型專案中是非常容易發生的。這也就是為什麼要寫單元測試去執行各個元件的功能,以保持程式的正確性。
首先去 ==AppTest.java== 裡新增單元測試的條件:
```java=
/**
* Unit test for simple App.
*/
public class AppTest {
private App app;
public AppTest(){
System.out.println( "\nAppTest Start... " );
this.app = new App();
this.app.registerToken( "Peko" );
}
/**
* Rigorous Test :-)
*/
@Test public void shouldAnswerWithTrue(){
assertEquals( 15, app.sum(10, 5) ); // 驗證加法運算是否有出錯
}
@Test public void checkKeyToken(){
assertEquals( App.KEY.replace("Pe", "Mi"), app.getKeyToken() );
System.out.println( "Do other things here..." );
}
}
```
接下來只要在終端機輸入:
```shell=
mvn test
```
經過單元測試的結果:

假如這時候我們在修改 ==App.java== 的 ==sum 函式==時,不小心把它改成 ==a * b==,這時候我們在執行一次 ==mvn test==,就會出現以下的結果:

根據以上的結果,當我們在執行單元測試時,就可以知道 ==App.java== 的 ==sum 函式== 寫錯了,這樣我們就可以很快地更正他。
---
## Chapter 2. 在 Gitlab 上佈署自動測試
### Step 1. 在 Gitlab 上建立 CI/CD 檔
這裡我就不講 CI/CD 的原理以及概念了,簡單來說就是能讓整個專案在測試、佈署、建置都能自動化,並且可以監控狀態。這裡我用 Gitlab 作為 CI/CD 的平台。
首先,先新增一個檔案 ==.gitlab-ci.yml== 放在上面 push 的專案跟目錄裡,內容打:
```yaml=
stages: # 定義有哪些 stages
- build
- refactoring
- test
- deploy
build-project: # stage 名稱
stage: build
tags:
- main-runner # 可執行的 runner tag
only:
- master # 可執行的分支(branch)
script:
- echo "Hello Peko" # 簡單的印出
build-project-issue:
stage: build
tags: # 可以多個 tag
- main-runner
- issue-runner
only:
- issue
script:
- echo "building issue"
refactoring-project:
stage: refactoring
tags:
- main-runner
only:
- refactor
script:
- echo "refactoring program"
test-project:
stage: test
tags:
- main-runner
only: # 可以多個 branch
- master
- issue
- refactor
script:
- echo "simple unit test"
deploy-project:
stage: deploy
tags:
- main-runner
only:
- master
script:
- echo "package the project"
```
:::info
這個內容只是範例用的,之後都可以自行的修改它!
:::
再來我各個講解 .yml 裡的功能與定義,首先:
* **stages** (第1行)
> 代表的是在進行階段,當前一階段通過時,才能進行下一階段。依照我們這個範例意思就是當在自動測試時,會先執行 **build -> test -> deploy**,如果在 **test** 失敗時,就會直接停止,就不會執行 **deploy** 了
* **build-project** (第7行)
> 這裡就是在定義各個 **stage** 的細節,這裡的 **build-project** 是 **stage** 名稱,要怎麼取都可以,只要看得懂且能執行就好。
>>* **stage** (第8行)
>> 這裡定義這個 **stage** 是哪一個階段,必須要跟上面 "**stages** (第1行)" 的名稱匹配。
>
>> * **tags** (第9行)
>> 這個定義的是給 Runner 的標籤,假如我們想讓特定 Runner 只能執行某些 **stage** 就可以利用這個做設定。
>
>> * **only** (第11行)
>> 這個是用來定義在哪些的 **分支(Branch)** 才會執行此 **stage**。
>
>> * **script** (第13行)
>> 這個是指 Runner 在進行測試時,會執行的指令,這個會根據作業系統而做不同的改變,像是這裡我 Runner 預設是 Windows 的 powershell,所以當在執行時就會執行以下指令 **powershell echo "Hello Peko"**
基本上以上就是最基本的 **.gitlab-ci.yml** 的設定,剩下的 **test-project**、**test-project-issue**、**deploy-project** 也都是相同的概念,如果要在有更複雜的功能可以自行去搜尋。
當建立好 **.gitlab-ci.yml** 之後,請記得 push 至 Gitlab,這時候去 Gitlab 專案裡的 **CI/CD** 就可以看到以下結果:

:::warning
這裡可以不用等它,不管怎麼等都只會卡在 pending,所以請繼續看下去。
:::
---
### Step 3. 下載 Runner 主程式
首先,先去先前的專案裡的 **Settings** -> **CI/CD** -> **Runners** (點擊右邊展開)。
:::warning
假如你的專案沒有 **Settings** 的話,請確認是否你具有對此專案權限喔。
:::
去 Gitlab 官網下載 Runner 的主程式,看你的作業系統就下載哪個,以我的來說是 Windows 10 64位元,所以我就點 **Binaries** -> **Install on Windows** -> **64-bit**

下載完後,檔案會是個 **gitlab-runner-windows-amd64.exe** 檔,這時請 **建立一個資料夾**,放在哪裡都可以,把這個 **gitlab-runner-windows-amd64.exe** 放到資料夾裡,資料夾的名稱可以自由的取,以英文為主就好。
---
### Step 4. 註冊 Runner
以我的來說,我是放置在 **D:\ProgramPackage\GitLabRunner** 這個路徑下,接下來開啟 **cmd(命令提示字元)** ,指到剛剛放置 **gitlab-runner-windows-amd64.exe** 的資料夾。接下來執行以下指令:
:::warning
請記得要以系統管理員執行 **cmd**
:::
安裝 gitlab-runner-windows-amd64.exe
```shell=
gitlab-runner-windows-amd64.exe install
```
:::danger
第一次執行此程式的時候或更動了 .exe 位置時都要執行此命令!之後註冊就不用執行了。
:::
註冊 Runner
```shell=
gitlab-runner-windows-amd64.exe register
```
接下來依序填入
* **網址** (第一個紅框處)
> Enter the GitLab instance URL (for example, https://gitlab.com/)
* **Token** (第二個紅框)
> Enter the registration token:
* **此 Runner 的描述**
> Enter a description for the runner
* **此 Runner 的 Tag** (逗號分隔,用於多個 Tag)
> <font color="red">根據我們前面的 .gitlab-ci.yml 設定,這用 main-runner 作為 Tag</font>
> Enter tags for the runner (comma-separated):
* **此 Runner 的執行器** (通常只要打 shell 就好)
> Enter an executor

註冊完後會看到的畫面:

之後去 Gitlab 的 Runner 下方就會看到剛剛註冊的 Runner 跑出來了

---
### Step 5. 執行 Runner
經過上述步驟後,只是完成了註冊,還沒讓 Runner 執行起來,接下來一樣在 **cmd(命令提示字元)** 輸入以下的指令:
```shell=
gitlab-runner-windows-amd64.exe verify //驗證
gitlab-runner-windows-amd64.exe start //啟動
gitlab-runner-windows-amd64.exe run //執行
```
:::danger
注意!上面的每一行指令都是不可或缺的,只要你重新啟動 Runner 都要執行一遍
:::
這時 **cmd(命令提示字元)** 會顯示以下訊息:

:::info
執行後停在這邊是正常的,別在意。
:::
接下來可以嘗試 Push 一次至 Gitlab 看執行的狀況 **CI/CD** -> **Pipelines** 。基本上假如你是 Windows 的話,第一次都會失敗,並且 **cmd(命令提示字元)** 會顯示以下訊息:

這個的解決方法為,到 **gitlab-runner-windows-amd64.exe** 的根目錄裡,找到一個名為 ==config.toml== 的檔案,把 **shell = "pwsh"** 改成 **shell = "powershell"**,然後去 **cmd(命令提示字元)** Ctrl+C 跳出,執行以下指令來停止 Runner:
```shell=
gitlab-runner-windows-amd64.exe stop
```
之後在執行上面的三條指令,來開啟 Runner,然後再 Push 一次就會顯示成功了:

點進去 **Stage** 可以看到它執行的結果,以我們的例子就可以看到底下的結果:

---
### Step 6. 將單元測試讓 Runner 執行
想要讓把 Java 的自動整合放到 Gitlab 上的方法,非常簡單,根據我們以上的範例只要改動 ==.gitlab-ci.yml== 裡的設定就可以了,以下是改動後的結果 **(這裡我只改動 script 而已,其餘的都一樣)**:
```yaml=
stages:
- build
- refactoring
- test
- deploy
build-project:
stage: build
tags:
- main-runner
only:
- master
script:
- mvn compile # mvn 編譯程式指令
build-project-issue:
stage: build
tags:
- main-runner
- issue-runner
only:
- issue
script: # 可以多個 script
- mvn clean # mvn 專案清空
- mvn compile # mvn 重新編譯
refactoring-project:
stage: refactoring
tags:
- main-runner
only:
- refactor
script:
- mvn clean
- mvn compile
- mvn verify
test-project:
stage: test
tags:
- main-runner
only:
- master
- issue
- refactor
script:
- mvn test # mvn 單元測試指令
deploy-project:
stage: deploy
tags:
- main-runner
only:
- master
script:
- mvn package # mvn 專案打包
```
接下來去 Gitlab 的 **Pipelines** 就可以看到執行結果了:

可以看到這裡的輸出變成了 **Maven** 的訊息,接下來我們可以試試單元測試是否有效。一樣 修改 ==App.java== 的 ==sum 函式==,把它改成 ==a * b== 之後,再次 Push 察看結果。以下是更改後會跳出的結果:

我們可以看到推送至 Gitlab 上的新的程式碼在進行 **Testing** 的時候 <font color="red">**failed**</font> 了,這也就代表我們設定的單元測試有用,並且在撰寫來源程式碼時寫錯了邏輯。
大致上這就是整體的流程,剩下的 **分支(Branch)** 就留給各為自己去測試了,基本上流程相同,指不握要先建立分支,然後再推送,大致上流程都差不多。假如要在自動整合的部分有更多不同的功能可以在自己去研究。
# 結論
CI/CD 已經是目前程式開發的趨勢之一,擁有這些知識對於日後管理與開發進度上都會有很大的優勢。目前在 Gitlab 上提供的 CI/CD 功能已經非常的實用了,很適合在測試不同情況下的程式碼,也能適時地追中這些程式碼是否是有效的,也能讓多人開發上更為的便利。