Django項(xiàng)目使用CircleCI的方法示例
自從認(rèn)識(shí)了 CircleCI 之后,基本上都在用這個(gè)了。相比于之前用的travis-ci ,CircleCI 丑是丑了點(diǎn),但是相比與 travis 有幾點(diǎn)好處:
- CircleCI 基于 docker image 的,怎么做隔離的不太清楚,有可能是在虛擬機(jī)上面執(zhí)行 docker 來(lái)做隔離的,而 travis 還是基于 VM。這樣好的好處是,CircleCI 提供了很多 image,你可以組合出來(lái)很多服務(wù)。比如 Django 項(xiàng)目用到了 redis 和 MySQL,你只要在 yaml 里面加上這兩個(gè) image 就好了,而 travis 要在 VM 里面處理好服務(wù)依賴。不僅不方便,每次執(zhí)行速度也慢很多。
- CircleCI 支持 private repo,travis 只支持開源 repo。
但要說(shuō)缺點(diǎn)的話,CircleCI 用戶體驗(yàn)實(shí)在不如 travis,配置比較復(fù)雜。每次用都會(huì)多少踩一些坑。這篇文章介紹一下一個(gè) Django 項(xiàng)目接入的過程,和其中一些要注意的坑。
1. 設(shè)定好 Django 項(xiàng)目的測(cè)試和依賴
以前 Django 測(cè)試用的是 Django 自帶的 manage.py 里面的 test. 后來(lái)發(fā)現(xiàn)還是 pytest 比較好:插件多、模板代碼少些很多,fixture 的設(shè)計(jì)比較合理,測(cè)試中使用到 db 需要明確聲明,否則無(wú)法 access db,這樣更加 explicit,測(cè)試執(zhí)行的速度也更快。
除了 pytest,其他的還有一些依賴, test-requirements.txt 文件的內(nèi)容如下:
File: test-requirements.txt -r dev-requirements.txt factory_boy pytest-cov pytest-django
其中 pytest-django 是 pytest 繼承到 Django 中去了,pytest-cov 是追蹤測(cè)試覆蓋率的,factory_boy 是可以根據(jù) Django 的 ORM 自動(dòng)生產(chǎn)測(cè)試需要的 Model (這個(gè)強(qiáng)烈推薦,如果不用這個(gè)的話,需要寫一推 json 來(lái)事先定義好測(cè)試用的 Model,后續(xù)維護(hù)也很費(fèi)勁,如果改了一個(gè)不需要測(cè)試的 Model 的 Field,這些 json 也需要維護(hù))。
然后運(yùn)行 Django 測(cè)試,使用 pytest 命令就好了:
$ DJANGO_SETTINGS_MODULE = myproject.settings.testing pytest --reuse-db --cov-config=.coveragerc --cov=. --cov-report=html --junitxml=test-reports/junit.xml
這個(gè)命令太長(zhǎng)了,我們可以將環(huán)境變量和命令參數(shù)寫到 pytest.ini 文件中去:
File: pytest.ini [pytest] DJANGO_SETTINGS_MODULE = easycron.settings.testing addopts = --reuse-db --cov-config=.coveragerc --cov=. --cov-report=html --junitxml=test-reports/junit.xml
這樣每次測(cè)試,使用 pytest 這個(gè)命令就可以了,參數(shù)和環(huán)境變量會(huì)自動(dòng)設(shè)置。
解釋一下每個(gè)參數(shù)是干嘛用的:
- 第一行是 Django 環(huán)境變量,用來(lái)區(qū)分測(cè)試使用的 django.conf.settings 和開發(fā)、生產(chǎn)用的;
- –resuse-db :pytest 測(cè)試復(fù)用DB,不必每次都創(chuàng)建然后執(zhí)行 migrations,對(duì)測(cè)試執(zhí)行速度的提升非常明顯。但是在 CircleCI 上運(yùn)行測(cè)試,由于每次 MySQL 都是一個(gè)新的鏡像實(shí)例,所以還是要每次新建數(shù)據(jù)庫(kù),執(zhí)行 migrations 的。這個(gè)參數(shù)只是在本地執(zhí)行的時(shí)候有用;
- –cov-config / –cov :這個(gè)是追蹤測(cè)試覆蓋率的 coverage.py 使用的配置文件,和要追蹤測(cè)試覆蓋率的文件夾;
- –cov-report :生成測(cè)試覆蓋率的格式,每次運(yùn)行完測(cè)試之后,生成覆蓋率測(cè)試的文件。在 CircleCI 上我們可以設(shè)置測(cè)試運(yùn)行完之后將這些文件上傳至 artifacts 上去,可以在瀏覽器看這些文件;
- –junitxml : 測(cè)試的 Summary,也可以在 CircleCI 上展示;
以上就是項(xiàng)目中測(cè)試的配置,現(xiàn)在運(yùn)行 pytest 可以自動(dòng)發(fā)現(xiàn)項(xiàng)目中的測(cè)試用例執(zhí)行了,并且測(cè)試完成后會(huì)生成測(cè)試報(bào)告。
接下來(lái)介紹如何在 CircleCI 上配置,實(shí)現(xiàn)每次 git push 之后自動(dòng)執(zhí)行代碼。
2. 在 CircleCI 開啟 CI 和設(shè)置運(yùn)行環(huán)境
接入的方式分兩步,根據(jù) CircleCI 的指引就可以:
- 用 Github 賬戶登陸 CircleCI,然后在 CircleCI 上導(dǎo)入 Github 的項(xiàng)目;
- 在項(xiàng)目中添加 .circleci/config.yml 配置文件,git push,就會(huì)自動(dòng)觸發(fā) CircleCI 的 build 了。
其中配置文件以我的這個(gè)項(xiàng)目為例,配置文件如下(基本上是拿 CircleCI 的配置模板修改了一下,保留了注釋):
# Python CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-python/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
# use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
- image: circleci/python:3.7.1
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
- image: circleci/redis:5.0.1
- image: circleci/mysql:8.0.12
environment:
MYSQL_DATABASE: test_easycron_
MYSQL_ROOT_HOST: "%"
MYSQL_USER: easycron
MYSQL_PASSWORD: 123
command: [--default-authentication-plugin=mysql_native_password]
working_directory: ~/repo
steps:
- checkout
- run:
name: install dockerize
command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
environment:
DOCKERIZE_VERSION: v0.3.0
- run:
name: Wait for db
command: dockerize -wait tcp://localhost:3306 -timeout 1m
# Download and cache dependencies
- restore_cache:
keys:
- v3-dependencies-{{ checksum "test-requirements.txt" }}
# fallback to using the latest cache if no exact match is found
- v3-dependencies-
- run:
name: install dependencies
command: |
python3 -m venv ~/venv
. ~/venv/bin/activate
pip install -r test-requirements.txt
- save_cache:
paths:
- ~/venv
key: v3-dependencies-{{ checksum "test-requirements.txt" }}
# run tests!
# this example uses Django's built-in test-runner
# other common Python testing frameworks include pytest and nose
# https://pytest.org
# https://nose.readthedocs.io
- run:
name: run tests
command: |
. ~/venv/bin/activate
pytest
- store_test_results:
path: test-reports
- store_artifacts:
path: htmlcov
destination: htmlcov
前面說(shuō)過 CircleCI 是基于 Docker 的,它的一個(gè)好處就是:如果你需要 MySQL、Redis 之類的服務(wù),只要在 docker 這里聲明就好了,CircleCI 在啟動(dòng)測(cè)試的時(shí)候會(huì)幫你啟動(dòng)這些容器。
build:docker 這里的配置就是用到的服務(wù),用到哪個(gè)配置就寫上 CircleCI 的 image 就好了,常用的都有,比較豐富。后面的 steps 來(lái)定義 CI 的步驟,一些事先定義好的 steps 可以參考下 文檔 , 比如 clone 代碼之類的就不需要自己實(shí)現(xiàn)了。
但是這里有一些挺坑的地方,需要注意。
使用 CircleCI 官方 MySQL 這個(gè) image 需要設(shè)置驗(yàn)證方式,不然的話會(huì)遇到以下這個(gè)錯(cuò)誤:
E MySQLdb._exceptions.OperationalError: (2059, "Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory")
MySQL,redis 等都不能通過 .sock 文件訪問,訪問的時(shí)候不要使用 localhost,使用 IP。因?yàn)楸举|(zhì)上這不是在同一個(gè) image 啟動(dòng)的,測(cè)試所在的容器并不會(huì)有這些服務(wù)的 sock 文件,實(shí)際上是啟動(dòng)了不同的 image 然后通過 docker 的 network 放在一組,實(shí)現(xiàn)了訪問。
還有一個(gè)巨坑的地方是,有時(shí)候你依賴的服務(wù)還沒準(zhǔn)備好,測(cè)試就開始執(zhí)行了。我用的時(shí)候發(fā)現(xiàn)有的時(shí)候訪問 MySQL 端口不通,有的時(shí)候卻是通的。解決的方式也很挫,就是 31-38 行,使用 dockerize block 住這個(gè) step,不斷檢查端口是否接受連接了。端口通了才繼續(xù)執(zhí)行后面的步驟。
這里為了加快測(cè)試的執(zhí)行速度,可以將創(chuàng)建的 venv 緩存起來(lái),參考上面的 restore cache 和 save cache 那一步。需要注意的是 key 加上了 checksum,這樣依賴文件更改的時(shí)候可以自動(dòng)重新安裝。有個(gè)小坑的地方是 CircleCI 竟然沒提供刪除 cache 的功能,所以我的 key 加上了 v3 ,如果想棄用之前的 cache 的話,只要升級(jí)到 v4 就好了,cache 找不到自動(dòng)安裝新的。
最后兩步是上傳測(cè)試 Summary 和覆蓋率文件。效果如下:

