Pywifi和Selenium的使用

前言

最近在适配AP驱动,为了测试稳定性,需要不停的断连AP,人工测试就是有麒麟臂的加持,也是效率极低的,所以想到使用Python写个脚本自动化操作。

利用pywifi我们实现wifi的断连操作;利用pythonping可以实现ping操作,检测网络是否通畅;selenium则是一个可以控制浏览器打开网页的自动化工具,详细介绍可以点击这里,自行修改元素。主要使用以上三个库,实现对AP稳定性和加流量压力的测试。

脚本先扫描指定AP是否存在,连接后ping指定IP,通畅则再打开浏览器,循环测试,并将测试过程记录到logging日志中

代码


import pywifi
import time
from pywifi import const
from pythonping import ping

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

import logging
from logging.handlers import RotatingFileHandler

# AP信息
TARGET_SSID = "AP_WIFI_TESTTEST"
SSID_KEY = "12345678"
TARGET_IP = "192.168.8.1"
# 网页信息
HOST_NAME = "http://192.168.8.1/"
USERNAME = "admin"
PASSWORD = "password"
# 日志路径
LOG_PATH = "..\\log\\wifi_test_log"


# 日志初始化类
class LogHelper:
    def __init__(self, log_path):
        self.logger = logging.getLogger('wifi_log')
        self.logger.setLevel(logging.INFO)
        # 写入文件,如果文件超过512k大小时,切割日志文件,保留100个文件
        wifi_test_log = RotatingFileHandler(log_path, maxBytes=512 * 1024, backupCount=100,
                                            encoding='utf-8')
        # 向文件输出的日志级别
        wifi_test_log.setLevel(logging.DEBUG)
        # 向文件输出的日志信息格式
        formatter = logging.Formatter(
            '%(asctime)s - line:%(lineno)d - %(levelname)s - %(message)s')
        wifi_test_log.setFormatter(formatter)
        # 加载文件到logger对象中
        self.logger.addHandler(wifi_test_log)

    def getLoger(self):
        return self.logger


# 全局日志
loggerH = LogHelper(LOG_PATH)
logger = loggerH.getLoger()


# wifi操作类
class WifiHelper:
    def __init__(self, ssid, key, ip):
        print("WifiHelper init")
        self.ssid = ssid
        self.key = key
        self.IP = ip
        wifi = pywifi.PyWiFi()
        # 取第一个无线网卡
        self.iface = wifi.interfaces()[0]
        logger.info("wifi interface is [%s]" % self.iface.name())

    def ssidExist(self):
        # 判断ssid是否存在
        self.iface.scan()
        time.sleep(3)
        bessis = self.iface.scan_results()
        for data in bessis:
            if data.ssid == self.ssid:
                return True

        return False

    def disconnectAP(self):
        # 断开连接
        if self.iface.status() != const.IFACE_DISCONNECTED:
            logger.info("Disconnect wifi interface [%s] SSID [%s]", self.iface.name(), self.ssid)
            self.iface.disconnect()

    def connectAP(self):
        # 连接AP
        if self.iface.status() != const.IFACE_DISCONNECTED:
            self.disconnectAP()
            time.sleep(5)

        if self.iface.status() == const.IFACE_DISCONNECTED:
            profile = pywifi.Profile()
            profile.ssid = self.ssid
            profile.auth = const.AUTH_ALG_OPEN  # 需要密码
            profile.akm.append(const.AKM_TYPE_WPA2PSK)  # 加密类型
            profile.cipher = const.CIPHER_TYPE_TKIP  # 加密单元
            if 0 != len(self.key):
                logger.info("connect key [%s]", self.key)
                profile.key = self.key  # 密码

            logger.info("SSID [%s] connecting...", self.ssid)
            self.iface.remove_all_network_profiles()
            time.sleep(3)  # 延时
            tep_profile = self.iface.add_network_profile(profile)
            self.iface.connect(tep_profile)
            time.sleep(5)  # 延时
            if const.IFACE_CONNECTING == self.iface.status():
                time.sleep(5)  # 延时
        # ping host 检查是否成功
        return self.pingHost()

    def pingHost(self):
        # ping 主机,会先检查连接状态和IP
        logger.info("Ping %s ...", self.IP)
        wifi_stat = self.iface.status()
        if wifi_stat != const.IFACE_CONNECTED or 0 == len(self.IP):
            logger.critical("Ping error.Status %d, IP %s ", wifi_stat, self.IP)
            return False

        try_cnt = 0
        while try_cnt < 2:
            response = ping(self.IP)
            if response.success():
                logger.info("Ping [%s] success", TARGET_IP)
                return True
            else:
                logger.critical("Ping [%s] error", TARGET_IP)
            time.sleep(3)
            try_cnt += 1
        return False

    def clearProfile(self):
        # 清空配置
        self.iface.remove_all_network_profiles()


