我们说我创建了这个简单的模块并将其命名为MyModule.py:
import threading
import multiprocessing
import time
def workerThreaded():
print 'thread working...'
time.sleep(2)
print 'thread complete'
def workerProcessed():
print 'process working...'
time.sleep(2)
print 'process complete'
def main():
workerThread = threading.Thread(target=workerThreaded)
workerThread.start()
workerProcess = multiprocessing.Process(target=workerProcessed)
workerProcess.start()
workerThread.join()
workerProcess.join()
if __name__ == '__main__':
main()
然后我把它扔到一起进行单元测试:
import unittest
import MyModule
class MyModuleTester(unittest.TestCase):
def testMyModule(self):
MyModule.main()
unittest.main()
(我知道这不是一个好的单元测试,因为它实际上没有测试它,它只是运行它,但这与我的问题无关)
如果我在PyCharm中使用代码覆盖率运行此单元测试,那么它只显示workerThreaded()
和main()
函数中的代码,尽管它明确涵盖了workerProcessed()
功能也很好。
如何让PyCharm在其代码覆盖率中包含在新流程中启动的代码?另外,我怎样才能让它包含if __name__ == '__main__':
块?
我正在运行PyCharm 2.7.3以及Python 2.7.3。
答案 0 :(得分:1)
Coverage.py可以衡量在子流程中运行的代码,详细信息位于http://nedbatchelder.com/code/coverage/subprocess.html
答案 1 :(得分:0)
我设法使其与子进程一起使用,不确定是否可以与线程或python 2一起使用。
在项目根目录中创建.covergerc文件
[run]
concurrency=multiprocessing
在项目根目录中创建sitecustomize.py文件
import atexit
from glob import glob
import os
from functools import partial
from shutil import copyfile
from tempfile import mktemp
def combine_coverage(coverage_pattern, xml_pattern, old_coverage, old_xml):
from coverage.cmdline import main
# Find newly created coverage files
coverage_files = [file for file in glob(coverage_pattern) if file not in old_coverage]
xml_files = [file for file in glob(xml_pattern) if file not in old_xml]
if not coverage_files:
raise Exception("No coverage files generated!")
if not xml_files:
raise Exception("No coverage xml file generated!")
# Combine all coverage files
main(["combine", *coverage_files])
# Convert them to xml
main(["xml"])
# Copy combined xml file over PyCharm generated one
copyfile('coverage.xml', xml_files[0])
os.remove('coverage.xml')
def enable_coverage():
import coverage
# Enable subprocess monitoring by providing rc file and enable coverage collecting
os.environ['COVERAGE_PROCESS_START'] = os.path.join(os.path.dirname(__file__), '.coveragerc')
coverage.process_startup()
# Get current coverage files so we can process only newly created ones
temp_root = os.path.dirname(mktemp())
coverage_pattern = '%s/pycharm-coverage*.coverage*' % temp_root
xml_pattern = '%s/pycharm-coverage*.xml' % temp_root
old_coverage = glob(coverage_pattern)
old_xml = glob(xml_pattern)
# Register atexit handler to collect coverage files when python is shutting down
atexit.register(partial(combine_coverage, coverage_pattern, xml_pattern, old_coverage, old_xml))
if os.getenv('PYCHARM_RUN_COVERAGE'):
enable_coverage()
这基本上可以检测代码是否在PyCharm Coverage中运行,并收集新生成的coverage文件。有多个文件,一个用于主进程,一个用于每个子进程。因此,我们需要将它们与“ coverage Combine”结合起来,然后通过“ coverage xml”将它们转换为xml,然后将结果文件复制到PyCharm生成的xml文件中。
请注意,如果您在测试coverage中杀死了子进程,py将不会写入数据文件。
不需要任何其他操作,只需点击PyCharm中的“使用Coverage运行单元测试”按钮即可。
就是这样。