1.selenium原理
- 架构层面的解读
selenium安装:pip install selenium;chromedriver.exe;浏览器。
python代码与浏览器之间通过驱动建立连接。
python ----http请求---> chromedriver.exe--js-->浏览器
不止python语言,Java、go、js都可以通过发送http请求,chromedriver.exe将请求里面的一些参数转换成相关的JS代码,浏览器接收到执行相关的操作。
- 源码层面定位解读
webdriver模块中,Service方法通过代码方式启动可执行文件,start()方法帮助我们把手动去启动chromedriver.exe的命令去转化为代码;RemoteWebDriver中RemoteConnection将访问chromedriver中的访问服务接口转化为代码,通过execute()方法进行发送请求,最终将传入的参数转化为method,url,body。
封装各种函数,最后都会调用execute()方法进行发送请求。
初始化浏览器的类 Chrome()做了两件事,
- 通过subpocess.Popen()启动chromedriver.exe
- 通过RemoteConnection初始化了很多的接口url,请求方法。得到需要访问的url和请求方法。
- 最终当我们调用driver下的方法时,最终都会调用execute()方法,而execute()方法又是调用_request()方法
比如:
driver.find_element(url)==>execute()--->_request(method,url,body)
driver.get()-->_request(method,url,body)
2.扩展:关键字驱动
关键字驱动和数据驱动的区别在于:不仅隔离了数据,而且把需要执行的动过也以字符串的形式,存放到表格当中。和数据驱动相同的是,它还是只有一个通用的测试执行函数。当运行测试脚本时,每条数据和动作会一起作为参数传入执行函数中。
我们来举一个实际的例子,首先创建一个excel/yaml文件存储一条用例的所有测试步骤,需要调用的操作和数据。
yaml文件中代码:
# - 表示list
- # 访问url
action: goto
params:
url: "https://v4.ketangpai.com/user/login.html"
- # 输入用户名
action: fill
params:
locator: ['css selector','input[name="account"]']
words: "looker53@sina.com"
- # 输入密码
action: fill
params:
locator: ['css selector','input[name="pass"]']
words: "xxxxxxxxxx"
- # 点击登录
action: click
params:
locator: ['css selector','.btn-btn']
- # 断言
action: assert_element_attribute_equal
params:
locator: ['css selector','.avatar']
name: "title"
expected: "yuze"
然后编写一个调用的函数调用yaml中的动作和数据:
import yaml
from pages.basepage import Page
def test_login_keyword(browser):
"""关键字驱动的测试函数"""
# 1、读取yaml文件的内容,包含浏览器操作和对应的测试数据
# 2、需要一个页面对象,调用basepage 浏览器操作
with open(r'keywords_login.yaml', encoding='utf-8') as f:
steps = yaml.safe_load(f)
page = Page(browser)
for step in steps:
method_name = step['action']
method_params = step['params']
# 通过方法名称获取方法
# getattr(page,metnod_name) 获取方法的内存地址
method = getattr(page, method_name)
# 调用方法
method(**method_params)
动作需要提前编写在某个固定的模块或者类中,然后通过getattr这种动态获取动作的操作从类中提取动作,再传入测试数据。比如上面的例子中,goto、fill、click动作都保存在一个BasePage的类中。
import time
from selenium.webdriver import Chrome, ActionChains, Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as when
from setting import config
class Page:
# driver: Chrome 解释driver的类型。方面后续使用时有提示
def __init__(self, driver: Chrome):
self.browser = driver
def goto(self, url):
"""去哪个url地址"""
return self.browser.get(url)
def fill(self, locator, words):
"""输入框内输入信息"""
# locator是列表,*locator解包
el = self.browser.find_element(*locator)
el.send_keys(words)
def click(self, locator):
"""点击"""
wait = WebDriverWait(self.browser, timeout=15)
# 元组形式传进去
condition = when.element_to_be_clickable(locator)
element = wait.until(condition)
# element.click()
# 鼠标操作,点击操作的封装最好使用ActionChains
ActionChains(self.browser).click(element).perform()
def assert_element_attribute_equal(self, locator, name, expected):
"""断言某个元素的属性等于"""
el = self.browser.find_element(*locator)
assert el.get_attribute(name) == expected
数据驱动是一种很好的模式,在进行接口自动化测试这样统一步骤的场景下非常有用。在ui自动化测试时,用硬编码或者和关键字驱动会更加合适。
参考资料:What is Data Driven Testing? Learn to create Framework
3.扩展:失败重运行
pip install pytest-rerunfailures
#terminal中输入该命令,表示如果失败,重新运行2遍
命令:pytest --reruns 2
或者代码中定义:
pytest.main(['--alluredir=output','--reruns','2'])
4.扩展:并发
解决:用例运行速度慢,使用插件:pytest-xdist(pip install pytest-xdist)
并发执行,表示可以同时执行多条case。
命令:pytest -n 4 ,表示同时执行4条case
注意事项:用例和用例之间不要有依赖关系。
并发数(worker)不是越多越好,与电脑性能有关,通常就是电脑的核数。
5.总结
1、web自动化测试执行流程,或者selenium操作原理
2、元素定位:
- 元素定位方式:8种,其实4种(源码中id,tag_name,name,class name 都是CSS选择器)
3、xpath vs css选择器
- css选择器整体上来说比xpath的表示更简洁;
- css选择器查找速度比xpath要快;
- xpath的功能比css选择器更强;
- 对于复杂元素xpath反而会更简洁;
- css选择器目前不支持通过文本查找元素,xpath可以。
4、如果元素定位出错,元素定位不稳定,可能的原因是什么?
- 检验元素定位表达式(浏览器F12源码中校验)
- 元素没有加载出来(等待)
- 查看元素是否在当前页面上(窗口,iframe,alert)
- 属性值是否是动态变化的(数字/active/hidden/加密数据)
5、等待方式
- 强制等待,显性和隐性不能解决时
- 显性等待,设置条件
- 隐性等待,查找元素
6、如何操作,上传文件,快捷键等
7、PO模式
8、web自动化测试框架是怎么搭建的?
- 分层,po,数据,basepage,locator,配置文件
- 模块介绍
9、怎么去做前置后置,pytest:夹具
- conftest.py文件中


356

被折叠的 条评论
为什么被折叠?



