iT邦幫忙

3

[不做怎麼知道系列之Android開發者的30天後端養成故事 Day13] - 老闆,來碗自動化測試吧 #讓科技幫你省時間 #持續整合 #CircleCI

Sam 2020-02-19 22:26:45 ‧ 7003 瀏覽
  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20200219/20124548jW3Xt7BcLq.png

哈囉,我們又見面了,今天我們來玩玩看 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。

我的流程是這樣的

  • 創一個新的 Django Project & Django App
  • 把 Django project 上傳到 Github
  • 註冊 CircleCI & 綁定 Github
  • 把 circleci-project-setup 的分支 merge 回去 master
  • 所以先 git checkout circleci-project-setup branch
  • 修改 config.yml (改成我們想要的 CI 流程)
  • Push 上去 Github → CircleCI 就會執行測試
    (因為現在 test.py 還沒有東西,所以測試會過很正常)
  • 新增一個 view 的 test case (測試 home page 的 status code)
  • 再一次 push 上去 (測試成功,耶)

看起來有點複雜,可是其實很簡單 der,只要抓住兩個重點

  1. config.yml 怎麼寫,每一行代表什麼意思
  2. CircleCI 對你的 Github 做了些什麼?

那麼,我們就開始囉 ~

創一個新的 Django Project & Django App

這部分詳情可以參考 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

把 Django project 上傳到 Github

  • 先到 Github 創個 Repository,再到 cmd

    $ git add .

    $ git commit -m "Init"

    $ git remote add origin https://github.com/yourgithub/yourreponame.git

註冊 CircleCI & 綁定 Github

當你在 CircleCI 內連結到 Github 帳號後,就會列出你所有的 repository,我的 Github Repository 叫做 CircleCI_Demo_Web。

https://ithelp.ithome.com.tw/upload/images/20200219/20124548opKDLO2Cgc.png

按下 Set Up Project 後,會在你的 Github repo 產生一個新的分支,並且加入一個 .circleci 的資料夾,裡面有個 config.yml 檔,這個 config 檔先不要理它,按下 Add Config 按鈕之後

https://ithelp.ithome.com.tw/upload/images/20200219/20124548zyHVjbuFMN.png

就會自動幫你進行第一次的 pipeline,然後就 FAILED 了,覺得 CircleCI 的預設 config 檔實在是有點爛,一點都沒有 Hello World 的感覺

https://ithelp.ithome.com.tw/upload/images/20200219/20124548PxgJj5MLTY.png

把 circleci-project-setup 的分支 merge 回去 master

是不是想這樣做 ? 可惜,因為 Pipeline FAILED,所以你無法 pull request

https://ithelp.ithome.com.tw/upload/images/20200219/20124548krZR8l20TA.png

修改 config.yml (改成我們想要的 CI 流程)

既然無法 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 這一行而已,其他都是前置步驟

Push 上去 Github → CircleCI 就會執行測試

  • 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 還沒有寫任何的測試,所以測試會過很正常

https://ithelp.ithome.com.tw/upload/images/20200219/20124548toaXq6MQXA.png

我的 commit 多做了好幾次 XD,原本以為要在 config 裡面寫 $ python manage.py runserver,之後才能跑 $ python manage.py test,結果不需要,所以才會有第三筆灰色 CANCELED,做到這邊,你應該會看到綠色勾勾才對,因為現在 test.py 裡面還沒有寫測試,怎麼測都應該要會過

新增一個 view 的 test case (測試 home page 的 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/ 看看有沒有很簡單的網頁出現

https://ithelp.ithome.com.tw/upload/images/20200219/20124548SDsrU2ujIm.png

表示 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 可以這樣做,還是說其他框架也能做到?

再一次 push 上去 (測試成功,耶)

https://ithelp.ithome.com.tw/upload/images/20200219/20124548U9iOJlbl9J.png

單日心得總結

如果看完還是無法成功的話,可以參考 (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,這是我的 不做怎麼知道系列 文章,我們 明天見。



圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言