做GUI自动化测试失败的原因常见的大致有2种:
  1、测试元素被修改了,导致被测试元素无法识别;这个是硬伤暂时还没有什么要的方法,看到百度qa有一篇文章说的是关于动态获取客户端元素信息的文章,可能不是适应所有的场景,但是理念还是可以借鉴一下,日后可能会运用到web上来。原文章在这http://qa.baidu.com/blog/?p=206
  2、测试过程较复杂导致过程中由于网络等不定因素影响测试结果。如等待时间过长、出现无效页面、出现非预期的窗口;其实这些情况在平时手工操作都没有什么大问题,但是用在自动化过程中,尤其是批量反复执行的过程中容易在某个用例场景里随机出现。
  这里讲到的工具是针对第2个问题的,提出一种设想即假定一个测试场景需要10个步骤,我们到如果通过gui一步步测试的话需要依次访问10个页面;而这10个步骤中有可能某个步骤在测试过程中由于不明原因导致场景失败,即你还没到终页面挂了;所以如果有一种方法直接把后一步的页面返回给浏览器的话,可以减少这个原因导致的测试失败了。
  具体的方案我们团队讨论了好几种,但大概原理都是一样的;即10个页面的访问中把前9个使用代码来完成,把后获得到的第10个页面的内容直接返回给测试者,这样跳过前9步在GUI上面的执行,提高了测试的效率,降低了测试不稳定因素。
  下面是具体的代码,暂时没有提供设置页面,这里只是原型,后期会在github上更新版本。
  main.py
#!/usr/bin/python
#encoding: utf-8
import web
import httplib, urllib
import sys
print sys.getdefaultencoding()
reload(sys)
sys.setdefaultencoding('utf-8')
print sys.getdefaultencoding()
urls = (
'/', 'hello',
'/(.*)', 'seeother',
)
from config import *
from hosts import hosts
web.config.debug = isdebug
app = web.application(urls, globals())
def do_proxy(method, host, path, data=None, headers={}):
print 'request header: %s' % headers
conn = httplib.HTTPConnection(hosts.get(host, host))
conn.request(method, path, body=data, headers=headers)
response = conn.getresponse()
r = [response.status, response.reason, response.read(), response.getheaders()]
print 'response result: %s' % r[:2]
#    print 'reseponse body: %s' % r[2]
conn.close()
return r
#import re
#hrefpat = re.compile(r'''href="(/.*?)"''', re.M)
#srcpat = re.compile(r'''src="(/.*?)"''', re.M)
#def replace_short_url(r):
#
#    data = r[2]
#    if hrefpat.search(data):
#        for n in hrefpat.finditer(data):
#            nn = 'href="http://%s%s"' % (goal_host, n.group(1))
#            data = data.replace(n.group(), nn)
#    if srcpat.search(data):
#        for n in srcpat.finditer(data):
#            nn = 'src="http://%s%s"' % (goal_host, n.group(1))
#            data = data.replace(n.group(), nn)
#    r[2] = data
#    return r
def get_http_request_info(headerappend):
env = web.ctx.env
#    print env
request_method = env['REQUEST_METHOD']
request_path = env['REQUEST_URI']
postdata = urllib.urlencode(web.input())
headers = {}
httpkeys = [i for i in env.keys() if i.startswith("HTTP_")]
for k in httpkeys:
headers[k[5:].replace('_', '-').lower()] = env[k]
headers['host'] = goal_host
headers['referer'] = 'http://%s/' % goal_host
headers['accept-encoding'] = 'identity'
if headerappend:
for k,v in headerappend.items():
headers[k] = v
return (request_method, '%s:%s' % (goal_host, env['SERVER_PORT']), request_path, postdata, headers)
from httpstatus import httpstatus
def set_http_response_info(r):
for h in r[3]:
if h[0] != 'cnotent-encoding':
web.header(h[0], h[1])
if h[0] == 'location':
location = h[1]
status = httpstatus.get(r[0])
if r[0] == 200:
return r[2]
elif r[0] == 301:
return status(location)
elif r[0] == 302:
return status(location)
elif r[0] == 303:
return status(location)
elif r[0] == 307:
return status(location)
elif r[0] == 404:
return status(r[2])
elif r[0] >= 500:
return status('%s %s' % r[:2], r[1])
else:
return status()
class seeother:
def GET(self, par):
print 'see other'
http_request_info = get_http_request_info(auth_header)
r = do_proxy(*http_request_info)
return set_http_response_info(r)
def POST(self, par):
return self.GET(par)
class hello:
def GET(self):
http_request_info = get_http_request_info(auth_header)
headers = http_request_info[4]
r = do_proxy("GET", "%s:%s" % (goal_host, 80), "/", "", headers)
return set_http_response_info(r)
if __name__ == "__main__":
app.run()
httpstatus.py
[python] view plaincopy在CODE上查看代码片派生到我的代码片
#!/usr/bin/python
#encoding: utf-8
from web import HTTPError
import web
class InternalError(HTTPError):
"""500 Internal Server Error`."""
message = "internal server error"
def __init__(self, status, message=None):
headers = {'Content-Type': 'text/html'}
HTTPError.__init__(self, status, headers, message or self.message)
internalerror = InternalError
httpstatus = {
200 : web.ok,
201 : web.created,
202 : web.accepted,
301 : web.redirect,
302 : web.found,
303 : web.seeother,
304 : web.notmodified,
307 : web.tempredirect,
400 : web.badrequest,
401 : web.unauthorized,
403 : web.forbidden,
404 : web.notfound,
405 : web.nomethod,
406 : web.notacceptable,
409 : web.conflict,
410 : web.gone,
412 : web.preconditionfailed,
500 : internalerror,
501 : internalerror,
502 : internalerror,
503 : internalerror,
504 : internalerror,
505 : internalerror,
}