coverage.py:HTML报告中预期执行行未标绿的原因排查
示例代码
#!/usr/bin/env python import os import sys from coverage import Coverage class Cover_Diy(object): def cover_diy(self, cmd): if cmd == "hostname": os.system(cmd) elif cmd == "uptime": os.system(cmd) else: os.system(cmd) def main(args): covd = Cover_Diy() covd.cover_diy(args[1]) if __name__ == "__main__": cov = Coverage() print dir(cov) cov.start() args = sys.argv try: sys.exit(main(args)) except Exception as ex: print ex cov.stop() cov.html_report(directory="/home/username/scripts/html")
执行命令
python sample.py hostname
问题
执行上述命令后,覆盖率报告中第3、4、5、7、9、10、11、18行被标记为未执行(缺失),请问原因是什么?
原因拆解
咱们一行一行理清楚这些未被标记为执行的代码:
第3、4、5行(import语句及空行):
这些代码在脚本启动后立刻执行,但你的覆盖率追踪是从cov.start()(代码第22行)才开始的。Coverage工具只会统计start()调用之后的代码执行情况,所以这些提前执行的import语句自然不会被记录,被标记为未执行。第7行(
def cover_diy(self, cmd):):
函数定义语句同样是在cov.start()之前执行的,属于追踪启动前的代码,所以Coverage没有统计到这行的执行,标记为未执行。第9、10、11行(elif和else分支):
你执行命令时传入的参数是hostname,代码只会进入if cmd == "hostname"的分支,elif和else分支的代码完全没有被触发执行,这些行自然覆盖率为0,被标记为未执行。第18行:
对应代码里的covd.cover_diy(args[1]),如果这行被标记未执行,大概率是行号对应误差;但更关键的是sys.exit(main(args))的问题:当main函数执行完该语句后,sys.exit()会直接终止程序,导致后续的cov.stop()和cov.html_report()根本没机会运行。不过核心逻辑还是:所有在cov.start()之前的代码都不会被统计,未触发的条件分支也不会被统计。
另外给你提个优化建议:把cov.start()移到脚本最前面(甚至import之前),就能统计到import、类和函数定义的代码执行情况了,同时把sys.exit()改成正常调用main,用finally确保cov.stop()和报告生成代码一定会执行:
if __name__ == "__main__": cov = Coverage() cov.start() # 提前启动追踪,覆盖更多代码 args = sys.argv try: main(args) except Exception as ex: print ex finally: cov.stop() cov.html_report(directory="/home/username/scripts/html")
内容的提问来源于stack exchange,提问作者ted

