為什麼需要質量控制工具
無需多言,我偏執地認為,所有動態語言寫成的專案,都應該使用 XXLint 之類的工具,該暴露的錯誤能提前就提前。
甚至,所有專案在 commit 之前都需要做兩件事情:
- lint 檢查
- UT
動態語言是邊解釋邊執行,缺乏編譯期。這是劣勢也是優勢,這是優勢也是劣勢。
Python 中,常用的質量控制工具就是:pytest(或其他),Pylint,flake8(較強大),本文介紹後兩者。
如何使用
如果沒有提及這兩款工具,那麼一個自然的想法是:給定原始碼目錄 src,工具要能夠檢查 src 所有符合要求的檔案
,即:
flake8 $OPTIONS $src
複製程式碼
事實上,這些工具就是這麼工作的。指定檔案或目錄,然後它幫你檢查。
與工作流的整合
命令列的使用尚且簡單,不過沒有人這麼使用(這仍然是重複性勞動),冗長的文件也沒幾個人喜歡閱讀,所以最佳實踐才是重點。
我個人的最佳實踐是:與 git pre-commit 結合,如果檢查不過,就不讓 commit。
思路大概有如下幾種:
- pre-commit 使用 bash 指令碼編寫,呼叫對應命令執行
- pre-commit 使用 Python 指令碼編寫(個人比較偏好這種,主要是對 Shell 實在愛不起來)
如果使用 Python 指令碼,我比較喜歡使用 Fabric 來組織我的程式碼( Fabric 簡單小巧,夠用)。
比如專案結構一般會這樣:
.pylintrc
.flake8
fabfile.py
project/
tests/
docs/
複製程式碼
那麼 fabfile.py 的內容大致就是
@task
def runpylint():
local(`pylint project/`)
@task
def runflake8():
local(`flake8 project/`)
@task
def runpytest():
pass
@task
def runfabfile():
execute(runpylint)
execute(runflake8)
execute(runpytest)
手動執行:
fab runfabfile
複製程式碼
那麼 .git/hooks/pre-commit
的內容就是:
#!/usr/bin/env bash
function _runfab() {
fab runfabfile
if [[ "$?" == 0 ]]; then
return 0
else
return 1
fi
}
_runfab
複製程式碼
總結
工具的使用,自然不是重點,原則才是。我覺得比較重要的幾條原則是:
- 一切從嚴。比如 Pylint 的
C
級別錯誤也不能放過(不過有些檢查確實多餘,可以 disable 掉,但是 disable 的數量應當越少越好)。 - 不僅與 pre-commit 結合,而且與 CI 工具結合,不留死角。