Python 程式碼覆蓋率統計工具 coverage.py
coverage.py是一個用來統計python程式程式碼覆蓋率的工具。它使用起來非常簡單,並且支援最終生成介面友好的html報告。在最新版本中,還提供了分支覆蓋的功能。
官方網站:
http://nedbatchelder.com/code/coverage/
win32版本下載地址:
http://pypi.python.org/pypi/coverage
或者通過easy-install來安裝:
easy_install coverage
裝好後,在c:\Python25\Scripts\(假設裝在c盤)目錄會有一個coverage.exe。通過這個exe基本上可以完成我們所有需要的功能。執行一下,如果發現少了那個模組,請先安裝easy_install。
Coverage Command Line
命令列使用說明: 詳見:http://nedbatchelder.com/code/coverage/cmd.html
最關鍵核心的幾個引數使用如下:
1. run
執行程式碼覆蓋率統計,只需要通過coverage的run引數執行被統計程式碼即可。
$ coverage run my_program.py arg1 arg2
跑完後,會自動生成一個覆蓋率統計結果檔案(data file):.coverage。如果要修改這個預設的檔名也可以,只要設定COVERAGE_FILE環境變數。
2. report
有了覆蓋率統計結果檔案,只需要再執行report引數,就可以在命令裡看到統計的結果。
$ coverage report
Name Stmts Exec Cover
---------------------------------------------
my_program 20 16 80%
my_module 15 13 86%
my_other_module 56 50 89%
---------------------------------------------
TOTAL 91 79 87%
3. html
最帥最酷的功能了,直接生成html的測試報告。
$ coverage html -d covhtml
生成的報告非常酷,直接關聯程式碼,高亮顯示覆蓋和未覆蓋的程式碼,支援排序。可以在這個地址預覽一下:
http://nedbatchelder.com/code/coverage/sample_html/
效果如下:
4. combine
用過程式碼覆蓋率工具的都知道,多份結果的合併至關重要。combine這個引數我琢磨了很久,開始總是合併不成功。後來終於明白了。執行合併操作很簡單,只要把需要合併的覆蓋率結果資料檔案放在同一個目錄裡,然後執行:
coverage combine
即可。但是,其實對目錄裡的結果檔案是有要求的,要求就是檔名的格式,需要合併的檔案必須有同樣的字首,然後後面跟一個名稱(通常是機器名),然後再跟一個數字(通常是程序ID),比如:
.coverage.CoderZh.1234
.coverage.Cnblogs.5678
為了方便執行結果的合併,我們在前面執行統計時,在run引數後面跟一個-p引數,會自動生成符合合併條件的結果檔案。
$ coverage run -p my_program.py arg1 arg2
合併後,會再生成一個.coverage檔案,然後再執行html檢視合併後的報告吧。
其他幾個erase annotate debug 引數就不介紹了。
Coverage API
除了使用命令列,還可以在python程式碼中直接呼叫coverage模組執行程式碼覆蓋率的統計。使用方法也非常簡單:
import coverage
cov = coverage.coverage()
cov.start()
# .. run your code ..
cov.stop()
cov.save()
coverage的建構函式可以設定結果檔案的名稱等。有個函式容易弄錯,就是use_cache,如果設定的use_cache(0),表示不在硬碟上讀寫結果檔案。如果需要結果資料用來合併,一定要設定use_cache(1)。
coverage提供一些很好用的函式,如:exclude(排除統計的程式碼),html_report(生成html報告),report(控制檯輸出結果)
下篇講講如何在測試django應用時,編寫一個自己的test runner來執行程式碼覆蓋率的統計。
出處:https://www.cnblogs.com/coderzh/archive/2009/12/01/pythoncoverage.html
#!/usr/bin/env python
import os
from app import create_app,db
from app.models import User,Role,create_roles,Post
from flask_script import Manager,Shell
from flask_migrate import Migrate,MigrateCommand
app=create_app(os.getenv('FLASK_CONFIG') or'default')
manager=Manager(app)
migrate=Migrate(app,db)
def make_shell_context():
return dict(app=app,db=db,User=User,Role=Role,Post=Post,create_roles=create_roles)
manager.add_command("shell",Shell(make_context=make_shell_context))
manager.add_command('db',MigrateCommand)
COV=None
if os.environ.get('COVERAGE'):
import coverage
COV=coverage.coverage(branch=True,include='app/*')
COV.start()
@manager.command
def test(coverage=False):
"""Run the unit tests"""
if coverage and not os.environ.get('COVERAGE'):
import sys
os.environ['COVERAGE']='1'
os.execvp(sys.executable,[sys.executable]+sys.argv)
import unittest
tests=unittest.TestLoader().discover('tests')
unittest.TextTestRunner(verbosity=2).run(tests)
if COV:
COV.stop()
COV.save()
print('Coverage:')
COV.report()
COV.erase()
@manager.command
def myprint():
print 'hello world'
if __name__=='__main__':
manager.run()