在这个到处都是“云里雾里”的云计算时代,如果不知道点OpenStack、Kubernetes等,出门都不好意思说自己是个程序猿了。

编码规范与代码静态检查

程序员最讨厌的四件事应该是:写注释,写文档,别人不写注释,别人不写文档。那么对于这样一个貌似很不好相处的群体,有人说,如果莎士比亚生活在当下,他会是一名科技作家,而且他座右铭会变成:“消灭世界上所有的程序员。”

消灭当然是做不到的,于是有一种所谓的编码规范的东西就被推上了前台,来预防程序员的各种个性与创造力。

对于达到百万行代码这个量级的OpenStack来说,它当然也必须有自己的一套编码规范来约束以及预防自己的众多开发者们是在把自己的创造力作用在构建一个蓬勃发展的开源云项目上,而不是一个其他的什么怪胎。

至于这个编码规范的内容,我们尽可打开http://legacy.python.org/dev/peps/pep-0008/这个链接去仔细阅读,这里的内容将着重放在OpenStack编码规范检查工具,及其相关的一个子项目Hacking上。

  • Python代码静态检查Flake8

对于OpenStack息息相关的Python代码静态检查来说,目前的工具主要有Pylint、Pep8、Pyflakes、Flake8等。

Pylint据评价属于稍显变态的一种,违背了Python开发者Happy Coding的倡导,或许这也是未被OpenStack社区所采纳的缘由。

至于Pep8则备受Python社区所推崇,负责Python代码风格的检查,据路边社报道,某些公司招聘Python工程师的要求有一条就是代码符合Pep8标准,具体可参见http://legacy.python.org/dev/peps/pep-0008/。

Pyflakes可以检查Python代码的逻辑错误。

最后粉墨登场的是Flake8,它是Pyflakes、Pep8以及NedBatchelder's McCabe script(关注Python代码复杂度的静态分析)三个工具的集大成者,综合封装了三者的功能,在简化操作的同时,还提供了扩展开发接口,详情参见https://pypi.python.org/pypi/flake8/2.0。

  • Hacking

有了上面的铺垫,我们很容易知道OpenStack使用的代码静态检查工具就是Flake8,并实现了一组扩展的Flake8插件来满足OpenStack的特殊需要,这组插件被单独作为一个子项目而存在,就是Hacking。

从上面Hacking源码中的setup.cfg文件内容可以看出,到目前为止,Hacking主要在注释、异常、文档、兼容性等编码规范方面实现了将近30个Flake8插件,详情参见http://docs.openstack.org/developer/hacking。

单元测试

OpenStack,单元测试又被称为SmallTests,粒度并不以开发者个人意愿以及对自身水平的自信而转移,起码从形式上追求着几近100%的代码覆盖率。也因此,我们提交一些新的代码时,必须要做的事情是往往提交更多的测试代码,而且常常花在单元测试上的时间要更多。

概括来说,OpenStack的单元测试追求的是速度、隔离以及可移植。对于速度,需要测试代码不和数据库、文件系统交互,也不能进行网络通信。另外,单元测试的粒度要足够小,确保一旦测试失败,能够很容易迅速地找到问题的根源。可移植是指测试代码不依赖于特定的硬件资源,能够让任何开发者去运行。

单元测试的代码位于每个项目源码树的<project>/tests/目录,遵循oslo.test库提供的基础框架。通常单元测试的代码需要专注在对核心实现逻辑的测试上,如果需要测试的代码引入了其他的依赖,比如依赖于某个特定的环境,我们在编写单元测试代码的过程中,花费时间最多的可能就是如何隔离这些依赖,否则,即使测试失败,也很难定位出问题所在。

对SUT(the system under test,被测试系统)完成隔离的基本原则是引入Test Double(类似特技替身演员),用Test Double来替代测试中的每一个依赖。

有多种类型的TestDouble,比如Mock对象、Fake对象等,它们可以作为数据库、I/O、以及网络等对象的替身,并将相应的操作隔离掉,在测试运行过程中,当执行到这些操作时,不会深入方法内部去执行,而是直接返回我们假设的一个值。

  • Tox

执行单元测试的途径有两种:Tox或者项目源码树根目录下的run_tests.sh脚本。不过通常我们使用的都是Tox。

Tox是个标准的 virtualenv(Virtual Python Environmentbuilder) 管理器和命令行测试工具。可以用于:检查软件包能否在不同的Python版本或解释器下正常安装;在不同的环境中运行运行测试代码;作为持续集成服务器的前端,大大减少测试工作所需时间。

