自動化測試 CI/CD
這篇是記錄我在看鐵人賽 Python 與自動化測試的敲門磚 的過程
CI/CD 簡介
CI/CD 其實是指兩個部分,分別是 Continuous Integration (持續整合) 以及 Continuous Deployment (持續部屬)
CI 持續整合
在軟體開發的過程中,通常會由無數個開發人員一起工作,然而隨著程式碼以及人數的增加,專案會越來越難進行整合,這個時候我們就可以透過 CI 來進行。與其說 CI 是個工具,不如說 CI 是一種合作模式,藉由簡單的設定來讓 CI 工具替我們進行測試,就可以降低我們的專案在進行更新、整合時碰到問題的機率。
在 CI 執行的過程中,會建議每個開發人員每天上班前先做一次 pull 的動作,於每天下班前至少執行一次 push 的動作,以此確保 CI 的運行效率。
CD 持續部屬
每當我們透過 CI 將專案整合完成後,便可以透過 CD 來進行自動化的部屬,減少我們在測試與部屬之間所耗費的時間
CI/CD 常用工具
GitLab
於 GitLab 上提供了 CI/CD 的介面,藉由在某處部屬好的 docker image,即可進行 CI/CD,為目前主流的 CI/CD 工具
GitHub
GitHub 於 2019 年推出了 GitHub Actions,此工具可以協助我們進行 CI,不過由於此功能還算新,尚有許多功能不成熟,因此比較建議使用在小型專案的 CI 當中
Jenkins
為目前主流的 CD 工具,藉由 GitLab 進行 CI 後,會將程式碼打包到 Jenkins 進行自動化部屬
GitHub 設定
建立 yml file
進入 github 專案並點選 Actions 選項
需要點擊啟用 Actions 設定
點擊 New Workflow
在 Workflows 欄位底下輸入 “python” 進行搜尋
選擇 Python Application,並點選 Configure 選項
將跳轉後出現的頁面的程式碼滑到最底下,並將 pytest 更改為 echo “hello”
點選右上方 “Start Commit” 選項
點選 “Commit new file” 選項
測試若有設定過會出錯,需要新建立一個repository才會成功
頁面會自動跳轉回專案首頁,請點選回 “Actions”,就可以看到 github 按照剛剛建立的檔案建立了一個 CI 任務
點進此任務,並選擇 build 選項
點選 “Test with pytest” 部分即可看到剛剛修改的 echo “hello”
修改 yml
由於我們剛剛是直接在 github 上進行 commit 來新增 workflows,因此我們要先回到專案上執行 git pull 確保專案同步
執行完 git pull 後即可在專案上看到 “.github” 這個目錄,並且有 “workflows” 這個子目錄
“workflows” 目錄下會有一個 python-app.yml 檔案,這個就是我們等一下要修改的檔案
在修改 yml 前我們先建立幾個簡單的 test case 並存放到 day_22/test_demo.py 目錄下
1 | def test_export_report_1(): |
打開 python-app.yml
將剛剛的 echo “hello” 修改為 pytest -s -v ./day_22/test_demo.py
1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python |
察看結果
修改完成後,我們就可以將整個專案 push 到 Github 上,這個時候我們就可以回到剛剛的 “Actions” 頁面察看結果了
下圖中我們可以看到 Acitons 這邊多了一個任務,任務名稱會使用剛剛的 commit message 命名
點進去該任務後就可以查看 pytest 的執行結果了
python-app.yml
運行於指定的 branch 上
我們可以透過 on 參數來設定當哪個 branch 被推上 Github 上時要進行 CI 的動作,由於 CI 的進行也是需要耗費一定的資源,因此不太可能讓所有瑣碎的 branch 被推上去時都自動進行一次,透過設定 branches 可以指定那些 branch 被推上來時要執行 CI
補充:可以看到 on 底下有分為 push 以及 pull_request 兩個層級,分別代表著 Github 上的兩種協作方式
1 | on: |
建立 CI 任務
變數 | 功能 |
---|---|
runs-on | 為 CI 執行時最底下的一個 docker image 名稱,設定完成後 CI 會於執行時使用該 image 建立環境 |
steps | 為實際 CI 執行的細項,每一個細項開頭都會使用 “-“ 來表示 |
uses | 為為運行此 steps 時啟動的服務,為 docker image 名稱 |
name | 為此 step 的名稱 |
run | 為此 step 要執行的命令 |
1 | jobs: |
GitLab 設定
建立 CI/CD runner
在 GitLab 運行 CI/CD 時,同樣需要一個 runner 在背後執行,只是在 GitHub 的時候,他們幫我們做好了,因此我們不需要去碰到這塊,下面的方法為建立 runner 並和 GitLab 上的專案綁定的方法
接下來的步驟請先在要建立 runner 的電腦上安裝 docker
前往 GitLab 專案的 Setting 裡面的 CI/CD 頁面
Setting > CI/CD
找到 Runner 部分並打開,可以看到要和 runner 做連線的網址以及 token
打開 terminal
建立 docker volume
1 | docker volume create gitlab-runner |
啟動 docker 並將他連上剛剛建立的 volume
1 | docker run -d --name gitlab-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock -v gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner:latest |
使用下方指令進行 runner 與 GitLab 的連線
1 | docker run --rm -it -v gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner:latest register |
接下來會開始進行註冊程序,我們會以一個問題搭配一個回答的方式撰寫
註冊程序 | 回答 |
---|---|
Enter the GitLab instance URL | 寫上剛剛在 GitLab 上看到的 url |
Enter the registration token | 寫上剛剛在 GitLab 上看到的 token |
Enter a description for the runner | 寫上你想要為這個 runner 的描述,這邊使用 “nickchen1998_ithelp_2022_marathon” |
Enter tags for the runner | 為這個 runner 增加 tag,用來指派 CI/CD 任務用,這邊先寫上 “nickchen1998_ithelp_2022_marathon” |
Enter optional maintenance note for the runner | 這部份我們不需要,直接按 Enter |
Enter an executor | 這邊我們輸入 “docker”,用來作為 runner 運行的環境 |
Enter the default Docker image | 當 yaml 檔沒有指定要使用的 image 時,預設會使用的 image,這邊我們輸入 “python:latest” |
註冊完成
回到剛剛的 runner 頁面,我們就可以看到一個新的 runner 被建立給這個專案
設定環境變數
我們可以透過 Settings 內的 CI/CD 頁面裡面的 Variables 欄位進行環境變數的設定
Settings > CI/CD > Variables
點選 Add Variable 開始設定環境變數
依序輸入 key、value 並點選 Add Variable
可以看到成功新增的變數
設定 yaml 檔案
建立 .gitlab-ci.yml
在整個專案的 “最外層” 建立 gitlab-ci.yml 檔案
建立流程
直接將工作名稱寫在最外層,並於其下一層利用 stage 表示此工作階段的名稱
1 | execute-test: |
將要執行的指令依序寫在 scripts 後方
1 | execute-test: |
最後利用 tag 指定我們要執行這個任務的 runner (昨天文章有提到該如何建立 runner)
1 | execute-test: |
管理 stage
透過設定 stage 可以來管理我們要執行哪個部份的腳本
透過下面這段程式碼,我們就成功設定執行所有 stage 為 test 的任務了
1 | stages: |
成果展示
可以看到下圖中 GitLab 順利為我們生成一條 CI pipline
這邊要注意 runner 要指定對並且是執行中才會成功,不然會 Pending
Selenium 設定
修改 .gitlab-ci.yml 設定檔案
首先我們要替我們的 .gitlab-ci.yml 加上 service 表示我們要在指定的任務中運行其他服務
1 | stages: |
接著透過設定 services 底下的 name 參數來指定我們要使用哪個 docker image,我們會需要使用到 selenium/standalone-chrome 這個 image 來替我們建立一個可以遠端執行 Chrome 的環境
1 | stages: |
最後透過設定 alias 參數來為這個 services 進行命名
1 | stages: |
script 方面我有實際測試,
pip3 install -r ./requirements.txt
這行實際運行會出錯,我後來調整成這樣可以運行成功
script:
- pip3 install pytest
- pip3 install selenium
- pip3 install webdriver_manager
- pytest -s -v ./day_26/test_demo.py
建立 fixture
建立一個 conftest.py 並將 driver 的 fixture 寫在裡面
1 | import sys |
撰寫測試程式
1 | from selenium.webdriver import Remote, Chrome |