哈囉,我們又見面了,今天我們來玩玩看 CircleCI
,體驗一下什麼是 持續整合(Continuous Integration
, CI),為什麼需要 自動化測試,跟 持續整合 有什麼關係,以及為什麼需要 持續整合。
Day11 玩過了測試,會不會覺得每次完成一段程式碼,還需要自己執行測試檔,重複做同一件事,是一件有點麻煩的事 ?!,所以俗話說得好「科技始於懶惰」,這時候我們就想「阿~ 如果有人可以閒閒沒事等我寫完程式,再幫我跑測試,然後再跟我說結果,就好了~~~」,所以有種方法是,拜託老闆去請一個測試人員,然後我再把 code 丟給他去測試,但是,現在科技進步,你可以讓工具幫你做這件事 !
所以 自動化測試 就出現了,自動化的方法有很多種,我們今天談的是 持續整合
概念中的自動化測試,簡單來說,這個自動化的流程是這樣的,當你把完成的功能程式碼 和 測試程式碼,推到 Github 上(你也可以選擇 pull request 才執行測試),持續整合的工具會檢測到你的程式碼更新,就根據你新的程式碼來跑測試,最後再把結果透過你設定的通知方式,來告訴你這次的測試結果,聽起來是不是挺方便的阿。
CI
)是什麼 ?持續整合是一種概念,其中 整合 的意思是 新程式碼 與 舊程式碼 的整合,而 持續 的意思是希望能夠在專案的開發過程中,不斷地進行新、舊程式碼整合,每個團隊能夠決定這個 持續 的頻率,可以是每個 commit,可以是每個 pull request,可以是只有 master branch 的每個 commit,依照不同的 CI 平台,可以設定的程度也不一樣。
簡單來說,持續整合,就是幫你做好 開發 與 測試 之間的銜接,當你寫好一段 code,把它 push 到 github
上,由持續整合的工具來幫你做測試,工具再透過 slack
或 email
告訴你測試結果,讓開發與測試的一切流程比使用飛柔的頭髮還要順。所謂的持續,表示的是,不是等到你把大功能都做好了,才一次做測試,而是每當完成一個段落,就由工具來持續地檢查你新完成的程式碼,跟原有的程式碼是否相容,有沒有影響到你的原有功能。
你所需要做的就是,把 code push 到 github
,喝一口水,然後你就知道這段 code 到底有沒有問題了,沒有問題就繼續開發或重構,有問題就回去找 bug。
如果用一句話來表示,就是 持續地 確保 你的程式碼每次更新,都是功能正常的,以上只是針對個人開發的角度來看,當這件事情在多人協作時,更加不容易達到,隨著團隊人數增加,確保程式碼品質的難度,成指數型上升,更何況還有離職與新進人員的經手。
簡言之,讓我們專注在開發,確保品質這種事情就交給工具來做吧。
CircleCI
?關於為什麼要選擇 CircleCI
而不是其他的 CI/CD 平台,可以參考 CircleCI 使用經驗談 | Hwchiu Learning Note。
首先,需要先有測試,再告訴 CI 你的執行環境,最後就是在 CI 執行我們的專案,並且執行測試。其中測試包含各種層級的測試方法,從單元測試到整合測試,依照專案規模來決定要執行到什麼層級的測試,還有看你的時間夠不夠寫這麼多測試 XD。
CircleCI
在這邊我們先展示把全新的 django 專案整合到 CircleCI。
Github
CircleCI
& 綁定 Github
circleci-project-setup
的分支 merge 回去 mastercircleci-project-setup
branchconfig.yml
(改成我們想要的 CI 流程)Github
→ CircleCI
就會執行測試test.py
還沒有東西,所以測試會過很正常)status code
)config.yml
怎麼寫,每一行代表什麼意思那麼,我們就開始囉 ~
這部分詳情可以參考 Day4,在這邊只列出大致流程,作為備忘或參考
進到 python virtual environment
$ django-env\Scripts\activate
利用已安裝的 django,創建新的 project
$ django-admin startproject demo_web_project
進到 project 目錄裡,並創建新的 app 在 project 裡
$ cd demo_web_project && django-admin startapp
先到 Github 創個 Repository,再到 cmd
$ git add .
$ git commit -m "Init"
$ git remote add origin https://github.com/yourgithub/yourreponame.git
當你在 CircleCI 內連結到 Github 帳號後,就會列出你所有的 repository,我的 Github Repository 叫做 CircleCI_Demo_Web
。
按下 Set Up Project
後,會在你的 Github repo 產生一個新的分支,並且加入一個 .circleci
的資料夾,裡面有個 config.yml
檔,這個 config 檔先不要理它,按下 Add Config
按鈕之後
就會自動幫你進行第一次的 pipeline,然後就 FAILED
了,覺得 CircleCI 的預設 config 檔實在是有點爛,一點都沒有 Hello World 的感覺
是不是想這樣做 ? 可惜,因為 Pipeline FAILED,所以你無法 pull request
既然無法 merge 回去 master,那我們就把 config 修好再回去 master 吧
那就在本地端先 checkout 到 circleci-project-setup 的 branch 吧
$ git checkout remote circleci-project-setup
修改 .circleci/config.yml
# CircleCI 的版本
version: 2.1
jobs:
# 把這個工作取名叫做 `build-and-test`
build-and-test:
# 告訴 circleci,我需要 docker 的環境
docker:
# 告訴 circleci,我要用 Docker Hub 上的
# `circleci/python` 的映像檔
# 而且 tag 是要 3.8.1 的 tag
- image: circleci/python:3.8.1
steps:
# 第一步
- checkout
# 第二步
- run:
# 先安裝 django
command: |
pip install django~=3.0.3
# 只是幫這個指令取名字而已
name: Install
# 第三步
- run:
# 執行 django 的測試
command: |
python manage.py test
name: Test
# 告訴 CircleCI,我要執行的工作,
# 總共要執行 `build-and-test` 這一個工作
workflows:
main:
jobs:
- build-and-test
總體來講,就是要執行 python manage.py test
這一行而已,其他都是前置步驟
Git Commit & Push
$ git add .
$ git commit -m "Update config.yml: Run django test"
$ git push -u origin circleci-project-setup
切換到 CircleCI 的 Pipeline 頁面 (為了確認執行成功)
因為現在 test.py
還沒有寫任何的測試,所以測試會過很正常
我的 commit 多做了好幾次 XD,原本以為要在 config 裡面寫 $ python manage.py runserver
,之後才能跑 $ python manage.py test
,結果不需要,所以才會有第三筆灰色 CANCELED
,做到這邊,你應該會看到綠色勾勾才對,因為現在 test.py
裡面還沒有寫測試,怎麼測都應該要會過
status code
)tests.py
from django.test import TestCase
class TestHomePageView(TestCase):
def test_reachable_home(self):
response = self.client.get('/home/')
self.assertEqual(response.status_code, 200)
views.py
from django.shortcuts import render
def home_view(request):
return render(request, 'home.html', {})
在 yourapp/
下新增 templates
的資料夾 並 新增一個 home.html
,這邊不懂的話可以參考 Day5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
Hi, circleci and django
</body>
</html>
urls.py
from django.contrib import admin
from django.urls import path
from demo_app.views import home_view
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', home_view)
]
settings.py
...
INSTALL_APP = [
...,
'yourappname'
]
...
在本地端跑跑看
$ python manage.py runserver
用瀏覽器到 http://127.0.0.1:8000/home/ 看看有沒有很簡單的網頁出現
表示 code 沒問題
執行測試
$ python manage.py test
$ python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.011s
OK
Destroying test database for alias 'default'...
至於在執行 test 之前,需不需要先 runserver ? 我自己在測試的時候,不需要 先 runserver 就能啟動測試,而且連頁面的 status code 這種測試,都可以在不 runserver 的情況下測試完成。我有在 stackoverflow 發問 這個問題,大家有興趣可以關注一下後續發展,如果大家有什麼想法,麻煩跟我講一下,同時我也很好奇,只有 django 可以這樣做,還是說其他框架也能做到?
如果看完還是無法成功的話,可以參考 (2019) Continuous integration for Django projects,我是參考到這篇才成功的,嗚嗚。
其實我最先成功是參考上面那篇,把原本的 django 專案放到 CircleCI
上,能成功連動、進行測試,可是,我完全不知道為什麼可以跑得動,只好努力把 config.yml
研究一下,然後再創一個新專案,重新用我的理解去做一個 config 出來,這就是為什麼今天這篇是用全新專案來講解 XD。
在做的時候還有一個問題是,我一直搞不懂 到底要不要把 Dockerfile
包在專案裡面讓 CircleCI
的 config.yml
去讀取阿 ?! 實驗證明,在 config.yml
裡的 docker 那一欄是直接從 Docker Hub
下載的,因為我的第一個成功的專案,裡面就包了各種奇奇怪怪的東西,包括 python virtual environment、dockerfile,覺得那個專案已經髒掉了 XD,所以才做全新專案,用個最乾淨的方式試試看。
好的,這篇我自認為非常難閱讀,太雜、太亂,想解釋觀念、又想帶實作、又想解釋指令,大家就多擔待 QQ
我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。