python+browsermob-proxy+selenium实现打点自动化验收

背景:

由于工作中有测打点的需求,所以就思考如何能使其自动化呢?
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')

你可能感兴趣的:(python+browsermob-proxy+selenium实现打点自动化验收)