﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-qileilove-随笔分类-ruby languages  </title><link>http://www.blogjava.net/qileilove/category/51347.html</link><description>不想做屌丝的码农，不是好项目经理！屌丝生涯从此开始！</description><language>zh-cn</language><lastBuildDate>Fri, 28 Feb 2014 06:53:18 GMT</lastBuildDate><pubDate>Fri, 28 Feb 2014 06:53:18 GMT</pubDate><ttl>60</ttl><item><title>Python解决插入数据库乱码问题</title><link>http://www.blogjava.net/qileilove/archive/2014/02/28/410441.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Fri, 28 Feb 2014 02:59:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2014/02/28/410441.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/410441.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2014/02/28/410441.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/410441.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/410441.html</trackback:ping><description><![CDATA[<div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">从网站上获取的信息要保存在本地<a target="_self" style="word-break: break-all; color: #202859; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">数据库</strong></u></a>中，但是保存的过程中数据库的信息都变成了乱码，怎么解决呢？客官听我娓娓道来。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　首先，保证以下四项的编码都是utf-8：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　1. 代码</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　2. 数据库连接</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　3. 表的字符集格式</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　4. 插入的数据格式</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　每步的操作如下：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　1. 保证代码的格式是utf-8，在代码最前面加上这句话</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　# -*- coding:utf8 -*-</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　#首先用于确定编码，加上这句</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　2. 保证数据库连接格式是utf-8，这么写</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　conn=MySQLdb.connect(host='localhost',user='root',passwd='****',db='kfxx',port=3306,charset='utf8')</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　cur=conn.cursor()</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　3. 保证表的字符集格式是utf-8，在建表的时候就能设置</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><a href="http://www.51testing.com/batch.download.php?aid=44655" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/02/14982672_201402240959131qwe3.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;"  alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　4. 保证插入的数据格式是utf-8，分为保证读取的页面格式是utf-8和字符串格式也是utf-8</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　#解决乱码问题</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><table align="center" style="word-break: break-all; border-style: solid; border-color: #999999; width: 612.7272338867188px; background-color: #dddddd; font-size: 12px;"><tbody style="word-break: break-all;"><tr style="word-break: break-all;"><td style="word-break: break-all;"><div style="word-break: break-all; margin: 10px 0px;">html_1 = urllib2.urlopen(cityURL,timeout=120).read()</div><div style="word-break: break-all; margin: 10px 0px;">mychar = chardet.detect(html_1)</div><div style="word-break: break-all; margin: 10px 0px;">bianma = mychar['encoding']</div><div style="word-break: break-all; margin: 10px 0px;">if bianma == 'utf-8' or bianma == 'UTF-8':</div><div style="word-break: break-all; margin: 10px 0px;">html = html_1</div><div style="word-break: break-all; margin: 10px 0px;">else :</div><div style="word-break: break-all; margin: 10px 0px;">html = html_1.decode('gb2312','ignore').encode('utf-8')</div></td></tr></tbody></table></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><table align="center" style="word-break: break-all; border-style: solid; border-color: #999999; width: 612.7272338867188px; background-color: #dddddd; font-size: 12px;"><tbody style="word-break: break-all;"><tr style="word-break: break-all;"><td style="word-break: break-all;"><div style="word-break: break-all; margin: 10px 0px;">chapter_soup = BeautifulSoup(html)</div><div style="word-break: break-all; margin: 10px 0px;">city = chapter_soup.find('div',class_ = 'row-fluid').find('h1').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">province = chapter_soup.find('a',class_ = 'province').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">pmNum = chapter_soup.find('div',class_ = 'row-fluid').find('span').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">suggest = chapter_soup.find('div',class_ = 'row-fluid').find('h2').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">rand = chapter_soup.find('div',class_ = 'row-fluid').find('h2').find_next_sibling('h2').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">face = chapter_soup.find('div',class_ = 'span4 pmemoji').find('h1').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">conclusion = chapter_soup.find('h1',class_ = 'review').get_text()</div><div style="word-break: break-all; margin: 10px 0px;">print city.encode('utf-8')</div><div style="word-break: break-all; margin: 10px 0px;">cur.execute('insert into t_pm values(\''+city.encode('utf-8')</div><div style="word-break: break-all; margin: 10px 0px;">+'\',\''+province.encode('utf-8')</div><div style="word-break: break-all; margin: 10px 0px;">+'\',\''+pmNum.encode('utf-8')</div><div style="word-break: break-all; margin: 10px 0px;">+'\',\''+suggest.encode('utf-8')</div><div style="word-break: break-all; margin: 10px 0px;">+'\',\''+rand.encode('utf-8')</div><div style="word-break: break-all; margin: 10px 0px;">+'\',\''+conclusion.encode('utf-8')+'\')')</div></td></tr></tbody></table></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">　　完成，插入的数据都是中文了，看效果图：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><a href="http://www.51testing.com/batch.download.php?aid=44656" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/02/14982672_201402240959132cH8h.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;"  alt="" /></a></div><img src ="http://www.blogjava.net/qileilove/aggbug/410441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2014-02-28 10:59 <a href="http://www.blogjava.net/qileilove/archive/2014/02/28/410441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用ruby 1.9新特性进行自动化脚本的编写</title><link>http://www.blogjava.net/qileilove/archive/2013/09/18/404210.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Wed, 18 Sep 2013 03:23:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2013/09/18/404210.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/404210.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2013/09/18/404210.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/404210.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/404210.html</trackback:ping><description><![CDATA[<p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">昨天因为要装watir-webdriver的原因将用了快一年的ruby1.8.6升级到了1.9。由于1.9是原生支持unicode编码，所以我们可以使用中文进行自动化脚本的编写<a href="" target="_self" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">工作</strong></u></a>。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　做了简单的封装后，我们可以实现如下的<a href="" target="_self" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">自动化测试</strong></u></a>代码。请注意，这些代码是可以正确运行并作为正式的自动化<a href="" target="_self" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">测试用例</strong></u></a>的。这样一来，自动化测试脚本跟手工测试用例就非常相似了，大言不惭的说相似程度可以达到60%。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;"><strong style="word-break: break-all; line-height: normal !important;">　　这样做有什么好处呢？</strong></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　&#9632; 手工测试用例更加容易&#8220;翻译&#8221;正自动化测试用例:</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;"></p><table align="center" style="word-break: break-all; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; border-style: solid; border-color: #999999; background-color: #dddddd; width: 612.2222290039063px;"><tbody style="word-break: break-all;"><tr style="word-break: break-all;"><td style="word-break: break-all;">测试浏览器 = Watir::Browser.new :firefox<br style="word-break: break-all;" />测试浏览器.转到 'www.google.com'<br style="word-break: break-all;" />在(测试浏览器.的.text_field(:name, "q")).中.输入 "qq"<br style="word-break: break-all;" />点击 测试浏览器.的.button(:name, "btnG")<br style="word-break: break-all;" />等待(测试浏览器.的.div(:id, "resultStats"))<br style="word-break: break-all;" />断言 '测试通过' if 测试浏览器.的.text.包含('腾讯QQ')<br style="word-break: break-all;" />关闭 测试浏览器</td></tr></tbody></table><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;"></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　由于加入了符合自然语义的&#8221;的&#8221;及&#8220;在&#8221;函数，整个测试用例的自然度得到大大提升，基本可以做到不熟悉自动化代码的人员可以大致猜测到用例的真实用例。让用例自己说话，这比反复释疑和解惑要好上一些；</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　&#9632; 手工测试人员编写用例的门槛相对降低:</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　由于代码的灵活度及兼容性相对较大（ruby语言的特性）及测试api相对简单(watir的特性），手工测试人员应该可以更加方便的理解和编写代码，这样用例编写的门槛降低；</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　&#9632; 用例维护成本降低:</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　中文化的用例代码可以很容易的进行review。大家应该有这样的经验，在有些代码中会出现一些随意的ab, zb之类难以理解的变量或方法名。纠其原因无非是不好的编程习惯或词穷的英文积淀。用上中文之后这些情况会有很大好转。代码本地化这项工作日本这些年一直在做，而且成果丰硕。我们完全可以通过ruby借鉴这一点；</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　&#9632; webdriver的强大特性</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　上面的测试代码是基于watir-webdriver编写的。由于webdriver支持多种浏览器，如ff，chrome，safiri，ie等，代码的扩展性非常强。在配置合理及框架支撑的前提下，基本可以做到一套脚本多浏览器运行，这对回归测试来说应该是一个利好消息；</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　当然，测试脚本中文化，自然化口语化也会带来一些列的问题，这点我们也必须清楚认识到。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　1.用例编写会相对费时一些；中英文结合编码在输入速度上确实不如纯英文；</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　2.对程序员来说上面的代码会有些怪异或者是令人难以忍受的；对于完美主义者来说，上面的代码是&#8220;不纯粹&#8221;且有些难看的；</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　<strong style="word-break: break-all; line-height: normal !important;">总结一下，个人的观点如下：</strong></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　对于产品代码来说，中英文混编的风格目前来说应该是不合时宜的。但对于测试脚本来说，中文越多，用例可读性越高，自动化测试代码越接近手动用例，这反而应该是一件不错的事情。这在里先抛砖引玉，希望有志同道合者可以一起研究，让自动化脚本更加的人性、自然、可读、可维护。也许在不远的将来，手动用例可以直接拿来当自动化用例执行也未尝不可能。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 23.99305534362793px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13.333333969116211px; background-color: #ffffff;">　　下面是用例的完整代码，由于只是演示兴致，因此只是随意在Module层进行了简单的可视化封装，过于简陋和demo，还望砖家手下留情。<br /><br /><table align="center" style="word-break: break-all; color: #333333; font-size: 12px; border-style: solid; border-color: #999999; background-color: #dddddd; width: 612.2222290039063px;"><tbody style="word-break: break-all;"><tr style="word-break: break-all;"><td style="word-break: break-all;"><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 1.8em !important;"># encoding: utf-8<br style="word-break: break-all; line-height: normal !important;" />require 'rubygems'<br style="word-break: break-all; line-height: normal !important;" />require 'watir-webdriver'<br style="word-break: break-all; line-height: normal !important;" />module CWrap<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 点击(obj)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.click rescue obj.class.to_s + '对象无法进行点击'<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 加载完毕()<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; alias :中 :加载完毕<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; alias :的 :中<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; alias :应该 :的<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 在(obj)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 等待(obj)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.wait_until_present rescue puts('该' + obj.class.to_s + '对象无法进行等待操作')<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 关闭(obj)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.close rescue puts('无法关闭这个' + obj.class.to_s + '对象')<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 输入(text)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.set text rescue puts('这个' + self.class.to_s + '对象无法进行输入')<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 转到(url)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.goto url rescue puts(self.class.to_s + '对象不是一个浏览器对象')<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 包含(text)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.include? text rescue puts self.class.to_s + '对象无法进行包含操作'<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; def 断言(text)<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; puts text<br style="word-break: break-all; line-height: normal !important;" />&nbsp;&nbsp;&nbsp; end<br style="word-break: break-all; line-height: normal !important;" />end<br style="word-break: break-all; line-height: normal !important;" />include CWrap</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 1.8em !important;">测试浏览器 = Watir::Browser.new :firefox<br style="word-break: break-all; line-height: normal !important;" />测试浏览器.转到 'www.google.com'<br style="word-break: break-all; line-height: normal !important;" />在(测试浏览器.的.text_field(:name, "q")).中.输入 "qq"<br style="word-break: break-all; line-height: normal !important;" />点击 测试浏览器.的.button(:name, "btnG")<br style="word-break: break-all; line-height: normal !important;" />等待(测试浏览器.的.div(:id, "resultStats"))<br style="word-break: break-all; line-height: normal !important;" />断言 '测试通过' if 测试浏览器.的.text.包含('腾讯QQ')<br style="word-break: break-all; line-height: normal !important;" />关闭 测试浏览器</p></td></tr></tbody></table></p><img src ="http://www.blogjava.net/qileilove/aggbug/404210.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2013-09-18 11:23 <a href="http://www.blogjava.net/qileilove/archive/2013/09/18/404210.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单的性能自动化测试架构设计和实现（pylot）-python</title><link>http://www.blogjava.net/qileilove/archive/2013/05/20/399491.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Mon, 20 May 2013 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2013/05/20/399491.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/399491.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2013/05/20/399491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/399491.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/399491.html</trackback:ping><description><![CDATA[<div><p align="center"><strong><a href="http://www.51testing.com/batch.download.php?aid=39865" target="_blank"><img style="width: 618px; height: 327px" src="http://www.51testing.com/attachments/2013/05/346836_201305101002491QXLk.jpg" border="0" height="347" width="718"  alt="" /></a></strong></p><p><strong>　　目的：</strong></p><p>　　和普通性能<a target="_self"><u><strong>自动化测试</strong></u></a>工具相似，创建给定数量的请求代理，对链接列表中的链接不断发送请求，并收集请求时间和其他响应信息，最终返回结果数据。</p><p>　　事实上，由于开源测试项目pylot的思路和这个项目有些相似，大部分示例代码使用pylot源码，一些会有稍微改动。</p><p><strong>　　设计思路：</strong></p><p>　　如设计图所示，总体上分为5个主要部分：</p><p>　　1、<a target="_self"><u><strong>Test</strong></u></a>.xml处理部分：</p><p>　 　通过用户的制作的testcase.xml文件，获取总体的属性值作为参数，并读取所有test  case所包含的信息，获取所有测试连接列表和其他配置数据，testcase.xml的格式如下，这个testcase.xml可以专门写一个xml写 作的工具，供QA人员以界面方式进行编写，提高效率并减小错误率：</p>&nbsp;&lt;testcases&gt;<br />&nbsp;<br />&nbsp;&lt;project&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;Test&lt;/name&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;Only Test&lt;/description&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;executor&gt;zhangyi&lt;/executor&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- 如果需要结果进入<a target="_self"><u><strong>数据库</strong></u></a>，配置下面数据库链接参数 -&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;DB<br />&nbsp;&lt;host&gt;&lt;/host&gt;<br />&nbsp;&lt;port&gt;&lt;/port&gt;<br />&nbsp;&lt;user&gt;&lt;/user&gt;<br />&nbsp;&lt;pwd&gt;&lt;/pwd&gt;<br />&nbsp;&lt;db&gt;&lt;/db&gt;<br />&nbsp;&lt;debug&gt;true&lt;/debug&gt;<br />&nbsp;&lt;/DB&gt;<br />&nbsp;&lt;type&gt;Example&lt;/type&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/project&gt;<br />&nbsp;&lt;property&gt;<br />&nbsp;&lt;old_version&gt;&lt;/old_verstion&gt;<br />&nbsp;&lt;old_version&gt;&lt;/old_verstion&gt;<br />&nbsp;&lt;wel_url&gt;r'http://www.baidu.cn/'&lt;/wel_url&gt;<br />&nbsp;&lt;/property&gt;<br />&nbsp;&lt;!-- run before all testcase --&gt;<br />&nbsp;&lt;beforesetup&gt;<br />&nbsp;&lt;/beforesetup&gt;<br />&nbsp;&lt;!-- run after all testcase --&gt;<br />&nbsp;&lt;afterteardown&gt;<br />&nbsp;&lt;/afterteardown&gt;&nbsp;&nbsp;<br />&nbsp;&lt;!-- run before each testcase. if fail, not continue run testcase--&gt;<br />&nbsp;&lt;setup&gt;<br />&nbsp;&lt;/setup&gt;<br />&nbsp;&lt;!-- run after each testcase. ignore testcase fail.&nbsp; --&gt;<br />&nbsp;&lt;teardown&gt;<br />&nbsp;&lt;/teardown&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- SAMPLE TEST CASE --&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case repeat=3&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://www.example.com&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case repeat=3&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://search.yahooapis.com/WebSearchService/V1/webSearch&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;POST&lt;/method&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;body&gt;&lt;![CDATA[appid=YahooDemo&amp;query=pylot]]&gt;&lt;/body&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add_header&gt;Content-type: application/x-www-form-urlencoded&lt;/add_header&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case repeat=2&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://search.yahooapis.com/WebSearchService/V1/webSearch&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;POST&lt;/method&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;body&gt;&lt;![CDATA[appid=YahooDemo&amp;query=pylot]]&gt;&lt;/body&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add_header&gt;Content-type: application/x-www-form-urlencoded&lt;/add_header&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case repeat=3&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://search.yahooapis.com/WebSearchService/V1/webSearch&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;POST&lt;/method&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;body&gt;&lt;![CDATA[appid=YahooDemo&amp;query=pylot]]&gt;&lt;/body&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add_header&gt;Content-type: application/x-www-form-urlencoded&lt;/add_header&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://www.example.com&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case repeat=10&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://www.example.com&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- SAMPLE TEST CASE --&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;!--<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url&gt;http://search.yahooapis.com/WebSearchService/V1/webSearch&lt;/url&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;POST&lt;/method&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;body&gt;&lt;![CDATA[appid=YahooDemo&amp;query=pylot]]&gt;&lt;/body&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add_header&gt;Content-type: application/x-www-form-urlencoded&lt;/add_header&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;/case&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />&nbsp;&lt;/testcases&gt;</div><div>　根据用户的策略，会对testcase.xml中的case项进行分割和组合，最终得到每个agent对应的 testcase.xml，agent会按照这个testcase.xml进行测试，通常来说，策略包含以下两种：a.  每个agent执行所有case；b. 将所有case平均分给agent执行。 <p>　　重要代码：</p> <p> </p><table style="border-bottom: #999 1px solid; border-left: #999 1px solid; background-color: #dddddd; width: 98%; font-size: 12px; border-top: #999 1px solid; border-right: #999 1px solid" align="center"> <tbody> <tr> <td>def load_xml_cases_dom(dom): <br />&nbsp;&nbsp;&nbsp;&nbsp; cases = [] <br />&nbsp;&nbsp;&nbsp;&nbsp; param_map = {} <br />&nbsp;&nbsp;&nbsp;&nbsp; for child in dom.getiterator():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if child.tag != dom.getroot().tag and child.tag == 'param': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name = child.attrib.get('name') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = child.attrib.get('value') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; param_map[name] = value <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if child.tag != dom.getroot().tag and child.tag == 'case': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req = Request() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; repeat = child.attrib.get('repeat') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if repeat: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.repeat = int(repeat) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.repeat = 1 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for element in child: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'url': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.url = element.text <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'method': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.method = element.text <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'body': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file_payload = element.attrib.get('file') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if file_payload: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.body = open(file_payload, 'rb').read() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.body = element.text <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'verify': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.verify = element.text <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'verify_negative': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.verify_negative = element.text <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'timer_group':<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.timer_group = element.text <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if element.tag.lower() == 'add_header': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; splat = element.text.split(':') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = splat[0].strip() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; del splat[0] <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req.add_header(x, ''.join(splat).strip()) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req = resolve_parameters(req, param_map)&nbsp; # substitute vars <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cases.append(req) <br />&nbsp;&nbsp;&nbsp;&nbsp; return case</td></tr></tbody></table> <p>　　2、Request请求代理部分：</p> <p>　　请求代理会根据分配给自己的testcase.xml进行初始化，获取所有配置参数和case列表，当接收到agent  manager发给的执行消息后，会开启一个线程对case列表中的每一个case进行处理；初始化agent时，agent  manager会传进来全局的几个队列，包括result queue，msg queue，error  queue；这些queue中的信息最终会由agent manager统一处理；</p> <p>　　重要代码：</p> <p> </p>    <p>&nbsp;&nbsp;&nbsp; def run(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agent_start_time = time.strftime('%H:%M:%S', time.localtime())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_latency = 0 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_connect_latency = 0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_bytes = 0<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while self.running: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.cookie_jar = cookielib.CookieJar() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for req in self.msg_queue: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for repeat in range(req.repeat): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.running: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request=Request(req) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # send the request message <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp, content, req_start_time, req_end_time, connect_end_time = request.send(req)</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # get times for logging and error display <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_time = time.localtime() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cur_date = time.strftime('%d %b %Y', tmp_time) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cur_time = time.strftime('%H:%M:%S', tmp_time)</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # check verifications and status code for errors <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_error = False <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if resp.code &gt;= 400 or resp.code == 0: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_error = True <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not req.verify == '': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not re.search(req.verify, content, re.DOTALL):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_error = True <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not req.verify_negative == '': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if re.search(req.verify_negative, content, re.DOTALL): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_error = True<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if is_error:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.error_count += 1 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  error_string = 'Agent %s:&nbsp; %s - %d %s,&nbsp; url: %s' % (self.id + 1,  cur_time, resp.code, resp.msg, req.url) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.error_queue.append(error_string) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  log_tuple = (self.id + 1, cur_date, cur_time, req_end_time,  req.url.replace(',', ''), resp.code, resp.msg.replace(',', '')) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.log_error('%s,%s,%s,%s,%s,%s,%s' % log_tuple)&nbsp; # write as csv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp_bytes = len(content) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; latency = (req_end_time - req_start_time) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connect_latency = (connect_end_time - req_start_time)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.count += 1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_bytes += resp_bytes <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_latency += latency <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_connect_latency += connect_latency&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # update shared stats dictionary <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  self.runtime_stats[self.id] = StatCollection(resp.code, resp.msg,  latency, self.count, self.error_count, total_latency,  total_connect_latency, total_bytes) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.runtime_stats[self.id].agent_start_time = agent_start_time<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # put response stats/info on queue for reading by the consumer (ResultWriter) thread <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  q_tuple = (self.id + 1, cur_date, cur_time, req_end_time,  req.url.replace(',', ''), resp.code, resp.msg.replace(',', ''),  resp_bytes, latency, connect_latency, req.timer_group) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.results_queue.put(q_tuple)<br />&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; expire_time = (self.interval - latency) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if expire_time &gt; 0: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(expire_time)&nbsp; # sleep remainder of interval so we keep even pacing&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:&nbsp; # don't go through entire range if stop has been called<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break</p></div><div>　3、Request请求部分： <p>　　对每一个case初始化为一个request类实例，包含这case的测试数据，测试方法和测试结果，agent会实例化对立中的每个case，并在主线程中执行测试方法，获取相应的测试数据；</p> <p>　　重要代码，这部分代码本来是pylot中的源码，个人更倾向于将它放在request中，需要少许更改：</p> <p> </p>    <p>&nbsp;&nbsp;&nbsp; def send(self, req):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # req is our own Request object <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if HTTP_DEBUG: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie_jar), urllib2.HTTPHandler(debuglevel=1)) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif COOKIES_ENABLED: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie_jar)) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; opener = urllib2.build_opener() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if req.method.upper() == 'POST': <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request = urllib2.Request(req.url, req.body, req.headers) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  request = urllib2.Request(req.url, None, req.headers)&nbsp; # urllib2  assumes a GET if no data is supplied.&nbsp; PUT and DELETE are not  supported&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # timed message send+receive (TTLB) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req_start_time = self.default_timer() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  resp = opener.open(request)&nbsp; # this sends the HTTP request and returns  as soon as it is done connecting and sending <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connect_end_time = self.default_timer() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; content = resp.read() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req_end_time = self.default_timer() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except httplib.HTTPException, e:&nbsp; # this can happen on an incomplete read, just catch all HTTPException <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connect_end_time = self.default_timer() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp = ErrorResponse() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.code = 0 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.msg = str(e) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.headers = {} <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; content = '' <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except urllib2.HTTPError, e:&nbsp; # http responses with status &gt;= 400 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connect_end_time = self.default_timer() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp = ErrorResponse() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.code = e.code <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.msg = httplib.responses[e.code]&nbsp; # constant dict of http error codes/reasons <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.headers = dict(e.info()) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; content = '' <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except urllib2.URLError, e:&nbsp; # this also catches socket errors <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connect_end_time = self.default_timer() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp = ErrorResponse() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.code = 0 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.msg = str(e.reason) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resp.headers = {}&nbsp; # headers are not available in the exception <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; content = '' <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req_end_time = self.default_timer() <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.trace_logging: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # log request/response messages <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.log_http_msgs(req, request, resp, content)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (resp, content, req_start_time, req_end_time, connect_end_time)</p></div><div>　4、代理管理部分： <p>　　代理管理的主要任务是创建几个重要数据的队列，实例化每个agent并为其创建新的线程。代理管理会管理这个线程池，并在这些中重要的队列中获取到测试的结果；</p> <p>　　重要代码：</p> <p> </p>    <p>&nbsp;&nbsp;&nbsp;&nbsp; def run(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.running = True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.agents_started = False <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.makedirs(self.output_dir, 0755) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except OSError: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.output_dir = self.output_dir + time.strftime('/results_%Y.%m.%d_%H.%M.%S', time.localtime()) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.makedirs(self.output_dir, 0755) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except OSError: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stderr.write('ERROR: Can not create output directory\n') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.exit(1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # start thread for reading and writing queued results <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.results_writer = ResultWriter(self.results_queue, self.output_dir) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.results_writer.setDaemon(True) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.results_writer.start()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(self.num_agents): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spacing = float(self.rampup) / float(self.num_agents) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i &gt; 0:&nbsp; # first agent starts right away <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(spacing) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.running:&nbsp; # in case stop() was called before all agents are started <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  agent = LoadAgent(i, self.interval, self.log_msgs, self.output_dir,  self.runtime_stats, self.error_queue, self.msg_queue,  self.results_queue) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agent.start() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.agent_refs.append(agent) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agent_started_line = 'Started agent ' + str(i + 1) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if sys.platform.startswith('win'): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write(chr(0x08) * len(agent_started_line))&nbsp; # move cursor back so we update the same line again <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write(agent_started_line) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esc = chr(27) # escape key <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write(esc + '[G' ) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write(esc + '[A' ) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write(agent_started_line + '\n') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if sys.platform.startswith('win'): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write('\n') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print '\nAll agents running...\n\n' <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.agents_started = True&nbsp; </p> <p>&nbsp;&nbsp;&nbsp;&nbsp; def stop(self): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.running = False <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for agent in self.agent_refs: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agent.stop()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if WAITFOR_AGENT_FINISH: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keep_running = True <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while keep_running: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keep_running = False <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for agent in self.agent_refs: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if agent.isAlive(): <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keep_running = True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(0.1)<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.results_writer.stop()</p></div><div>5、结果生成部分： <p>　　代理中获取的数据最终写到一个csv文件中，在代理部分的执行函数完成后，读取这个文件的内容，生成相关的结果数据和图片（图片在python中倾向于使用matlibplot包）。最终将其写成html的结果报告形式：</p> <p>　　重要代码：</p> <p> </p><table style="border-bottom: #999 1px solid; border-left: #999 1px solid; background-color: #dddddd; width: 98%; font-size: 12px; border-top: #999 1px solid; border-right: #999 1px solid" align="center"> <tbody> <tr> <td>&nbsp;def generate_results(dir, test_name): <br />&nbsp;&nbsp;&nbsp;&nbsp; print '\nGenerating Results...' <br />&nbsp;&nbsp;&nbsp;&nbsp; try: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; merged_log = open(dir + '/agent_stats.csv', 'rb').readlines()&nbsp; # this log contains commingled results from all agents <br />&nbsp;&nbsp;&nbsp;&nbsp; except IOError: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stderr.write('ERROR: Can not find your results log file\n') <br />&nbsp;&nbsp;&nbsp;&nbsp; merged_error_log = merge_error_files(dir)&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; if len(merged_log) == 0: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fh = open(dir + '/results.html', 'w') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  fh.write(r'&lt;html&gt;&lt;body&gt;&lt;p&gt;None of the agents finished  successfully.&nbsp; There is no data to  report.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;\n') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fh.close() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stdout.write('ERROR: None of the agents finished successfully.&nbsp; There is no data to report.\n') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; timings = list_timings(merged_log) <br />&nbsp;&nbsp;&nbsp;&nbsp; best_times, worst_times = best_and_worst_requests(merged_log) <br />&nbsp;&nbsp;&nbsp;&nbsp; timer_group_stats = get_timer_groups(merged_log) <br />&nbsp;&nbsp;&nbsp;&nbsp; timing_secs = [int(x[0]) for x in timings]&nbsp; # grab just the secs (rounded-down) <br />&nbsp;&nbsp;&nbsp;&nbsp; throughputs = calc_throughputs(timing_secs)&nbsp; # dict of secs and throughputs <br />&nbsp;&nbsp;&nbsp;&nbsp; throughput_stats = corestats.Stats(throughputs.values()) <br />&nbsp;&nbsp;&nbsp;&nbsp; resp_data_set = [x[1] for x in timings] # grab just the timings <br />&nbsp;&nbsp;&nbsp;&nbsp; response_stats = corestats.Stats(resp_data_set)&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; # calc the stats and load up a dictionary with the results <br />&nbsp;&nbsp;&nbsp;&nbsp; stats_dict = get_stats(response_stats, throughput_stats)&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; # get the pickled stats dictionaries we saved<br />&nbsp;&nbsp;&nbsp;&nbsp; runtime_stats_dict, workload_dict = load_dat_detail(dir)<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; # get the summary stats and load up a dictionary with the results&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict = {} <br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict['cur_time'] = time.strftime('%m/%d/%Y %H:%M:%S', time.localtime()) <br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict['duration'] = int(timings[-1][0] - timings[0][0]) + 1&nbsp; # add 1 to round up <br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict['num_agents'] = workload_dict['num_agents']<br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict['req_count'] = len(timing_secs) <br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict['err_count'] = len(merged_error_log) <br />&nbsp;&nbsp;&nbsp;&nbsp; summary_dict['bytes_received'] = calc_bytes(merged_log) <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; # write html report <br />&nbsp;&nbsp;&nbsp;&nbsp; fh = open(dir + '/results.html', 'w') <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_head_html(fh) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_starting_content(fh, test_name) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_summary_results(fh, summary_dict, workload_dict)<br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_stats_tables(fh, stats_dict) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_images(fh) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_timer_group_stats(fh, timer_group_stats) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_agent_detail_table(fh, runtime_stats_dict) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_best_worst_requests(fh, best_times, worst_times) <br />&nbsp;&nbsp;&nbsp;&nbsp; reportwriter.write_closing_html(fh) <br />&nbsp;&nbsp;&nbsp;&nbsp; fh.close() <br />&nbsp;&nbsp;&nbsp;&nbsp; # response time graph <br />&nbsp;def resp_graph(nested_resp_list, dir='./'): <br />&nbsp;&nbsp;&nbsp;&nbsp; fig = figure(figsize=(8, 3))&nbsp; # image dimensions&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; ax = fig.add_subplot(111) <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.set_xlabel('Elapsed Time In Test (secs)', size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.set_ylabel('Response Time (secs)' , size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.grid(True, color='#666666') <br />&nbsp;&nbsp;&nbsp;&nbsp; xticks(size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; yticks(size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; axis(xmin=0)<br />&nbsp;&nbsp;&nbsp;&nbsp; x_seq = [item[0] for item in nested_resp_list]<br />&nbsp;&nbsp;&nbsp;&nbsp; y_seq = [item[1] for item in nested_resp_list] <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.plot(x_seq, y_seq, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; color='blue', linestyle='-', linewidth=1.0, marker='o',<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; markeredgecolor='blue', markerfacecolor='yellow', markersize=2.0)<br />&nbsp;&nbsp;&nbsp;&nbsp; savefig(dir + 'response_time_graph.png')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />&nbsp;# throughput graph <br />&nbsp;def tp_graph(throughputs_dict, dir='./'): <br />&nbsp;&nbsp;&nbsp;&nbsp; fig = figure(figsize=(8, 3))&nbsp; # image dimensions <br />&nbsp;&nbsp;&nbsp;&nbsp; ax = fig.add_subplot(111) <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.set_xlabel('Elapsed Time In Test (secs)', size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.set_ylabel('Requests Per Second (count)' , size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.grid(True, color='#666666') <br />&nbsp;&nbsp;&nbsp;&nbsp; xticks(size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; yticks(size='x-small') <br />&nbsp;&nbsp;&nbsp;&nbsp; axis(xmin=0) <br />&nbsp;&nbsp;&nbsp;&nbsp; keys = throughputs_dict.keys() <br />&nbsp;&nbsp;&nbsp;&nbsp; keys.sort() <br />&nbsp;&nbsp;&nbsp;&nbsp; values = [] <br />&nbsp;&nbsp;&nbsp;&nbsp; for key in keys: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; values.append(throughputs_dict[key]) <br />&nbsp;&nbsp;&nbsp;&nbsp; x_seq = keys <br />&nbsp;&nbsp;&nbsp;&nbsp; y_seq = values <br />&nbsp;&nbsp;&nbsp;&nbsp; ax.plot(x_seq, y_seq,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; color='red', linestyle='-', linewidth=1.0, marker='o', <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; markeredgecolor='red', markerfacecolor='yellow', markersize=2.0)<br />&nbsp;&nbsp;&nbsp;&nbsp; savefig(dir + 'throughput_graph.png')&nbsp;&nbsp;&nbsp;&nbsp; try:&nbsp; # graphing only works on systems with Matplotlib installed <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print 'Generating Graphs...' <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; import graph <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; graph.resp_graph(timings, dir=dir+'/') <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; graph.tp_graph(throughputs, dir=dir+'/') <br />&nbsp;&nbsp;&nbsp;&nbsp; except: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stderr.write('ERROR: Unable to generate graphs with Matplotlib\n') <br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; print '\nDone generating results. You can view your test at:' <br />&nbsp;print '%s/results.html\n' % dir</td></tr></tbody></table> <p>　　对于项目的运行，既可以采取控制台方式，也可以提供给QA人员GUI的方式。Pylot中提供了很好的GUI支持，可以作为示例使用。实际上不 建议使用GUI的方式，另外pylot中没有用户指定策略的支持，这个需要自己专门进行开发；另外就是pylot中的类封装结构还不是很好，对以后的扩展 来说还需要一定的更改。但是作为一般使用已经足够了，下面是pylot的最终报告结果（只做实例使用）。</p> <p align="center"><a href="http://www.51testing.com/batch.download.php?aid=39866" target="_blank"><img style="width: 352px; height: 439px" src="http://www.51testing.com/attachments/2013/05/346836_201305101002551ITbV.jpg" border="0" height="1553" width="877"  alt="" /></a></p></div><img src ="http://www.blogjava.net/qileilove/aggbug/399491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2013-05-20 10:35 <a href="http://www.blogjava.net/qileilove/archive/2013/05/20/399491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>