# 页面操作
class OperationHDMHelper:
    driver = ''

    def __init__(self):
        print("OperationHDMHelper init")

    def signInPage(self, hostname, username, password):
        '''
        首页的登陆
        '''
        option = webdriver.ChromeOptions()
        # 不自动关闭浏览器
        option.add_experimental_option("detach", True)
        # 忽略证书错误
        option.add_argument('ignore-certificate-errors')
        # 后台运行
        # option.add_argument('headless')
        # 修改get为非阻塞
        desired_capabilities = DesiredCapabilities.CHROME
        desired_capabilities["pageLoadStrategy"] = "none"
        # 实例化
        self.driver = webdriver.Chrome(executable_path='chromedriver.exe', chrome_options=option)

        # 注意,是阻塞的,需要等页面完全加载完成。为了避免未加载完成程序卡住,所以设置了pageLoadStrategy
        self.driver.get(hostname)
        time.sleep(7)

        # 定位用户名,并登陆. 隐式等待首页加载完成,注意,后面的等待都是这个时间
        self.driver.implicitly_wait(10)
        try:
            self.driver.find_element(By.ID, "username")
        except Exception as e:
            logger.error("Get login page timeout: %s", e)
            return False

        self.driver.find_element(By.ID, "username").send_keys(username)
        self.driver.find_element(By.ID, "password").send_keys(password)
        time.sleep(1)
        self.driver.find_element(By.XPATH,
                                 '//*[@id="app"]/div/div/div[2]/div[2]/div/form/div[3]/div/div/span/button').click()
        return True

    def operateMenu(self):
        '''
        开始操作页面
        '''
        try_cnt = 5
        while try_cnt:
            try_cnt -= 1
            time.sleep(2)
            self.driver.implicitly_wait(5)
            try:  # 点击系统管理
                self.driver.find_element(By.XPATH, '//*[@id="admin-layout"]/header/div[2]/ul/li[4]').click()
            except Exception as e:
                logger.error("get click page1 timeout: %s", e)
                return False
            time.sleep(2)

            self.driver.implicitly_wait(5)
            try:  # 远程运维
                self.driver.find_element(By.XPATH,
                                         '// *[ @ id = "admin-layout"] / header / div[2] / ul / li[10]').click()
            except Exception as e:
                logger.error("get click page2 timeout: %s", e)
                return False
            time.sleep(2)

            self.driver.implicitly_wait(5)
            try:  # 首页
                self.driver.find_element(By.XPATH,
                                         '// *[ @ id = "admin-layout"] / header / div[2] / ul / li[2]').click()
            except Exception as e:
                logger.error("get click page3 timeout: %s", e)
                return False

        return True

    def signOutPage(self):
        self.driver.implicitly_wait(5)
        try:  # 点击头像
            self.driver.find_element(By.XPATH, '//*[@id="admin-layout"]/header/div[3]/div/div/div[2]').click()
        except Exception as e:
            logger.error("get click touxiang timeout: %s", e)
            return False
        time.sleep(2)
        try:  # 点击退出登陆
            self.driver.find_element(By.XPATH,
                                     '//*[@id="admin-layout"]/header/div[3]/div/div/div[2]/div/div/div/div/div[2]/button').click()
        except Exception as e:
            logger.error("get click sign out timeout: %s", e)
            return False
        time.sleep(2)
        try:  # 点击确定
            self.driver.find_element(By.XPATH,
                                     '/html/body/div[4]/div/div[2]/div/div[2]/div/div/div[2]/button[2]').click()
        except Exception as e:
            logger.error("get click queding timeout: %s", e)
            return False
        return True

    def closePage(self):
        # 关闭页面
        self.driver.close()

    def quitDriver(self):
        # 退出
        self.closePage()
        self.driver.quit()


