背景:
由于工作中有测打点的需求,所以就思考如何能使其自动化呢?
1)思路,回忆手动测试的过程,主要有两步(抓包a,b和验证c):
a.在浏览器到指定页面查看某个位置的广告或图片是否展现,并抓取打点请求;
b.或在指定页面指定位置下,点击某广告或图片,点击他们,并抓取打点请求;
c.把抓到的请求跟产品的打点文档进行对比字段,查看是否传某些特定参数,以及参数值是否正确
2)行动:手工测试流程出来之后,只要模拟手工测试的过程写demo就行,后续还可以完善批量执行的过程,以及平台工具了,思路清晰后就想需要完成这些我需要做什么?
同样是两步:抓包和验证;
抓包:在网上查了一下,做代理的最终选择browsermob-proxy,当然还需要selenium的配合,来模拟我们打开页面,点击某等动作
验证:因为打点参数是key-value的,所以使用dict取key验证value即可
工具准备:
1、browsermob-proxy server下载:http://bmp.lightbody.net/
2、pip install browsermob-proxy
3、pip install selenium
4、chromedriver的下载:http://testqa.cn/article/detail/242
使用browsermob-proxy遇到的问题:
1、java子进程没有被关闭:
使用browsermob-proxy的demo:
from browsermobproxy import Server
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import json
import time
# port = {"port":8811}
server = Server(r"D:\program\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat")
server.start()
proxy = server.create_proxy()
chrome_option = Options()
chrome_option.add_argument('--proxy-server={0}'.format(proxy.proxy))
driver = webdriver.Chrome(chrome_options=chrome_option)
base_url = "https://www.baidu.com/s"
proxy.new_har("baidu", options={'captureHeaders': True, 'captureContent': True})
driver.get(base_url)
result = proxy.har
# proxy.wait_for_traffic_to_stop(1,60)
# 导出成har文件
with open('proxytest.har','w') as outfile:
json.dump(proxy.har,outfile)
# 从抓取遍历
for entry in result['log']['entries']:
_url = entry['request']['url']
if "kuaichuan" in _url:
print(_url)
# 抓取请求方法和请求参数
_method = entry['request']['method']
_queryString = entry['request']['queryString']
print(_method)
print(_queryString)
# proxy.close() # 关闭java子进程,解决地址被占用的问题
server.stop()
driver.quit()
这里有个坑,就是这里关闭时其实他没有关闭java子进程,导致每次再重新执行时就报“地址被占用”,后来看到了解决方案(垃圾,不OK!!!):
在server.stop()之前先执行:
proxy.close()
解决方案:https://github.com/AutomatedTester/browsermob-proxy-py/issues/8
后来直接使用python执行cmd命令,杀java进程
import psutil
import os
def killjava():
pids = psutil.pids()
for pid in pids:
p = psutil.Process(pid)
print('pid-%s,pname-%s' % (pid, p.name()))
if 'java.exe' in p.name():
cmd = 'taskkill /f /im java.exe'
os.system(cmd)
执行完最后调用一下这个方法,只能想到这里了。。。不好!!前后都加了,有时候还是有报错,偶尔需要运行第二遍,但是目前只能先这么解决了!!
2、ssl配置,获取https请求:
参考:https://stackoverflow.com/questions/57219570/how-to-handle-ssl-certificate-in-browser-mob-proxy-using-selenium-python
需要对driver增加一个desired_capabilities配置:
# r = requests.post('http://localhost:8080/proxy', data = {'trustAllServers':'true'})
capabilities = webdriver.DesiredCapabilities().CHROME
capabilities['acceptInsecureCerts'] = True
driver = webdriver.Chrome(chrome_options=chrome_options,desired_capabilities=capabilities)
解决完这两个问题,基本就是selenium的事情啦,哦吼吼~~~
3、跳转新窗口,之前的请求(todo)
完整代码(以点击导航首页的广告为例)
1、配置文件格式:
[
{
"url": "https://hao.123.com/", //打点页面
"find_element": "//img[@src='https://s3m.mediav.com/tmanager/373606df094109ede8743a4d22429221.jpg']",//xpath路径定位元素
"action": "click",// 具体行为
"dotInterface": "https://papi.look.cn/srv/c", // 打点域名和接口
"varify": "{'uid': 'not null','sign': '360_37ccb7e5','channel': 'youlike','act': 'click'}"// 打点接口需验证的parameter
},{
......
}
]
2、完整代码(待完善)
import json
import unittest
import ddt
from BeautifulReport import BeautifulReport as bf
import time
from browsermobproxy import Server
from selenium import webdriver
import psutil
import os
import re
'''验证打点,配置文件getdot.json'''
filename = 'getdot.json'
@ddt.ddt
class GetDot(unittest.TestCase):
# class GetDot():
@classmethod
def setUpClass(cls):
print("****start****")
@classmethod
def tearDownClass(cls):
print("***end***")
@classmethod
def varify(cls, real,exp):
'''
验证实际值和预期值是否一致
:param real: 实际值
:param exp: 预期值
:return: True是一致,False是不一致
'''
if isinstance(exp,dict) and len(real) == len(exp):
for key in exp.keys():
if key not in real.keys():
return False
else:
# 非空字符只需要判断有值即可
if key in ['url', 'uid'] and real[key] != "" and real[key] != None:
continue
else:
if exp[key] != real[key]:
return False
else:
continue
return True
else:
return False
@classmethod
def killjava(cls):
'''杀本地java子进程'''
pids = psutil.pids()
for pid in pids:
p = psutil.Process(pid)
# print('pid-%s,pname-%s' % (pid, p.name()))
if 'java.exe' in p.name():
cmd = 'taskkill /f /im java.exe'
os.system(cmd)
@classmethod
def creatDriver(cls):
'''配置代理 和 chromedriver'''
GetDot.killjava()
server = Server(r"D:\program\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat")
server.start()
proxy = server.create_proxy()
proxy.selenium_proxy()
proxy.new_har("kuaichuan", options={'captureHeaders': True, 'captureContent': True})
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
capabilities = webdriver.DesiredCapabilities().CHROME
capabilities['acceptInsecureCerts'] = True
driver = webdriver.Chrome(chrome_options=chrome_options, desired_capabilities=capabilities)
return driver,proxy
@classmethod
def url2dict(cls,url):
new_u = re.split(r'[?,&]', url)
new_u.pop(0)
url_dict = {}
print(new_u)
for i in new_u:
i = str(i).split("=")
url_dict[i[0]] = i[1]
return url_dict
@ddt.file_data(filename)
def test_varify(self,url,find_element,action,dotInterface,varify):
driver,proxy = GetDot.creatDriver()
driver.get(url)
time.sleep(5)
if action == "click":
driver.find_element_by_xpath(find_element).click()
time.sleep(5)
result = proxy.har
# print("!!@@@@@@@@@@@")
print(dotInterface)
for entry in result['log']['entries']:
_url = entry['request']['url']
print(_url)
if dotInterface in _url:
# print(_url)
# real = GetDot.url2dict(_url)
real = entry['request']['queryString']
# print("*******************query")
print(real)
print(varify)
self.assertEqual(varify,True)
# GetDot.varify(real,varify)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(GetDot)
run = bf(suite)
run.report(filename='varify', description='test_get_dot')