每个项目源码树的根目录下都有一个tox配置文件tox.ini,对于我们的开发,通常只需要运行下面的两个tox命令。

$ tox –e pep8 //代码规范检查

$ tox –e py36 -vv

第一次执行时,会自动安装一些依赖的软件包,如果自动安装失败,我们需要根据提示信息手动进行安装。

持续集成

OpenStack使用Jenkins搭建自己的持续集成服务器。对于一般的小团队开发来说,通常可能会先commit然后再跑CI,而OpenStack则不同,它通过Gerrit首先对每个commit进行review,这个时候,Jenkins会执行整个CI的过程,通过会“+1”,否则标记“-1”,如下图所示。

上图所示即为Jenkins的一次执行结果,Jenkins栏表明了Jenkins针对这个commit都进行哪些测试以及结果,这个列表以gate-ceilometer-为前缀的是tox的测试结果,比如gate-ceilometer-pep8对应的即是运行“tox –epep8”。

  • Tempest

根据上文的描述,Jenkins背后需要依托大量的单元测试以及集成测试代码,单元测试的代码位于各个项目自身的源码树里,而OpenStack的集成测试则是使用Tempest作为框架。

Tempest是OpenStack项目中一个独立的项目,它的源码位于/opt/stack/tempest/(使用Devstack部署开发环境),包含了大量的测试用例。

代码评审

对于OpenStack来说,为了保证代码评审的有效进行,首先需要做的是为我们寻找合适的道具“橡皮鸭”,然后提供一个将这些道具和我们有效联结起来的平台。

这些道具自然就是分散在全球各地的OpenStack开发者们,与橡皮鸭不同的是,他们会发表自己的意见和看法。而这个联结的平台就是Gerrit。

  • Gerrit工作流程

Android在 Git 的使用上有两个重要的创新:一个是为多版本库协同而引入的repo(对git使用的封装),另一个就是 Gerrit——代码审核服务器。Gerrit 为Git 引入的代码审核是强制性的,也就是说除非特别的授权设置,向Git版本库的推送(Push)必须要经过 Gerrit 服务器,修订必须经过代码审核的一套工作流程之后,才可能经批准并纳入正式代码库中。

OpenStack也将Gerrit引入到自己的代码管理里,工作流程大体和Android对Gerrit的使用相同,区别是过程更为简洁,而且使用了Jenkins来完成自动化测试。

首先我们在本地代码仓库中做出自己的修改,然后我们能够很容易通过git 命令(或git-review封装)将自己的代码push到Gerrit管理下的Git版本库。Jenkins将对我们的提交进行自动化测试并给出反馈,其他开发者也能够使用Gerrit对我们的代码给出他们的注释与反馈,其中,项目的maintainer(OpenStack中称为Core Developer)的反馈权重更高(+2),如果你的patch能够得到两个“+2”,那么恭喜你,你的patch将被merge到OpenStack的源码树里。

所有这些注释、质疑、反馈、变更等代码评审的工作都通过Web界面来完成,因此Web服务器是Gerrit的重要组件,Gerrit通过Web服务器实现对整个评审工作流的控制。下面的图即为针对某一个提交的评审页面。

 

  • git-review

Gerrit做了大量的工作来保证代码从提交、评审、修订、再提交这个流水线作业的顺利有序进行,我们开发者也需要在其中小心翼翼地配合,这种谨慎与琐碎当然不太符合程序员们的审美观,于是一个叫git-review的工具出现了,它封装了与Gerrit打交道的所有细节,我们需要做的只是开心地执行commit与review这两个git的子命令,然后在Web图形界面上去看图说话,根本不用去琢磨有关Gerrit如何“吃喝拉撒”的种种细节。

为了对一个项目使用git-review,我们需要首先对该项目进行设置,比如对于nova:

$ cd nova

$ git review -s

git-review会检查你是否能够登录Gerrit,如果不能,它会向你索要你的Gerrit账号。如果你看到“We don't know whereyour gerrit is.”这样的错误,就需要执行下面的命令:

$ git remote add gerrit ssh://<username>@review.opendev.org:29418/openstack/nova.git

然后我们最经常做的事情,除了修改代码之外,就是按照一个熟练工的标准执行下面的这些命令:

$ git checkout –b branch-name

$ git commit –a (--amend)

$ git review

至于git-review如何去安装在此不作赘述,因为大多数Linux发行版已经将其集成到了自己的包管理器。

 

相关阅读

代码质量保证体系(上)

代码质量保证体系(下)

喜欢的话,欢迎扫码关(打)注(赏) ^-^

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