class TestHelper(WifiHelper, OperationHDMHelper):
    def __init__(self, ssid, key, ip):
        WifiHelper.__init__(self, ssid, key, ip)
        OperationHDMHelper.__init__(self)
        self.ssid = ssid

    def onlyTestConnect(self):
        '''
        仅测试AP连接断开
        '''
        succeed_cnt = 0  # 成功计数
        failed_cnt = 0  # 失败计数
        exec_cnt = 0  # 执行计数
        while True:  # 死循环
            exec_cnt += 1
            logger.info("Test connect AP count %d", exec_cnt)
            if self.ssidExist():  # ssid 是否存在
                if self.connectAP():  # 连接AP
                    succeed_cnt += 1
                    failed_cnt = 0
                    logger.info("Connect [%s] success %d", self.ssid, succeed_cnt)
                    if 0 == succeed_cnt % 100:
                        logger.debug("Connect [%s] success %d", self.ssid, succeed_cnt)
                else:  # 没有连接成功
                    failed_cnt += 1
                    logger.error("Connect [%s] failed, failed cnt %d", self.ssid, failed_cnt)
            else:  # ssid 不存在
                failed_cnt += 1
                logger.critical("SSID [%s] not exist, failed cnt %d", self.ssid, failed_cnt)

            time.sleep(15)
            self.disconnectAP()
            if failed_cnt >= 20:
                logger.critical("So many failed, exit")
                exit(1)

    def ConnectAndOperate(self):
        '''
        在连接后测试打开页面
        '''
        ap_succeed_cnt = 0  # AP成功计数
        ap_failed_cnt = 0  # AP失败计数
        ap_exec_cnt = 0  # AP执行计数

        oprt_succeed_cnt = 0  # 成功计数
        oprt_failed_cnt = 0  # 失败计数
        oprt_exec_cnt = 0  # 执行计数
        while True:  # 死循环
            ap_exec_cnt += 1
            logger.info("Test ConnectAndOperate count %d", ap_exec_cnt)
            if self.ssidExist():  # ssid 是否存在
                if self.connectAP():  # 连接AP
                    ap_succeed_cnt += 1
                    ap_failed_cnt = 0  # 失败计数清零
                    logger.debug("Connect [%s] success %d, start operate", self.ssid, ap_succeed_cnt)

                    # 开始执行操作页面,循环次数
                    try_cnt = 20
                    while try_cnt:
                        try_cnt -= 1
                        oprt_exec_cnt += 1
                        if 0 == oprt_exec_cnt % 20:
                            logger.debug("Operate exec cnt %d", oprt_exec_cnt)

                        if self.signInPage(HOST_NAME, USERNAME, PASSWORD):  # 登陆页面
                            # 具体操作
                            if self.operateMenu():  # 操作成功
                                oprt_succeed_cnt += 1
                                oprt_failed_cnt = 0
                                logger.info("Operate success succeed cnt %d", oprt_succeed_cnt)
                            else:  # 页面超时
                                oprt_failed_cnt += 1
                                logger.error("Operate timeout failed cnt %d, exec cnt %d",
                                             oprt_failed_cnt, oprt_exec_cnt)

                        else:  # 不成功
                            oprt_failed_cnt += 1
                            logger.error("Login timeout failed cnt %d, exec cnt %d",
                                         oprt_failed_cnt, oprt_exec_cnt)

                        # 通用操作检查网络
                        if self.pingHost():  # 还能ping通,重新打开页面
                            self.signOutPage()  # 点击退出
                            time.sleep(1)  # 等待显示
                            self.quitDriver()  # 关闭标签即可
                            continue
                        else:  # 不通,退出网页操作
                            self.quitDriver()  # 退出
                            break

                else:  # AP没有连接成功
                    ap_failed_cnt += 1
                    logger.critical("Connect [%s] failed, failed cnt %d, successes cnt %d",
                                    self.ssid, ap_failed_cnt, ap_succeed_cnt)
            else:  # ssid 不存在
                ap_failed_cnt += 1
                logger.critical("SSID [%s] not exist, failed cnt %d, successes cnt %d",
                                self.ssid, ap_failed_cnt, ap_succeed_cnt)

            time.sleep(15)
            self.disconnectAP()
            if ap_failed_cnt >= 20:  # 连续失败20次,退出
                logger.critical("So many failed, exit")
                exit(1)


def main():
    test_helper = TestHelper(TARGET_SSID, SSID_KEY, TARGET_IP)
    test_helper.ConnectAndOperate()


if __name__ == "__main__":
    main()


posted @ 2023-02-19 21:14  小满的博客  阅读(24)  评论(0)    收藏  举报