1.浏览器操作
from selenium import webdriver
from selenium.webdriver.common.by import By
(1)
driver = webdriver.Chrome()
#启动chromedriver服务,连接chromedriver服务
打开一个浏览器。开启与浏览器的会话。
(2)访问 网站
driver.get(“http://www.baidu.com”) # 第一个页面
(3)最大化窗口,最小化窗口
driver.maximize_window() # 大
driver.minimize_window() # 小
(4)设置窗口大小
driver.set_window_size()
(5)重新加载页面 - F5
driver.refresh()
(6)回到上一个页面,前进
driver.back()
(7)回到下一个页面,后退
driver.forward()
(8)关闭当前窗口
driver.close() # 只是关闭当前窗口。会话仍然存在。
(9)关闭这个会话
driver.quit() # 所有事情干完之后,应该当,关闭这个会话。关闭chromedriver服务。
#--------------------------------------------------------------------------------------------------#
2.元素定位8大定位
# 第1类:靠元素的单一属性找元素。 6种定位方法:
# 第2类:组合属性来定位元素。— 男生/定居北京/高富帅 2种定位方法:xpath、css选择器。
# 1、id - 身份证。动态的id: # 找元素
# 定位策略:id 值:kw
# 找元素:DOM树。
# 获取元素的属性。
# 元素可选:radio、checkbox
# 元素可用(is_enabled):按钮 - 天生就是可点击。如果是不可击的状态(disabled),表示按钮不可用。
# 输入框:- 天生就是让用户输入信息的。如果是只读状态不可编辑(readonly属性),表示输入框不可用。
# 8种方式查找子元素:在自己的后代元素里查找子元素。
# send_keys :输入操作
# click: 点击操作
# is_displayed:元素在页面中是否可见。
# 元素的三种状态:元素存在(find) < 元素可见 < 元素可用
(1)id定位
element = driver.find_element_by_id(“kw”) # WebElement对象,封装你对元素想干的事情。
print(element.tag_name)
eels2 = driver.find_element(“id”,“kw”)
ele2 = driver.find_element(By.ID,“kw”)
print(ele2.tag_name)
(2)tag_name 标签名定位。
el = driver.find_element_by_tag_name(“input”)
# driver.find_element(By.TAG_NAME,“input”)
# 返回第一个匹配到的元素。
els = driver.find_elements_by_tag_name(“input”)
# driver.find_elements(By.TAG_NAME,“input”)
# 返回所有匹配到的元素。==列表,列表都是WebElement对象pri
(3)元素name属性定位
driver.find_element_by_name("")
driver.find_elements_by_name("")
(4)class属性定位
driver.find_element_by_class_name("bg") # 参数只能是一种装修风格,只能是一个class值。
driver.find_elements_by_class_name("bg")
(5)(6)a元素-链接。
driver.find_element_by_link_text("hao123")
driver.find_element_by_partial_link_text("hao")
# 返回第一个匹配到的元素。
driver.find_elements_by_link_text("")
driver.find_elements_by_partial_link_text("")
# 返回所有匹配到的元素。==列表
(7)xpath定位:
# 绝对定位
/html/body/div[2]/div/form/div[1]/input # 按照路径一级一级定位
# 相对定位元素的相对位置,按照类型做筛选
# 基本用法:
//标签名[@属性名称=值]
# 逻辑运算:
//标签名[@属性名称=值 and/or @属性名称=值]
# 文本定位,不变动的属性或者文件。
//标签名[contains(@属性/text(),要包含的内容)]
# 层级定位,通过祖宗限定范围后,再找自己。
# //div[@id="u1"]//a[@name="tj_login"]
(8)xpath轴定位
# 轴运算:
ancestor:祖先结点 包括父
parent:父结点 给g
preceding: 当前元素节点标签之前的所有结点。(html页面先后顺序)
preceding-sibling: 当前元素节点标签之前的所有兄弟结点
following: 当前元素节点标签之后的所有结点。(html页面先后顺序)
following-sibling:当前元素节点标签之后的所有兄弟结点
# 使用语法:
已知的元素/轴名称::标签名称[@属性=值]
例://div//table//td//preceding::td
//dd[@data-val="张芝波"]/following-sibling::dd[contains(@class,"batscore")]/span
driver.find_element_by_xpath(' //div[@id="u1"]//a[@name="tj_login"]')
#--------------------------------------------------------------------------------------------------#
3.等待时间
(1)强制等待
time.sleep(3) # 强制等待
(2)隐性等待
driver.implicitly_wait(30) # 隐性等待,智能等待,元素存在
(3)显性等待
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome() # 会话的起始标志。
driver.implicitly_wait(30)
driver.get("http://www.baidu.com")
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()
# 弹出了登陆框 - 页面的变化 默认0.5秒
# WebDriverWait(driver,等待上限,轮询周期).until(条件)
loc = (By.ID,"TANGRAM__PSP_10__footerULoginBtn")
WebDriverWait(driver,10).until(EC.visibility_of_element_located(loc))
# EC.visibility_of_element_located(loc)
# 元素可见 visibility_of_element_located EC.visibility_of_element_located(loc)
# 元素们可见 EC.visibility_of_all_elements_located
time.sleep(1)
driver.find_element(*loc).click()
#--------------------------------------------------------------------------------------------------#
4.切换句柄
from selenium import webdriver
driver = webdriver.Chrome() # 会话的起始标志。
driver.get(“http://www.baidu.com”)
# 搜索 柠檬班,点击柠檬班第一个结果。
driver.find_element_by_id("kw").send_keys("柠檬班")
driver.find_element_by_id("su").click()
# 要等待结果出现,搜索结果当中,选第一个
loc = (By.XPATH,'//a[text()="腾讯课堂 - 机构主页"]')
WebDriverWait(driver,20).until(EC.visibility_of_element_located(loc))
driver.find_element(*loc).click()
# 导致新的窗口出现了。
# 等待有新的窗口出现,我再去切换窗口。
time.sleep(0.5)
(1)获取所有窗口的句柄
wins = driver.window_handles
print("所有窗口句柄:",wins)
(2)获取当前窗口的句柄
cur_win = driver.current_window_handle
print("当前的窗口句柄是:",cur_win)
(3)windows切换,切换到最新打开的窗口
driver.switch_to.window(wins[-1])
# 新的窗口
loc = (By.XPATH,'//ul[@id="js-tab"]//h2[contains(text(),"老师")]')
WebDriverWait(driver,20).until(EC.visibility_of_element_located(loc))
driver.find_element(*loc).click()
# EC.new_window_is_opened
(4)iframe切换
driver.switch_to.frame("login_frame_qq") #name
driver.switch_to.frame(2) # 下标
driver.switch_to.frame(driver.find_element_by_name('login_frame_qq')) # webElement对象
# 切换完成之后,就直接是新的html页面里定位。
# 切出来,直接切换到默认的主页面
driver.switch_to.default_content()
# 切到上一个iframe
driver.switch_to.parent_frame()
(5)alert切换
from selenium import webdriver
driver = webdriver.Chrome() # 会话的起始标志。
driver.get(r"D:\Pychram-Workspace\py22-Web-Study\web_1122\xj_demo.html")
# 做一动作,非html弹出框出现
driver.find_element_by_id("press").click()
time.sleep(1)
# 切换
al = driver.switch_to.alert
# 关掉这个弹出框
al.dismiss() # 取消
# al.accept() # 确定
print(al.text) # 获取弹出框的文本
(6)总结
"""
1、显性等待:WebdriverWait等待\expected_condition条件
WebdriverWait(driver,20).until(EC.条件)
辅助等待:sleep
2、3大切换
windows切换
iframe切换
alert切换
1)动作:导致窗口,iframe,alert出现。
2)找到你要切换的它:窗口(先得到所有句柄,再切换到窗口句柄)、
iframe(name、下标、webelement对象)
alert
3) 切换:driver.switch_to.window/frame/alert
4) 关闭alert
"""
#--------------------------------------------------------------------------------------------------#
5.pytest
(1)与unittest的区别
1)用例的编写?支持函数
2)用例的识别?自动化识别。识别规则?目录-文件名-用例名 pytest命令行(pytest.main())
3)用例的断言?assert 表达式(结果为True,False) - 逻辑/比较/函数返回值。 unittest:self.assertXXXX
4)用例的报告?unitest/pytest --html。但是 pytest是可以集成第三方报告工具-allure
pytest有非常丰富的插件:700+
(2)语言写用例的用例框架共性:
1)写用例: 前置、步骤、断言、后置。 pytest如何表达前置后置?
2)运行用例:unitest、pytest .main()
3)生成报告:
4)组织用例:筛选用例的功能?
5)运行用例时的配置:用例失败重试(unittest不自带、pytest自带)
6)数据驱动支持:unitest:ddt pytest:参数化
(3)pytest前置后置:(不可以与unittest、ddt共存)
pytest: fixture - 前置&后置。
级别:1、用例会话(session)级别:接口自动化当的数据库连接。
2、模块(.py/module)级别:
3、测试类(class)级别
4、测试用例(def/function)级别
定义:一个函数包含前置和后置。
0) 确定级别:夹心饼干到底夹什么。
1)怎么区分前和后? 银河:yield
2)函数名称可以随便定义,如何识别为前置后置?
函数前面@pytest.fixture
3) 如果用例要使用 前置当中的变量,怎么办?
返回用例要使用的变量。yield 返回值。
用例调用的时候, fixture的函数名称作为用例的参数,接收它的返回值
调用(与测试用例关联用例):
用例级别:
类前面,@pytest.mark.usefixtures("fixture的函数名称")
测试函数前面,@pytest.mark.usefixtures("fixture的函数名称")
# conftest.py -- 前置后置全局共享
作用域:仅限于当前目录以及它的子孙后代目录当中的用例。
定义各个级别的 fixture
fixture可以继承fixture: ????
# module \ session ???
参数化: 实现数据驱动 @pytest.mark.parametrize("case",LD.wrong_datas)
筛选用例 :给用例打标记。
93个人 -- 93个用例
运行:全是妹纸! -- 40个 标记:女
1步:向pytest注册你的标记。 pytest.ini
2步:在需要标记的用例上面,打上标记。
用例上面:@pytest.mark.标记名
3步:运行 已标记 的用例。 pytest参数:-m 标签名
(4)数据驱动
@pytest.mark.parametrize
(5)用例打标签
1)注册标签名:创建一个pytest.ini配置文件 前两行为固定格式,第三行为标记名称
[pytest]
markers=
smoke
2)使用方法1:再用例上方标记,可以再类上方标记(标记类中所有的测试用例),
也可以单独在测试用例上方标记,一个用例或者类可以重复标记多个。
@pytest.mark.标签名
3)使用方法2:也可以再用例类下方标记
标记范圈:测试用例、测试类、模块文件,使用以下申明测试类下,所有用例都被打上该标签)
class TestClass(object)
pytestmark = pytest.mark.标签名
pytestmark= [pytest.mark.标签1,pytest.mark.标签2]#多标签模式
同理(py文件下,所有测试函数和测试类里的测试函数,都有该标签import pytest
pytestmark = pytest.mark.webtest
pytestmark= [pytest.mark.标签1,pytest.mark.标签2]#多标签模式
4)运行
在命令行下运行:pytest -m 标签名
在脚本中运行:pytest.main(["-m","标签名"])
(6)测试报告
(7)重复执行
1)安装重运行插件:pip install pytest-rerunfailures
2)运行
在命令行下运行:pytest -m 标签名
在脚本中运行:pytest.main(["--reruns","2","--reruns-delay","5"]) #重运行两次,间隔5秒
#--------------------------------------------------------------------------------------------------#