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

用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  - -- 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 只显示指定的模块的覆盖率报告。这可以非常有效地把覆盖率报告的输出限制为您希望观察的模块或包。可以从本文下载源代码,注释掉一些测试,从而观察覆盖率报告机制的实际工作情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值