test summary 展示

測(cè)試覆蓋率文件
注意 venv 不要建立在 working_directory 下面,不然你的 venv 里面的庫(kù)也會(huì)被追蹤測(cè)試覆蓋率。
最后再吐槽一下 Artifacts 沒有自動(dòng)打開 index.html 的按鈕,每次都需要自己找到這個(gè)文件點(diǎn)開,有點(diǎn)反人類。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
pyecharts繪制各種數(shù)據(jù)可視化圖表案例附效果+代碼
這篇文章主要介紹了pyecharts繪制各種數(shù)據(jù)可視化圖表案例并附效果和代碼,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,感興趣的小伙伴可以參考一下2022-06-06
Python虛擬環(huán)境virtualenv的安裝與使用詳解
virtualenv可以用來(lái)管理互不干擾的獨(dú)立python虛擬環(huán)境,在有些場(chǎng)景下非常有用,下面這篇文章主要給大家介紹了Python虛擬環(huán)境virtualenv安裝與使用的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-05-05
Python flask框架定時(shí)任務(wù)apscheduler應(yīng)用介紹
Flask是Python社區(qū)非常流行的一個(gè)Web開發(fā)框架,本文將嘗試將介紹APScheduler應(yīng)用于Flask之中實(shí)現(xiàn)定時(shí)任務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-10-10
小白教你PyCharm從下載到安裝再到科學(xué)使用PyCharm2020最新激活碼
這篇文章主要介紹了PyCharm最新版從下載到安裝再到科學(xué)使用PyCharm2020最新激活碼,需要的朋友可以參考下2020-09-09
使用python編寫批量卸載手機(jī)中安裝的android應(yīng)用腳本
該腳本的功能是卸載android手機(jī)中安裝的所有第三方應(yīng)用,主要是使用adb shell pm、adb uninstall 命令,需要的朋友可以參考下2014-07-07
python實(shí)現(xiàn)雪花飄落效果實(shí)例講解
在本篇文章里小編給大家整理了關(guān)于python實(shí)現(xiàn)雪花飄落效果的相關(guān)實(shí)例內(nèi)容,以及代碼寫法,需要的朋友們參考下。2019-06-06
python游戲?qū)崙?zhàn)項(xiàng)目之童年經(jīng)典超級(jí)瑪麗
史上十大最經(jīng)典小霸王游戲中魂斗羅只能排在第二,那么第一是誰(shuí)?最經(jīng)典最風(fēng)靡的當(dāng)屬超級(jí)瑪麗,那個(gè)戴帽子的大胡子穿著背帶褲的馬里奧哪個(gè)不認(rèn)得,小編帶你用python實(shí)現(xiàn)超級(jí)瑪麗緬懷童年2021-09-09

