博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python多进程运行测试用例的写报告为空的问题与解决
阅读量:7071 次
发布时间:2019-06-28

本文共 4640 字,大约阅读时间需要 15 分钟。

研究多线程问题也是因为当时自动发送报告邮件导致的,那会还没找到解决方案就一直想着如果启用多进程运行呢,结果就遇到了个新的问题,就是本文的来源。

先贴个书本讲解多进程运行测试用例的源代码:

1 # coding=utf-8 2 import unittest,os,time,multiprocessing 3 import commands 4 from email.mime.text import MIMEText 5 import HTMLTestRunner 6 import sys 7 sys.path.append('..\selenium_process') 8  9 10 def EEEcreatsuite1():11     casedir=[]12     listaa=os.listdir('..\\selenium_process')13     for xx in listaa:14         if 'thread' in xx:15             casedir.append(xx)16     print casedir17 18     suite=[]19     for n in casedir:20         testunit=unittest.TestSuite()21         discover=unittest.defaultTestLoader.discover(str(n),pattern='start_*.py',top_level_dir=r'..\\..\\test_unittest')22         for test_suite in discover:23             for test_case in test_suite:24                 testunit.addTest(test_case)25                 print testunit26         suite.append(testunit)27 28     return suite,casedir29 30 31 def EEEEEmutiRunCase(suite,casedir):32     now=time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time()))33     #把当前时间加到报告中34     filename="..\\report\\"+now+'result.html'35     fp=file(filename,'wb')36 37     proclist=[]38     s=039     for i in suite:40         runner=HTMLTestRunner.HTMLTestRunner(41             stream=fp,42             title=str(casedir[s])+u'测试报告',43             description=u'用例执行情况:'44             )45         proc=multiprocessing.Process(target=runner.run,args=(i,))  46         proclist.append(proc)47         s=s+148         print proclist49 50     for p in proclist: p.start()51     for p in proclist: p.join()52     fp.close()53 54 55 if __name__=='__main__':56     runtmp=EEEcreatsuite1()57     EEEEEmutiRunCase(runtmp[0],runtmp[1])

上面作者书本没有提示运行环境,由于书本例子代码基本除了特殊说明都是windows上运行的。于是我照着敲完后就运行报错,一直都是:ValueError: I/O operation on closed file。

我由于学习才入门,不明白这个报错到底为何,因为我检查代码确保没有敲错,照着作者的代码我敢肯定100%一致。

我研究了一整天就没整出个所以然来,后来百度搜索看到windows和linux多进程机制的区别,如下:

