0


学好selenium工具,就能实现你想得到的所有事情

文章目录

一、介绍背景

情况是这样的:某段时间之前,开发想找我用ui自动化帮他们实现一个功能:在系统某些时候生成报告的时候会failed,但是又不再重新生成,因此需要人工edit再次submit才能生成,原因png是由当前html页面生成。但是作为测试的我有一个疑惑?开始不是常用定时任务或是失败重试吗?怎么不这样做呢?或者有其他办法使之成功呢?然后开发自己优化了一下,就默默的成功了,这事儿就算过去了,不曾想几天前又复活了,需要我来协助,然后我问,这玩意儿不能使用接口去完成吗?开发解释:不能,why?原因是html转png:前端拿到接口响应数据,动态绘制html,然后再生成png。那么问题来了:为什么会失败?什么情况下会失败呢?

二、开发与实现

作者的python开发环境那是有好几套,接口、ui自动化的环境那是现成的,拿来即用,这里仅用来演示步骤。

2.1、部署开发环境

下载python安装包,一路默认,会自动加入path环境变量;
pip工具安装:pip install selenium
再下载对应chromedriver浏览器驱动:https://chromedriver.storage.googleapis.com/index.html

2.2、开始码代码<demo只为提供思路>

又因为作者是有比较系统的ui自动化测试思想,首先是po模式,但是这个需求是一次性的,所以并不想把它复杂化<相对线性脚本>,本着开发效率出发<不曾想也花了一天的时间,主要耗时在调试脚本>

#!/bin/python3# -*-coding: utf-8 -*-# 编码在linux环境下才能识别中文import json
import logging
from time import sleep
import time

import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

# 日志系统
log_format ='%(asctime)s - %(levelname)s - %(message)s'
logging.basicConfig(filename="scoreSys.log", filemode='a+',format=log_format, level=logging.DEBUG)

options = webdriver.ChromeOptions()#options.add_argument('--disable-gpu')#options.add_argument('--headless')#options.add_argument('--no-sandbox')#options.add_argument('--disable-dev-shm-usage')# 初始化页面对象
driver = webdriver.Chrome(executable_path="../chromedriver.exe", options=options)"""打开浏览器"""# https://score.ieltsbro.com/
logging.info(">>>>>>>>>>>>>>>>>打开口语报告系统<<<<<<<<<<<<<<<<<<<<<<")#     driver.get("https://xxx.xxx.com/home")
driver.get("https://uat.xxx.xxx.com/xxx/home")
driver.maximize_window()
driver.implicitly_wait(10)# 登录页,页面元素
account_input =(By.XPATH,"//input[@placeholder='Email']")
passwd_input =(By.XPATH,"//input[@placeholder='Password']")
verify_code =(By.XPATH,"//input[@placeholder='Code']")
signIn_btn =(By.XPATH,"//span[text()=' Sign In ']")# 登录的操作步骤
driver.find_element(*account_input).send_keys("[email protected]")
driver.find_element(*passwd_input).send_keys("xxxxx")
driver.find_element(*verify_code).send_keys("1234")
driver.find_element(*signIn_btn).click()
logging.info(">>>>>>>>>>>>>>>>>用户登录口语报告系统<<<<<<<<<<<<<<<<<<<<<<")
sleep(1)# ui登录后获取请求头中token属性
headers ={"content-type":"application/json"}# 登录系统后用户名元素
account_text =(By.CSS_SELECTOR,".user_name")
change_passwd =(By.CSS_SELECTOR,".pwdBtn")"""检查登录状态"""
account_info = driver.find_element(*account_text).text
logging.info(">>>>>>>>>>>>>>>>>检查用户是否成功登录系统<<<<<<<<<<<<<<<<<<<<<<")try:assert account_info =="xxxx","断言失败"except:
    logging.info(">>>>>>>>>>>>>>>>>用户:{},登录失败!!!<<<<<<<<<<<<<<<<<<<<<<".format(account_info))else:
    logging.info(">>>>>>>>>>>>>>>>>用户:{},登录成功!!!<<<<<<<<<<<<<<<<<<<<<<".format(account_info))
    userInfo = json.loads(driver.execute_script('return localStorage.getItem("userInfo");'))
    v = json.loads(userInfo.get("v"))
    token = v.get("token")
    headers["token"]= token

