为什么需要质量控制工具
无需多言,我偏执地认为,所有动态语言写成的项目,都应该使用 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 工具结合,不留死角。