具体思路跟把文件输出集中在一起也差不多,就是把进程需要写入文件的内容作为返回值返回给惠和的回调函数,使用回调函数向文件中写入内容。这样做在windows下面还有一个好处,在windows环境下,python的多进程没有像linux环境下的多进程一样,linux环境下的multiprocessing库是基于fork函数,父进程fork了一个子进程之后会把自己的资源,比如文件句柄都传递给子进程。但是在windows环境下没有fork函数,所以如果你在父进程里打开了一个文件,在子进程中写入,会出现ValueError: I/O operation on closed file这样的错误,而且在windows环境下最好加入if __name__ == '__main__'这样的判断,以避免一些可能出现的RuntimeError或者死锁。(from 网址:http://blog.csdn.net/Q_AN1314/article/details/51923022)

我看到“但是在windows环境下没有fork函数,所以如果你在父进程里打开了一个文件,在子进程中写入,会出现ValueError: I/O operation on closed file这样的错误”这句时就突然意识到运行书本样例出现的问题应该就是这个导致的,于是我仔细分析代码发现fp代开写文件是在主进程里操作的,而Process启动的进程是不跟主进程同一个的,所以无法共享到fp的状态的。

我左思右想如何把fp的状态通过process加载启动之前传过去,甚至考虑到了用进程共享变量的形式,最后我想到既然fp=file先在主进程里就打开准备写了,我可不可以把这步直接去process创建的进程里进行?我改写代码如下:

1 # coding=utf-8 2 import unittest,os,time,multiprocessing 3 import commands 4 from email.mime.text import MIMEText 5 import HTMLTestRunner 6 import send_mail 7 import sys 8 sys.path.append('..\selenium_process') 9 10 11 def EEEcreatsuite1():12     casedir=[]13     listaa=os.listdir('..\\selenium_process')14     for xx in listaa:15         if 'thread' in xx:16             casedir.append(xx)17     print casedir18 19     suite=[]20     for n in casedir:21         testunit=unittest.TestSuite()22         discover=unittest.defaultTestLoader.discover(str(n),pattern='start_*.py',top_level_dir=r'..\\..\\test_unittest')23         for test_suite in discover:24             for test_case in test_suite:25                 testunit.addTest(test_case)26                 print testunit27         suite.append(testunit)28 29     return suite,casedir30 31 32 def htmlrun(filename,testut,casedir):33     fp=file(filename,'a+')  #改写、前模式是wb或w+结果都只是一个进程写进了报告,另外一个进程未写入,改成a+后,搞定,写入成功34     runner=HTMLTestRunner.HTMLTestRunner(35             stream=fp,36             title=str(casedir)+u'测试报告',37             description=u'用例执行情况:'38             )39     runner.run(testut)40     fp.close()41 42 def EEEEEmutiRunCase(suite,casedir):43     now=time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time()))44     #把当前时间加到报告中45     filename="..\\report\\"+now+'result.html'46     proclist=[]47     s=048     for i in suite:49         proc=multiprocessing.Process(target=htmlrun,args=(filename,i,casedir[s])) 50         proclist.append(proc)51         s=s+152         print proclist53 54     for p in proclist: p.start()55     for p in proclist: p.join()56     send_mail.sendreport()57 58 59 60 61 62 if __name__=='__main__':63     runtmp=EEEcreatsuite1()64     EEEEEmutiRunCase(runtmp[0],runtmp[1])

 

结果运行通过,报告写入成功。

中间还有句:fp=file(filename,'wb') 这是作者原来写的代码,我发现运行成功后,只有一个进程的报告写入了报告,另外一个还是没写入;于是查看file()函数帮助后+模式运行多任务读与写,改成fp=file(filename,'a+')后,运行成功,所有进程的结果都写入了报告。

转载于:https://www.cnblogs.com/mias/p/6736470.html

你可能感兴趣的文章
nginx的proxy_cache缓存配置
查看>>
论文笔记:Variational Capsules for Image Analysis and Synthesis
查看>>
爬虫 大规模数据 采集心得和示例
查看>>
CentOS中利用Docker安装RabbitMQ
查看>>
Kubernetes中StatefulSet介绍
查看>>
Jquery mobiscroll 移动设备(手机)wap日期时间选择插件以及滑动、滚动插件
查看>>
Tuxera NTFS for Mac 拼团仅需¥99!再见原价¥298!
查看>>
如何恢复u盘误删文件,看完就不会觉得自己很菜了
查看>>
WPF中ListBox滚动时的缓动效果
查看>>
javaOOM该分析dump文件而不是看异常log日志原因
查看>>
vue组件值传递之父组件向子组件传递(props)
查看>>
MySQL5.6 主从复制 ERROR 1776 (HY000): Parameters MASTER_LOG_FILE
查看>>
mysql重启,重启释放ibtmp1
查看>>
我是一个线程(修订版) 转
查看>>
numpy二分查找
查看>>
DevExpress第三方控件使用实例之ASPxPopupControl弹出子窗体
查看>>
【视频】ASP.NET Core MVC 2.* 入门
查看>>
Go基础系列:接口类型断言和type-switch
查看>>
Presentational and Container Components
查看>>
windows系统-phpstudy升级mysql8.0.12安装教程及修改密码和安装注意事项
查看>>