您的位置:首页 > 编程语言 > Python开发

用Python编写干净 可测试 高质量的代码

2014-12-22 23:31 363 查看
用Python编写干净 可测试 高质量的代码

  您不必听信我的观点,也不必直接研究代码,可以通过其他方法明显地看出这两种风格之间的差异。第一种方法是实际度量得到测试的代码行数。Nose 是一种流行的 Python 单元测试框架扩展,它可以方便地自动运行一批测试和插件,比如度量代码覆盖率。通过在开发期间度量代码覆盖率,会很快看出对于由大函数组成、包含深度嵌套的逻辑、以非一般化方式构建的代码来说,测试覆盖率几乎不可能达到 100%。

  度量差异的第二种方法是使用静态分析工具。有几种流行的 Python 工具可以为 Python 开发人员提供多种指标,从一般性代码质量指标到重复代码或复杂度等特殊指标。可以用 pygenie 或 pymetrics 度量代码的圈(cyclomatic)复杂度(见 参考资料)。

  下面是对相当简单的 “干净” 代码运行 pygenie 的结果示例:

  pygenie 的圈复杂度输出

% python pygenie.py complexity --verbose highlight spy

File: /Users/ngift/Documents/src/highlight.py

Type Name Complexity

----------------------------------------------------------------------------------------

M HighlightDocumentOperations._create_snippit 3

M HighlightDocumentOperations._reconstruct_document_string 3

M HighlightDocumentOperations._doc_to_sentences 2

M HighlightDocumentOperations._querystring_to_dict 2

M HighlightDocumentOperations._word_frequency_sort 2

M HighlightDocumentOperations.highlight_doc 2

X /Users/ngift/Documents/src/highlight.py 1

C HighlightDocumentOperations 1

M HighlightDocumentOperations.__init__ 1

M HighlightDocumentOperations._custom_highlight_tag 1

M HighlightDocumentOperations._score_sentences 1

M HighlightDocumentOperations._multiple_string_replace 1

  正如在此示例中看到的,每个方法都极其简单,复杂度都低于 10,这符合 McCabe 提出的原则。在我的从业经历中,我见过在没有测试的情况下编写的巨大函数,它们的复杂度超过 140,长度超过 1200 行。毫无疑问,根本不可能测试这样的代码。实际上甚至无法确认它是有效的,也不可能重构它。如果代码的作者一直牢记测试,在保持 100% 测试覆盖率的情况下编写相同的逻辑,就不可能出现如此高的复杂度。

  干净代码假想解决方案

  现在,我们来看一个完整的源代码示例以及相配的单元测试和功能性测试,看看它的实际作用以及为什么说这样的代码是干净的。按照严格的指标,“干净” 的合理定义是代码满足以下要求:接近 100% 测试覆盖率;所有类和方法的圈复杂度都低于 10;用 pylint 得到的评分接近 10.0。下面的示例使用 nose 在 highlight 模块上执行单元测试和 doctest 覆盖率检查:

  运行 nosetests 和覆盖率报告:100% 覆盖率

% nosetests -v --with-coverage --cover-package=highlight --with-doctest\

--cover-erase --exe

Doctest: highlight.HighlightDocumentOperations._custom_highlight_tag ... ok

test_functional.test_snippit_algorithm ... ok

test_custom_highlight_tag (test_highlight.TestHighlight) ... ok

Consumes the generator, and then verifies the result[0]
... ok

Verifies highlighted text is what we expect ... ok

test_multi_string_replace (test_highlight.TestHighlight) ... ok

Verifies the yielded results are what is expected ... ok

Name Stmts Exec Cover Missing

-----------------------------------------

highlight 71 71 100%

----------------------------------------------------------------------

Ran 7 tests in 4.223s

OK

  如上所示,带几个选项运行了 nosetests 命令,highlight spy 脚本的测试覆盖率为 100%。惟一需要注意的是 --cover-package=highlight,它让 nose 只显示指定的模块的覆盖率报告。这可以非常有效地把覆盖率报告的输出限制为您希望观察的模块或包。可以从本文下载源代码,注释掉一些测试,从而观察覆盖率报告机制的实际工作情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: