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()

浙公网安备 33010602011771号