# 搜索条件
select_box =(By.XPATH,"//input[@placeholder='Report status']")
select_input =(By.XPATH,"//span[text()='Failed']")
select_btn =(By.XPATH,"//span[text()='Search']")"""输入fail点击查询"""# 查询操作
driver.find_element(*select_box).click()
sleep(1)
driver.find_element(*select_input).click()
driver.find_element(*select_btn).click()# 列表是否有失败状态的
fail_status ="//td//div[text()='Fail']"# 找到失败的edit按钮
edit_btn =(By.XPATH,"{}/../parent::td[1]//following-sibling::td//span[text()='Edit']".format(fail_status))
submit_selector =(By.XPATH,"//div[contains(text(),'Submit')]")"""提交报告"""# 首先按fail条件查询
click_search()# 找到更多需要edit的按钮
status_eles = driver.find_elements(*edit_btn)
ele_nums =len(status_eles)# 页面元素找到元素不唯一# 接口获取fail总数及id列表
nums, fail_li = get_fail_nums()

count =0# 记录真实补偿次数
success_li =[]# 记录成功补偿报告idwhile ele_nums >0:
    status_eles = driver.find_elements(*edit_btn)try:for ele in status_eles:
            clicked = ele.is_displayed()# 因为找到元素不唯一,需要判断元素是否显示if clicked:
                ele.click()
                driver.find_element(*submit_selector).click()# 提交
                success_li.append(driver.current_url.split("=")[-1])#等待提交之后跳转的页面元素是否出现
                WebDriverWait(driver,50).until(EC.presence_of_element_located(change_passwd)) 
                count +=1except:
        ele_nums -=1else:
        ele_nums -=1finally:
        click_search()# 每次需重新查询
            
driver.quit()

2.3、思路分析

  1. 第一步,开发针对我的特殊帐号去除验证码登录,<毕竟实现验证码登录成本还是有的>
  2. 首页增加报告查询条件:success or failed;
  3. 需要发送钉钉通知<这是后面实现>
  4. 操作流程:登录-检查登录状态-查询fail条件的数据-进入编辑页面-点击submit-再重新查询fail条件-如有继续edit-submit,如初反复直到没有fail的数据为止-关闭浏览器

2.4、难点解析

在selenium做ui自动化的时候,最难的不是实现某个功能代码块,而是定位元素的表达式,但是页面又不全是id、name等唯一元素,更多是需要写css_selector\xpath表达式;

  • html的结果页是个table,那么在根据fail失败元素同级找到它的edit,这个如下所示;是不是比较懵圈
# 列表是否有失败状态的
fail_status ="//td//div[text()='Fail']"# 找到失败的edit按钮
edit_btn =(By.XPATH,"{}/../parent::td[1]//following-sibling::td//span[text()='Edit']".format(fail_status))# 解释下上面的表达式:/.. 表示查找上级,parent::表示父级,following-sibling::平级中的下级
  • 其实实现之后并不需要如此,因为是先按fail条件查询,那么剩下就是fail,直接找edit即可。
  • 难点是ui+接口的结合;因为上述代码之初,在找到需要重新submit的报告,数目不正确,因为元素重复不唯一<每个元素都有显示和隐藏>,
clicked = ele.is_displayed()# 因为找到元素不唯一,需要判断元素是否显示
  • 所以想通过接口来确定真正fail的条数,所以先ui登录,获取token传递给接口请求,在这里插入图片描述
# 这是个新技能点,每次尝试不同的需求,总会遇到不同的问题,然后找到解决方案
userInfo = json.loads(driver.execute_script('return localStorage.getItem("userInfo");'))# 这个userInfo是key,而不是直接叫token
从demo中可以看出作者的po思想,将定位元素的标识单独提取出来保存,没直接放在方法里
  • 从demo中可以看出作者的po思想,将定位元素的标识单独提取出来保存,没直接放在方法里

这里提醒所有重试UI自动化测试的工作者:写代码不是为了去实现某个功能;而是提炼思想,解决思想问题,因为功能问题早晚都有解决办法,而解决问题的思想没有,那就真的没有了。

三、总结

条条大路通罗马,不是所有问题都只有一种解决办法,而是任何问题都会有解决办法。解决问题的思路很重要,思维、眼界需要打开,会有不一样的风景,感谢您的收看,咱们下次再见!日拱一卒无有尽,功不唐捐终入海。


本文转载自: https://blog.csdn.net/u011466469/article/details/128248676
版权归原作者 我先测了 所有, 如有侵权,请联系我们删除。

“学好selenium工具,就能实现你想得到的所有事情”的评论:

还没有评论