1. selenium 原理、web自动化方法

一、什么是webUI自动化

通过自动化工具--selenium,按照测试人员的设想--代码逻辑,自动执行测试,简单来说,就是用代码模仿手工操作

webUI自动化的价值:

1、验证逻辑

2、代替大量的重复手工测试

3、ui自动化目标不是发现多少个bug,而是为手工回归测试节省了多少时间

selenium 与 webdriver

selenium 是一个用于web测试的工具,运行在浏览器中,就想真正的用户一样,支持主流的浏览器

webdriver封装了一套操作浏览器的api,因为python代码不能直接操作浏览器

测试脚本,浏览器驱动,浏览器

HTML,也可以叫做页面标签,也会叫做元素

HTML以开始标签起始,以结束标签终止,但有一些例外

部分HTML元素具有空内容

以开始标签的结束而结束

元素的内容是开始容标签与结束标签之间的内

大多数HTML元素有属性

属性一般描述于开始标签

属性相当于给标签添加了描述信息

属性通常以键值对形式出现

"""

ui 自动化主要包含两部分,一是选择界面元素,二是操作界面元素

根据元素的特征选择界面元素:

id属性   通常是唯一的,也有不唯一的时候(随机id,重复id)

随机id和重复id,不可以使用id进行定位

否则,id是第一选择

name属性

Class

tag_name

根据元素的关系   css、xpath

操作界面元素

输入操作:点击、输入、拖拽

输出操作:

定位元素的步骤

1、找到元素对应的标签

2、观察元素是否有可利用的属性

3、若无法通过属性定位,则增加关系进行辅助定位

元素定位八种方法

1、id属性    -- 常用

2、name属性    -- 常用

3、class属性

4、tag_name标签名称

5、link_text链接文本

6、partial_link_text链接文本模糊定位

7、css表达式      -- 常用

8、xpath表达式    -- 常用

实例:

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://127.0.0.1:8088/login")

# 元素定位的第一种方法,根据id定位

a = driver.find_element_by_id("login-form")

# 元素定位的第二种方法,根据 name 属性进行定位

username_input_box = driver.find_element_by_name("username")

username_input_box.send_keys("libai")

# 元素定位的第三种方法,根据class属性进行定位

#   根据 classname进行定位的时候,有时候会遇到复合类,也就是class属性中间有空格

#   class 属性比较特殊,空格代表间隔符号,表示这个元素的class属性有多个值

#   任取其中一个值就可以定位(但是不保证唯一

driver.find_element_by_class_name("xdafsdf")

# 元素定位的第四种方法, 根据标签名称进行定位

driver.find_element_by_tag_name("p")

# 元素定位的第五种方法,根据链接文本进行定位

driver.find_element_by_link_text("超链接显示在外的文本")

# 元素定位的第六种方法,根据链接文本模糊定位

driver.find_element_by_partial_link_text("超链接显示在外的文本,一部分即可,但是不能错")

# 元素定位的第七种方法,根据 css表达式进行定位

driver.find_element_by_css_selector(

"body > section > div.left-side.sticky-left-side > div.left-side-inner > ul > li:nth-child(1) > a > span")

# 元素定位的第八种方法

driver.find_element_by_xpath("/html/body/section/div[1]/div[3]/ul/li[1]/a/i")

匹配元素列表

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://127.0.0.1:8088/login")

# driver.find_element_by_class_name("form-control").send_keys("123")

"""

find_element,会返回找到的第一个元素,如果根据表达式找不到元素,就报错

find_elements,会寻找页面上所有满足表达式的元素,将所有能找到的元素存在一个列表里,如果一个找不到,那就返回空列表

"""

# 寻找所有class属性为 form-control 的元素,存入列表,列表赋值给变量 eleSli

eleSli = driver.find_elements_by_class_name("form-control")

# 声明了一个列表

txtSli = ["111", "222"]

# 事先知道 eleSli 列表中有两个元素,所以设置循环为两次

for idx in range(2):

# eleSli[idx] 每次循环,根据下标取出 eleSli中的内容 -- 一个元素

# 对这个元素输入文本,文本内容来源于 txtSli,取相同的下标

eleSli[idx].send_keys(txtSli[idx])

  1. 元素等待、web自动化常用操作、Xpath高级语法

一、设置元素等待

大多数 Web 应用程序都是使用 Ajax 和 Javascript 开发的。当浏览器加载页面时,

我们想要与之交互的元素可能尚未被加载出来。此刻不仅难以识别元素,而且很容

易定位不到元素,抛出异常。使用 Waits,我们可以解决此问题

WebDriver 提供了两种类型的等待:显式等待和隐式等待

l

隐式等待: 设置一个超时时间,在这个时间内不断寻找这个元素,超时找不到就会抛出异

l

显示等待: 设置一个超时时间和一个元素查找条件,在这个时间内不断寻找这个元素,超

时找不到就会抛出异常

# 隐式等待

driver.implicitly_wait(10)

优点:

l

使用简单, 一次添加终生有效

l

一般在创建 driver 之后设置一个隐式等待(创建 driver 之后设置,目的是让

driver 的整个生命周期都有隐式等待的逻辑)

l

设置后的元素查找全都会进入隐式等待的逻辑

缺点:

l

无法对指定的元素进行等待

l

需要等页面全部加载完成, 相对浪费时间, 降低脚本执行速度显示等待

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

# 每隔 0.5 秒检查一次,最多等待 10

ele = WebDriverWait(driver, 10, 0.5).until(

EC.visibility_of_element_located(

(By.CSS_SELECTOR, "元素定位表达式")

)

)

ele.click()

优点:

不需要等待页面全部加载完成, 相对节省时间

可以指定需要等待的元素, 对一些加载缓慢的元素, 可以为其增加等待时间

缺点:

使用相对复杂, 代码量多

每次等待都需要再写一遍代码

我们可以将显示等待封装为一个函数, 以后需要的时候就调用函数, 可以省去很多代码量

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

def webElementWait(driver, timeout, lo_time, by_locate, locate):

"""

:param driver: 浏览器驱动对象

:param timeout: 最大等待时间

:param lo_time: 轮询时间

:param by_locate: 元素定位方法

:param locate: 元素定位表达式

:return:

"""

# 每隔 0.5 秒检查一次,最多等待 10

ele = WebDriverWait(driver, timeout, lo_time).until(

# 这里传入我们的期望条件

EC.visibility_of_element_located( (by_locate, locate)

)

)

return ele

可将显示等待与隐式等待结合使用

l

申明一个隐式等待, 全局通用

l

对一些加载特别缓慢的元素,设置显示等待, 适当为其增加等待时间

l

当显示等待与隐式等待一同出现的时候, 取时间更多的一个

二、webdriver 常用方法

我们定位元素之后要对这个元素进行操作, 或单击(按钮、链接等) 或输入(输入框) ,

下面就来认识 WebDriver 中最常用的几个方法:

clear(): 清除文本。

send_keys (value): 模拟按键输入(被操作元素需要是个文本输入框)。

click(): 单击元素。

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("https://www.baidu.com")

driver.find_element_by_id("kw").send_keys("selenium") # 输入内容

driver.find_element_by_id("kw").clear() # 清除内容

driver.find_element_by_id("kw").send_keys("python") # 输入内容

driver.find_element_by_id("su").click() # 点击内容

driver.quit()

其他方法

size: 返回元素的尺寸。text: 获取元素的文本。

get_attribute(name): 获得属性值。

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://www.baidu.com")

# 获得输入框的尺寸

size = driver.find_element_by_id('kw').size

print(size)

# 返回百度页面底部备案信息

text = driver.find_element_by_id("cp").text

print(text)

# 返回元素的属性值, 可以是 id name type 或其他任意属性

attribute = driver.find_element_by_id("kw").get_attribute('type')

print(attribute)

driver.quit()

我们也可以获取一些页面上的信息

l

title:用于获得当前页面的标题

l

current_url:用户获得当前页面的 URL

l

text:获取标签对之间的文本信息

注意:

l

标签元素如果不展示在页面上,获取结果为空

l

标签对中间没有值,获取结果为空

l

如 input 标签之类的标签,获取结果为空

l

get_attribute 方法,获取元素某个属性的值

l

ele.get_attribute('href')

l

上述代码获取 ele 这个元素的 href 属性的值

三、控制浏览器操作

1、控制浏览器大小

WebDriver 提供了 set_window_size()方法来设置浏览器的大小

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://www.baidu.com")

# 参数数字为像素点

print("设置浏览器宽 600、高 600 显示")

driver.set_window_size(600, 600)

driver.quit()

在 PC 端执行自动化测试脚本大多的情况下是希望浏览器在全屏幕模式下执行,那么可以使用

maximize_window()方法使打开的浏览器全屏显示

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("http://www.baidu.com")

# 设置全屏显示

driver.maximize_window()

# # 设置最小化浏览器,基本没啥用

# driver.minimize_window()

driver.quit()

控制浏览器前进、后退、刷新

from selenium import webdriver

driver = webdriver.Firefox()# 访问百度首页

driver.get("http://www.baidu.com")

# 访问新闻页面

driver.get("http://news.baidu.com")

# 返回(后退)到百度首页

driver.back()

# 前进到新闻页

driver.forward()

# 刷新界面

driver.refresh()

driver.quit()

四、xpath 高级语法

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常

规的电脑文件系统中看到的表达式非常相似。其标准语法如下:

Xpath=//tagname[@attribute='value']

l

// : 选择当前节点

l

Tagname: 节点标签名

l

@: 选择属性

l

Attribute: 节点属性名

l

Value: 属性值

xpath 这种定位方式, webdriver 会将整个页面的所有元素进行扫描以定位我们所需要的元

素, 这是个非常费时的操作, 如果脚本中大量使用 xpath 做元素定位的话, 脚本的执行速

度会明显变慢。XPath 有绝对定位和相对定位两种,绝对定位使用绝对路径,缺点是路径太长,只要一个节点

变动就无法定位。以单斜杠(/)开始,表示从根节点开始选择元素。

相对路径以双斜杠(//)开始,可以从 HTML 文档的任何位置开始。

xpath id 定位:

# 选择 id abc span 元素

//span[@id="abc"]

class 定位

# 选择 class abc span 元素

//span[@class="abc"]

其他属性值定位

# 在没有 id class 属性的前提下,可以使用其他属性定位

# 选择 name abc span 元素

//span[@name="abc"]

# 选择 type abc span 元素

//span[@name="type"]

xpath 可以使用 and 或者 or 连接多个属性

//input[@name='login'and @type='submit']

//input[@name='a'or @name='b']

xpath 还可以根据元素文本进行定位,以下示例中的 * 表示通配符,可匹配任意类型的标签

Xpath = //*[text()='text_value']

子元素定位,以 “/” 表示:

# 选择父元素为 div 的所有 a 元素

//div/a

后代元素定位,以 “//” 表示:

# 选择先辈元素为 div 的所有 a 元素

//div//afrom selenium import webdriver

"""

# XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电

脑文件系统中看到的表达式非常相似

缺点:

xpath 这种定位方式, webdriver 会将整个页面的所有元素进行扫描以定位我们所需要的元素,

这是个非常费时的操作, 如果脚本中大量使用 xpath 做元素定位的话, 脚本的执行速度可能

会稍慢

"""

# 创建浏览器驱动对象

driver = webdriver.Chrome("/Users/.../chromedriver")

# 访问网址

driver.get("/Users/...2/xpathStu.html")

# xpath 的绝对路径

driver.find_element_by_xpath("/html/body/div/ul/li[1]/ol/li[2]/ul/li[1]")

# xpath 的相对路径

driver.find_element_by_xpath("//li")

# xpath . 表示当前路径

driver.find_element_by_xpath("/html/body/div/ul/li[1]/ol/li[2]/ul/li[1]/.")

# xpath .. 表示上层路径

driver.find_element_by_xpath("/html/body/div/ul/li[1]/ol/li[2]/ul/li[1]/.")

# xpath 可以用 * 表示任意节点

driver.find_element_by_xpath("/html/body/div/ul/li[1]/ul/li[1]/ul/*")

# 如果需要用属性来筛选元素, 可以用 @

driver.find_element_by_xpath("//li[@id=\"abc\"]")

# 可以不为属性指定值

driver.find_element_by_xpath("//li[@id]")

# 也可以匹配固定值的任意属性

driver.find_element_by_xpath("//li[@*=\"abc\"]")

# 也可以用下标协助定位, 但要记住, 1 开始数

driver.find_element_by_xpath("/html/body/div/ul/li[1]/ol/li[2]/ul/li[1]")

# 最后第一个

driver.find_element_by_xpath("/html/body/div/ul/li[1]/ol/li[2]/ul/li[last()]")

# 倒数第二个driver.find_element_by_xpath("/html/body/div/ul/li[1]/ol/li[2]/ul/li[last()-1]")

# 根据元素文本值进行匹配

driver.find_element_by_xpath("//p[text=\"123\"]")

# 注意:当你使用 父元素.find_element_by_xpath 这种方式定位的时候,元素定位表达式必须以点

开头,如

ele = driver.find_elements_by_xpath("//div[@id='category-block']//ol/li")

b = ele.find_elements_by_xpath('.//li[@class=\'subcate-item\']//span')

# 如果不用点,会从整个文档开始找,即使你前边使用了父元素也没有效果,xpath

  1. CSS高级语法与高级元素操作

一、 css 高级语法

1、推荐的定位方式的优先级

l

优先级最高:ID

l

优先级其次:name

l

优先级再次:CSS selector

l

优先级再次:Xpath

针对 css selector 和 xpath 的优先级做一个简单的说明

在项目中我们可能用的最多的是 css 或者 xpath,那么针对这两种,我们优先选择 css,

原因在哪些?

原因 1:css 是配合 html 来工作,是一种匹配模式定位,而 xpath 是配合 xml 工作的,

通过遍历定位,所以两者在设计上,css 性能更优秀

原因 2:语言简洁,明了,相对 xpath

原因 3:前段开发主要是使用 css,不使用 xpath,所以在技术上面,我们可以获得帮助

的机会非常多

但 xpath 也有其优点:

l

Xpath 可以通过元素文本来定位,而 CSS Selector 不能

l

Xpath 可以通过子节点来定位父节点,CSS Selector 不能

2、定位元素的注意事项(划重点)

l

找到待定位元素的唯一属性

l

如果该元素没有唯一属性,则先找到能被唯一定位到的父元素/子元素/相邻元素,再使用

“>”," ","+"等进行辅助定位。

l

不要使用随机唯一属性定位

l

最重要的是多跟研发沟通,尽量把关键元素加上 ID 或者 name,并减少不合理的页面元

素,例如重复 ID 这样的事情最好不要发生。

CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明:

我们做 web 自动化测试,只需关注 选择器部分,帮我们找到元素

3、css 选择器

id 选择器

id 选择器可以选中具有特定 id HTML 元素

CSS id 选择器以 "#" 来定义。

以下的样式规则应用于元素属性 id="para1":

#para1 { text-align:center; color:red; }

class 选择器

class 选择器可以选中具有特定 class 属性的 HTML 元素

CSS 中,class 选择器以 "."号 来定义,若有空格,亦可以"."来代替

在以下的例子中,所有拥有 class 属性为 center HTML 元素均为居中

.center {text-align:center;}

标签选择器

标签选择器可以选中同类型的 html 标签元素

在以下的例子中,将所有的 p 标签设置为红色

p. {color:red;}

另外,你可以将标签选择器与属性选择器结合起来使用

以下,会将所有 class 属性为 re 的元素变成红色

p.re {color:red;}

分组选择器

分组选择器可以选中一组 HTML 元素

css 中,分组选择器以 “,” 来定义

以下实例,会将所有的 h1 标签、h2 标签、p 标签的内容变成红色

h1,h2,p { color:green; }

属性选择器

属性选择器选择具有特定属性的 HTML 元素

以下实例将所有包含 title 属性的元素变为蓝色

[title] { color:blue; }

你也可以为属性指定值

以下实例将所有 title 属性为 wa 的元素变为蓝色

[title=“wa]

{ color:blue; }

你也可以为元素指定标签

以下实例将所有 title 属性为 wa p 标签变为蓝色

p[title=“wa]

{ color:blue; }

组合选择符

CSS3 中包含了四种组合方式:

l

后代选择器(以空格分隔)

l

子元素选择器(以大于号分隔)

l

相邻兄弟选择器(以加号分隔)

l

后续兄弟选择器(以小波浪号分隔)

后代选择器

后代选择器用于选取某元素的后代元素,无论层级有多深

以下实例将 <div> 元素中所有的 p 元素背景修改为黄色:

div p { background-color:yellow; }

子元素选择器

与后代选择器相比,子元素选择器只能选择其父元素的直接子元素

以下实例选择了<div>元素中所有直接子元素 <p>

div>p { background-color:yellow; }

相邻兄弟选择器

相邻兄弟选择器可选择紧接在另一元素后的元素,且二者有相同父元素

以下实例选取了所有位于 <div> 元素后的第一个 <p> 元素:

div+p { background-color:yellow; }

后续兄弟选择器

后续兄弟选择器选取所有指定元素之后的相邻兄弟元素。

以下实例选取了所有 <div> 元素之后的所有相邻兄弟元素 <p> :

div~p { background-color:yellow; }

伪类

nth-child(n) 匹配属于其父元素的第 N 个子元素(不必指定标签类型)

nth-last-child(n),如字面意思:倒数第几个标签

first-child,第一个标签

last-child,最后一个标签

二、 高级元素操作

1、窗口截图

from selenium import webdriver

# 创建浏览器驱动对象

driver = webdriver.Chrome("D:\...\chromedriver")

# 访问网址

driver.get("https://www.baidu.com/")

# 截屏,截取整个页面

driver.get_screenshot_as_file("./all.png")

# 截屏,截取单个元素

ele = driver.find_element_by_id("form")

ele.screenshot("./ele.png")

driver.quit()

出现 bug 之后,可以截图

from selenium import webdriver

import time

# 创建浏览器驱动对象

driver = webdriver.Chrome("/Users/。。。/chromedriver")

driver.implicitly_wait(3)

# 访问网址

driver.get("http://192.168.0.108:8088/login")

# 输入用户名

driver.find_element_by_name("username").send_keys("libai")

# 输入密码

driver.find_element_by_name("password").send_keys("opmsopms123")

# 点击登录按钮

driver.find_element_by_tag_name("button").click()

# 点击侧边菜单栏-员工相册

driver.find_element_by_css_selector(

"body > section > div.left-side.sticky-left-side > div.left-side-inner > ul > li:nth-child(6) > a").click()

# 点击油菜花这张照片

driver.find_element_by_link_text("油菜花").click()# 向下滑动

driver.execute_script("window.scrollBy(0, 900);")

# 使用时间戳作为评论的内容

commentStr = "%s" % time.time()

# 输入评论

driver.find_element_by_name("comment").send_keys("commentStr")

# 提交评论

driver.find_element_by_css_selector("#album-comment-form > div > div > button").click()

# 获取最后一条评论

lastComment = driver.find_element_by_xpath("//ul[@class=\"activity-list\"]/li[last()]//span").text

# 不一致说明有问题,截图

if commentStr != lastComment:

# 截屏,截取单个元素

ele = driver.find_element_by_xpath("//ul[@class=\"activity-list\"]")

ele.screenshot("./%s.png" % lastComment)

2、警告框处理

在 WebDriver 中处理 JavaScript 所生成的 alert、confirm 以及 prompt 十分简单,具体做

法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后使用

text/accept/dismiss/ send_keys 等方法进行操作

l

text:返回 alert/confirm/prompt 中的文字信息

l

accept():接受现有警告框

l

dismiss():取消现有警告框

l

send_keys(“haha”):发送文本至警告框

from selenium import webdriver

# 创建浏览器驱动对象

driver = webdriver.Chrome("/Users/。。。/chromedriver")

# 访问网址

driver.get("/Users/。。。/test1.html")

"""# 触发确认框

driver.find_element_by_id("bu1").click()

# 获取对话框

al = driver.switch_to.alert

al.accept()

"""

"""

# 触发确认框

driver.find_element_by_id("bu2").click()

# 获取确认框

al = driver.switch_to.alert

# 取消确认框

al.dismiss()

"""

# 触发提示框

driver.find_element_by_id("bu3").click()

# 获取提示框

al = driver.switch_to.alert

print(al.text)

al.send_keys("今天温度很高")

al.accept()

3、鼠标事件

用 selenium 做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击、双击、 点击鼠标右键、拖拽等等。而 selenium 给我们提供了一个类来处理这类事件—— ActionChains

ActionChains 类提供了鼠标操作的常用方法:

l

perform(): 执行操作

l

context_click(): 右击;

l

double_click(): 双击;

l

drag_and_drop(): 拖动;

l

move_to_element(): 鼠标悬停。

from selenium import webdriver# 引入 ActionChains

from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Chrome()

driver.get("https://www.baidu.cn")

# 定位到要悬停的元素

above = driver.find_element_by_link_text("设置")

# 对定位到的元素执行鼠标悬停操作

ActionChains(driver).move_to_element(above).perform()

driver.quit()

4、键盘事件

Keys()类提供了键盘上几乎所有按键的方法。 前面了解到, send_keys()方法可以用来模拟 键盘输入, 除此 之外, 我们还可以用它来输入键盘上的按键, 甚至是组合键, 如 Ctrl+A、 Ctrl+C 等

from selenium import webdriver

# 引入 Keys 模块

from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()

driver.get("http://www.baidu.com")

# 输入框输入内容

driver.find_element_by_id("kw").send_keys("seleniumm")

# 删除多输入的一个 m

driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)

# 输入空格键+“教程

driver.find_element_by_id("kw").send_keys(Keys.SPACE)

driver.find_element_by_id("kw").send_keys("教程")

# ctrl+a 全选输入框内容

driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')

# ctrl+x 剪切输入框内容driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')

# ctrl+v 粘贴内容到输入框

driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v')

# 通过回车键来代替单击操作

driver.find_element_by_id("su").send_keys(Keys.ENTER)

driver.quit()

以下为常用的键盘操作:

l

send_keys(Keys.BACK_SPACE) 删除键(BackSpace)

l

send_keys(Keys.SPACE) 空格键(Space)

l

send_keys(Keys.TAB) 制表键(Tab)

l

send_keys(Keys.ESCAPE) 回退键(Esc)

l

send_keys(Keys.ENTER) 回车键(Enter)

l

send_keys(Keys.CONTROL,'a') 全选(Ctrl+A)

l

send_keys(Keys.CONTROL,'c') 复制(Ctrl+C)

l

send_keys(Keys.CONTROL,'x') 剪切(Ctrl+X)

l

send_keys(Keys.CONTROL,'v') 粘贴(Ctrl+V)

l

send_keys(Keys.F1) 键盘 F1

l

……

l

send_keys(Keys.F12) 键盘 F12

5、下拉框选择

WebDriver 提供了 Select 类来处理下拉框。注意,只有当下拉框是 select 标签的时候使用

from selenium import webdriver

from selenium.webdriver.support.select import Select

import time

# 实例化一个浏览器对象

driver = webdriver.Chrome("D:\\tool\...\chromedriver")# 访问网址

driver.get("D:\\test\...\selectStu.html")

# 定位到下拉框元素

ele = driver.find_element_by_id("bc288089-c52d-497b-aa4d-71f81b24faa3")

# # 根据 value 属性选择

# Select(ele).select_by_value("3")

# 根据下拉框文本选择

Select(ele).select_by_visible_text("3333333")

time.sleep(3)

  1. 浏览器高级操作

一、高级浏览器操作

1、文件上传

对于通过 input 标签实现的上传功能,可以将其看作是一个输入框,即通过 send_keys()指定 本地文件路径的方式实现文件上传

对于非 input 标签实现的上传功能,我们可以通过模拟键盘敲击的方式实现,代码如下

# 这个是 windows 版本的

from selenium import webdriver

import win32com.client

import time

driver = webdriver.Chrome()

driver.implicitly_wait(5)

driver.get("https://tinypng.com/")

# 触发上传文件的操作

driver.find_element_by_css_selector("#top .icon").click()

sh = win32com.client.Dispatch("WScript.shell")

time.sleep(3)

sh.Sendkeys("D:\\test\script\study\seleniumStu\day6\qqjt.png\n") # 无目标的,单纯的敲击键盘

driver.quit()

# 这个是 mac 版本的

from selenium.webdriver.common.action_chains import ActionChains

from selenium import webdriver

from pykeyboard import PyKeyboard

from pymouse import PyMouse

import pyperclip

import time

# 安装命令pip3 install PyUserInput# 创建浏览器驱动对象

driver = webdriver.Chrome()

driver.implicitly_wait(3)

# 访问网址

driver.get("http://192.168.0.108:8088/login")

# 输入用户名

driver.find_element_by_name("username").send_keys("libai")

# 输入密码

driver.find_element_by_name("password").send_keys("opmsopms123")

# 点击登录按钮

driver.find_element_by_tag_name("button").click()

# 点击员工相册

driver.find_element_by_css_selector("ul.js-left-nav > li:nth-child(6)").click()

# 点击上传照片

driver.find_element_by_css_selector(".pull-right > a:nth-child(3)").click()

# 点击请选择, 触发上传文件的操作

ActionChains(driver).click(driver.find_element_by_id("albumUpload")).perform()

time.sleep(3)

def upload_file(file):

# 创建鼠标对象

k = PyKeyboard()

# 创建键盘对象

m = PyMouse()

filepath = "/"

# 模拟快捷键 Command+Shift+G

k.press_keys(["Command", "Shift", "G"])

# 输入文件路径

x_dim, y_dim = m.screen_size()

m.click(x_dim // 2, y_dim // 2, 1)

# 复制文件路径开头的斜杠/

pyperclip.copy(filepath)

# 粘贴斜杠/

k.press_keys(["Command", "V"])

time.sleep(2)

# 输入文件全路径进去

k.type_string(file)

k.press_key("Return")

time.sleep(2)

k.press_key("Return")

time.sleep(2)upload_file("/Users/。。。/ele.png")

2、cookie 操作(课后阅读,不作要求)

WebDriver 提供了操作 Cookie 的相关方法,可以读取、添加和删除 cookie 信息

WebDriver 操作 cookie 的方法:

l

get_cookies(): 获得所有 cookie 信息

l

get_cookie(name): 返回字典的 key 为“name”的 cookie 信息

l

add_cookie(cookie_dict) : 添加 cookie。“cookie_dict”指字典对象,必须有 name

和 value 值

l

delete_cookie(name,optionsString):删除 cookie 信息。“name”是要删除的 cookie

的名称,“optionsString”是该 cookie 的选项,目前支持的选项包括“路径”,“域”

l

delete_all_cookies(): 删除所有 cookie 信息

from selenium import webdriver

driver = webdriver.Firefox()

driver.get("http://www.youdao.com")

# 获得 cookie 信息

cookie = driver.get_cookies()

# 将获得 cookie 的信息打印

print(cookie)

driver.quit()

可以尝试一下,获取 opms 登陆以后的 cookies 信息,注意是登陆以后的

from selenium import webdriver

# 这是之前获取到的 cookies, 记得把每一个字典的 expiry 注释# 用你刚才获取到的 opms 登陆后的 cookie 替换

cookies = [{'domain': '.baidu.com',

'httpOnly': False,

'name': 'H_PS_PSSID',

'path': '/',

'secure': False,

'value': '1431_21125_30839_31186_30909_31228_30823_31086_31164_22158'},

{'domain': '.baidu.com',

# 'expiry': 1845350230.981488, 这个时间由服务端规定,不能插入

'httpOnly': True,

'name': 'BDUSS',

'path': '/',

'secure': False,

'value': 'jlhWTBAAAAAAAAF67il5eu4peR'}] # 是个列表,列表里是一个个的字典

driver = webdriver.Chrome()

driver.implicitly_wait(10)

driver.get("opms 的网址")

# 清除所有 cookie

driver.delete_all_cookies()

for cookie in cookies:

# 添加 cookie

driver.add_cookie(cookie)

driver.refresh()

3、iframe 切换

iframe,又叫浮动帧标记,是内嵌的网页元素,可以将一个 html 文件嵌入到另一个 html 文 件中显示

对 iframe 进行操作,需要用到以下三种方法:

l

switch_to_iframe() 切换到 iframe 上(未来会被删除,不建议使用)

l

switch_to.frame() 切换到 iframe 上

l

switch_to.default_content() 切换回原主页面通过如下方式进行切换操作

#定位到 iframe

iframe=driver.find_element_by_id("x-URS-iframe")

#切换到 iframe

driver.switch_to_frame(iframe)

from selenium import webdriver

import time

driver = webdriver.Chrome("D:\。。。\chromedriver")

# 隐式等待

driver.implicitly_wait(5)

driver.get("D:\\test\。。。\test.html")

"""

iframe 进行操作,需要用到以下三种方法:

switch_to_iframe() 切换到 iframe

switch_to.frame() 切换到 iframe

switch_to.default_content() 切换回原主页面

"""

iframe = driver.find_element_by_id("f91fb5bc-bd95-45bf-bd77-977a2afbd25f")

driver.switch_to.frame(iframe)

driver.find_element_by_id("e4890ded-16e1-4445-bf8e-7f655793f332").send_keys("haha")

time.sleep(5)

driver.quit()

4、多标签页切换

在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要切换到新打开的窗口上进 行操作。

WebDriver 提供了以下方法

l

current_window_handle:获得当前标签页句柄

l

window_handles:返回所有便签页的句柄

l

switch_to.window(标签页句柄):切换到对应的标签页

l

关闭标签页使用 close 方法

from selenium import webdriver

# 创建浏览器驱动对象driver = webdriver.Chrome()

# 访问网址

driver.get("http://www.baidu.com")

# 找到搜索按钮

input_element = driver.find_element_by_id("kw")

# 输入搜索内容

input_element.send_keys("松勤\n")

# 点击松勤教育官网

driver.find_element_by_css_selector("#\34 > h3 > a > em").click()

# 获得当前所有打开的窗口的句柄

all_handles = driver.window_handles

for handle in all_handles:

driver.switch_to.window(handle)

print(driver.title)

# 退出浏览器

driver.quit()

5、页面滚动

在自动化操作中,如果 web 页面过长,而我们需要的元素并不在当前可视页面中,那么 selenium 就无法对其进行操作;此时,我们就需要像平时操作浏览器一样来滚动页面,使我 们需要操作的对象可见!

window.scrollBy()

l

window.scrollBy(0,500) 向下滚动 500 个像素

l

window.scrollBy(0,-500) 向上滚动 500 个像素

l

window.scrollBy(500,0) 向右滚动 500 个像素

l

window.scrollBy(-500,0) 向左滚动 500 个像素

Selenium 中实现滚动页面

l driver.execute_script("window.scrollBy(0,500)")

l driver.execute_script("arguments[0].scrollIntoView();", ele) 滚动至元素 ele 可见 有时候,我们需要滚动的不是整个页面,而是页面中的某个元素,这个元素有滚动条。

HTML 案例:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

<style type="text/css">

div.scroll {

background-color: #00FFFF;

width: 100px;

height: 100px;

overflow: auto;

}

</style>

</head>

<body>

<p>下面这个元素自带滚动条</p>

<div class="scroll">

<ul>

<li>111abcdefghijk</li>

<li>222abcdefghijk</li>

<li>333abcdefghijk</li>

<li>444abcdefghijk</li>

<li>555abcdefghijk</li>

<li>666abcdefghijk</li>

<li>777abcdefghijk</li>

</ul>

</div>

</body>

</html>

处理方式也很简单,我们找到这个带滚动条的元素的 css 表达式就可以了js="document.querySelector("这里填 css 表达式").scrollTop=100"

# 修改这个元素的 scrollTop 就可以

dr.execute_script(js)

# 控制横向滚动

js="document.querySelector("这里填 css 表达式

  1. po模式

po 模式

1、简单的 po 模式

Page Object Model:

PO 设计模式是一种思想,应用在 selenium 自动化上,其主要体现在对界面交互细节的封装,也就是在实际测试中只关注业务流程就 OK 了 ,传统的设计中,在新增测试用例之后,代码会有以下几个问题:

l

易读性差:一连串的 find element 会使代码显得杂乱无章

l

可复用性差:无公共方法,很难复用

l

可维护性差:一旦元素变化,需要维护修改大量测试用例

因此考虑到优化:

PO 模式是一种自动化测试设计模式,将页面定位和业务操作分开,也就是把元素的定位 和测试脚本分开,从而提供可维护性。

首先抽象封装一个 BasePage 类,这个基类拥有一些 Webdriver 实例的属性,然后每一 个 Page 继承 BasePage,可以通过 driver 管理每一个 Page 中的元素,而且在 Page 中将这些操作封装为一个一个的方法。TestCase 依赖 page 类,进行组织测试步骤的工作。

这样做的好处,就是有元素变化,只需要维护每一个 Page 就行了,测试步骤变化,只需 要维护 TestCase 即可

下面举一个简单的例子来看一下 PO 模式:

from selenium import webdriver

class LoginPage:

def __init__(self, path=None):

# 创建 driver 对象

self.driver = webdriver.Chrome()

# 最大化窗口

self.driver.maximize_window()

# 访问网址

self.driver.get(path)

# 用户名输入框

def username_input_box(self):

return self.driver.find_element_by_id("username")

# 密码输入框

def password_input_box(self):

return self.driver.find_element_by_id("password") # 登录按钮

def login_button_box(self):

return self.driver.find_element_by_id("btnLogin")

# 抽离出页面动作类, 继承对应的页面类

class LoginPageAction(LoginPage):

def login_action(self):

"""

登录宝利商城

:return:

"""

self.username_input_box().send_keys("松勤老师")

self.password_input_box().send_keys("123456")

self.login_button_box().click()

if __name__ == '__main__':

LoginPageActionObj = LoginPageAction("http://120.55.190.222:38090/#/login")

LoginPageActionObj.login_action()

2、初级版本

我们观察到,有些信息是可以写在配置文件里的,所以提取出文件 mySettings.py

# 项目网址

url = "http://120.55.190.222:38090/#/login"

# 账号密码

username = "松勤老师"

password = "123456"

另外浏览器驱动对象也可以提取出来,所以提取出文件 myDriver.py

# 路径记得换成自己的

from foo.songQing.seleniumV2.day4.初级版本.mySettings import url

from selenium import webdriver

class Driver:

# 初始化为 None

_driver = None @classmethod

def get_driver(cls, browser_name="chrome"):

"""

获取浏览器驱动对象

:param browser_name: 浏览器名称

:return:

"""

# 如果不为空就不需要新建了

if cls._driver is None:

if browser_name == 'chrome':

cls._driver = webdriver.Chrome()

elif browser_name == 'firefox':

cls._driver = webdriver.Firefox()

elif browser_name == 'safari':

cls._driver = webdriver.Safari()

elif browser_name == 'opera':

cls._driver = webdriver.Opera()

elif browser_name == 'edge':

cls._driver = webdriver.Edge()

elif browser_name == 'ie':

cls._driver = webdriver.Ie()

# 隐式等待五秒

cls._driver.implicitly_wait(5)

# 最大化窗口

cls._driver.maximize_window()

# 访问默认的网页

cls._driver.get(url)

# 登录

cls.__login()

return cls._driver

@classmethod

def __login(cls):

"""

私有方法, 只能在类里边使用

类外部无法使用, 子类不能继承

解决登录问题

:return:

"""

cls._driver.find_element_by_id("username").send_keys("松勤老师")

cls._driver.find_element_by_id("password").send_keys("123456")

cls._driver.find_element_by_id("btnLogin").click()if __name__ == '__main__':

# 无论调用多少次, 都只有一个浏览器

Driver.get_driver()

Driver.get_driver()

Driver.get_driver()

Driver.get_driver()

我们知道,ui 自动化的价值不在于发现多少 bug,而在于帮助手工测试节省了多少时间。所以,ui 自动化的

case 只测试正向场景,对于登录而言,只要能正常登录,即认为此条 case 是通过的。所以将登录的逻辑写

driver 类中。这样做的另一个好处是,当页面的数量增多,我们无需额外花费精力去保证登录一定在其他

case 之前执行。

这个时候,页面类就只剩下了与网页元素、元素操作相关的代码,我们以商城后台的登录页面为例

# 注意, 这个导入路径要换成自己的

from foo.songQing.seleniumV2.day5.初级版本.mySettings import username, password

from foo.songQing.seleniumV2.day5.初级版本.myDriver import Driver

class LoginPage:

def __init__(self):

# 创建 driver 对象

self.driver = Driver.get_driver()

# 用户名输入框

def username_input_box(self):

return self.driver.find_element_by_id("username")

# 密码输入框

def password_input_box(self):

return self.driver.find_element_by_id("password")

# 登录按钮

def login_button_box(self):

return self.driver.find_element_by_id("btnLogin")

# 抽离出页面动作类, 继承对应的页面类

class LoginPageAction(LoginPage):

def login_action(self):

"""

登录宝利商城:return:

"""

self.username_input_box().send_keys(username)

self.password_input_box().send_keys(password)

self.login_button_box().click()

if __name__ == '__main__':

LoginPageActionObj = LoginPageAction()

LoginPageActionObj.login_action()

3、抽离出 BasePage 的版本

等待的时候,需要一个超时时间和一个轮询时间----将其加入配置文件

# 项目网址

url = "http://120.55.190.222:38090/#/login"

# 账号密码

username = "松勤老师"

password = "123456"

# 智能等待超时时间

time_out = 10

# 智能等待轮询时间

poll_frequency = 0.5

driver 类保持不变

from foo.songQing.seleniumV2.day5.抽离出 BasePage 的版本.mySetting import url

from selenium import webdriver

class Driver:

# 初始化为 None

_driver = None

@classmethod

def get_driver(cls, browser_name="chrome"):

""" 获取浏览器驱动对象

:param browser_name: 浏览器名称

:return:

"""

# 如果不为空就不需要新建了

if cls._driver is None:

if browser_name == 'chrome':

cls._driver = webdriver.Chrome()

elif browser_name == 'firefox':

cls._driver = webdriver.Firefox()

elif browser_name == 'safari':

cls._driver = webdriver.Safari()

elif browser_name == 'opera':

cls._driver = webdriver.Opera()

elif browser_name == 'edge':

cls._driver = webdriver.Edge()

elif browser_name == 'ie':

cls._driver = webdriver.Ie()

# 最大化窗口

cls._driver.maximize_window()

# 访问默认的网页

cls._driver.get(url)

return cls._driver

if __name__ == '__main__':

# 无论调用多少次, 都只有一个浏览器

Driver.get_driver()

Driver.get_driver()

Driver.get_driver()

Driver.get_driver()

我们发现每个页面类都有一些通用的内容,所以抽离出来,形成 basePage

from foo.songQing.seleniumV2.day5.抽离出 basePage 的版本.mySetting import time_out, poll_frequency

from foo.songQing.seleniumV2.day5.抽离出 basePage 的版本.myDriver import Driver

from selenium.webdriver.support import expected_conditions as ec

from selenium.webdriver.support.wait import WebDriverWait

class BasePage:

def __init__(self): # 获取浏览器对象

self.driver = Driver.get_driver()

def get_element(self, locator):

"""

根据表达式匹配单个元素

:param locator: 元素定位表达式, 以元组形式传入, 示例: (By.ID, "abc")

:return:

"""

# 判断元素是否存在

WebDriverWait(

# 传入浏览器对象

driver=self.driver,

# 传入超时时间

timeout=time_out,

# 设置轮询时间

poll_frequency=poll_frequency).until(

# 检测定位的元素是否可见

ec.visibility_of_element_located(locator))

# 返回元素对象, 元组传参

return self.driver.find_element(*locator)

def get_elements(self, locator):

"""

根据表达式匹配元素列表

:param locator:

:return:

"""

# 判断元素是否存在

WebDriverWait(

# 传入浏览器对象

driver=self.driver,

# 传入超时时间

timeout=time_out,

# 设置轮询时间

poll_frequency=poll_frequency).until(

# 检测定位的元素是否可见 // 元素被定位并可见

ec.visibility_of_all_elements_located(locator))

# 返回元素列表, 元组传参

return self.driver.find_elements(*locator)

loginpage 也进行一些修改

from foo.songQing.seleniumV2.day5.抽离出 basePage 的版本.mySetting import username, password

from foo.songQing.seleniumV2.day5.抽离出 basePage 的版本.basePage import BasePagefrom selenium.webdriver.common.by import By

class LoginPage(BasePage):

def __init__(self):

"""

进一步抽离元素定位方法

这里只封装寻找元素的方法, 不会真的去找元素

"""

# 执行父类的构造方法

super().__init__()

# 用户名输入框

self.username_input_locator = (By.ID, "username")

# 密码输入框

self.password_input_locator = (By.ID, "password")

# 登录按钮

self.login_button_locator = (By.ID, "btnLogin")

# 用户名输入框

def username_input_box(self):

return self.driver.find_element(*self.username_input_locator)

# 密码输入框

def password_input_box(self):

return self.driver.find_element(*self.password_input_locator)

# 登录按钮

def login_button_box(self):

return self.driver.find_element(*self.login_button_locator)

# 抽离出页面动作类, 继承对应的页面类

class LoginPageAction(LoginPage):

def login(self):

"""

访问商家管理后台, 登录用户

:return:

"""

# 输入用户名

self.username_input_box().send_keys(username)

# 输入密码

self.password_input_box().send_keys(password) # 点击登录按钮

self.login_button_box().click()

if __name__ == '__main__':

LoginPageActionObj = LoginPageAction()

LoginPageActionObj.login()

  1. Po的高阶用法

mySettings.py

# 项目网址

url = "http://120.55.190.222:38090/#/login"

# 账号密码

username = "松勤老师"

password = "123456"

# 智能等待超时时间

time_out = 10

# 智能等待轮询时间

poll_frequency = 0.5

myDriver.py

from foo.songQing.seleniumV2.day5.utils.mySettings import url

from selenium import webdriver

class Driver:

# 初始化为 None

_driver = None

@classmethod

def get_driver(cls, browser_name="chrome"):

"""

获取浏览器驱动对象

:param browser_name: 浏览器名称

:return:

"""

# 如果不为空就不需要新建了

if cls._driver is None:

if browser_name == 'chrome':

cls._driver = webdriver.Chrome()

elif browser_name == 'firefox':

cls._driver = webdriver.Firefox()

elif browser_name == 'safari': cls._driver = webdriver.Safari()

elif browser_name == 'opera':

cls._driver = webdriver.Opera()

elif browser_name == 'edge':

cls._driver = webdriver.Edge()

elif browser_name == 'ie':

cls._driver = webdriver.Ie()

cls._driver.implicitly_wait(5)

cls._driver.maximize_window()

cls._driver.get(url)

cls.__login()

return cls._driver

@classmethod

def __login(cls):

"""

私有方法, 只能在类里边使用

类外部无法使用, 子类不能继承

解决登录问题

:return:

"""

cls._driver.find_element_by_id("username").send_keys("松勤老师")

cls._driver.find_element_by_id("password").send_keys("123456")

cls._driver.find_element_by_id("btnLogin").click()

if __name__ == '__main__':

# 无论调用多少次, 都只有一个浏览器

Driver.get_driver()

Driver.get_driver()

Driver.get_driver()

Driver.get_driver()

basePage.py

from foo.songQing.seleniumV2.day5.utils.mySettings import time_out, poll_frequency

from foo.songQing.seleniumV2.day5.utils.myDriver import Driver

from selenium.webdriver.support import expected_conditions as ec

from selenium.webdriver.support.wait import WebDriverWait

import time

class BasePage: def __init__(self):

# 获取浏览器对象

self.driver = Driver.get_driver()

def get_element(self, locator):

"""

根据表达式匹配单个元素

:param locator: 元素定位表达式, 以元组形式传入, 示例: (By.ID, "abc")

:return:

"""

# 判断元素是否存在

WebDriverWait(

# 传入浏览器对象

driver=self.driver,

# 传入超时时间

timeout=time_out,

# 设置轮询时间

poll_frequency=poll_frequency).until(

# 检测定位的元素是否可见

ec.visibility_of_element_located(locator))

# 返回元素对象, 元组传参

return self.driver.find_element(*locator)

def to_page(self, url):

time.sleep(1)

self.driver.get(url)

if __name__ == '__main__':

x = BasePage()

addProductPage.py

from foo.songQing.seleniumV2.day5.pages.basePage import BasePage

import time

class AddProductPage(BasePage):

def __init__(self):

super().__init__()

self.url = "http://120.55.190.222:38090/#/pms/addProduct" def product_classification_select_box(self):

"""商品分类下拉框, 外框"""

return self.driver.find_element_by_css_selector("form > div:nth-child(1) .el-cascader__label")

def product_classification_select_box_idx1(self, idx1):

"""商品分类下拉框, 一级分类"""

return self.driver.find_element_by_css_selector("ul.el-cascader-menu > li:nth-child(%s)" % idx1)

def product_classification_select_box_idx2(self, idx2):

"""商品分类下拉框, 二级分类"""

return self.driver.find_element_by_css_selector("ul + ul.el-cascader-menu > li:nth-child(%s)" %

idx2)

def product_name_input_box(self):

"""商品名称输入框"""

return self.driver.find_element_by_css_selector("label[for=\"name\"] + div input")

def product_subtitle_input_box(self):

"""副标题输入框"""

return self.driver.find_element_by_css_selector("label[for=\"subTitle\"] + div input")

def product_brand_select_box(self):

"""商品品牌下拉框外框"""

return self.driver.find_element_by_css_selector("label[for=\"brandId\"] + div input")

def product_brand_select_box_option(self, idx):

"""商品品牌下拉框, 一级分类"""

return self.driver.find_element_by_css_selector("body > div:nth-child(8) ul > li:nth-child(%s)" %

idx)

def next_step_commodity_promotion_button_box(self):

"""下一步, 填写商品促销按钮"""

return self.driver.find_element_by_xpath("//*[text()=\"下一步,填写商品促销\"]")

def is_herald_box(self):

"""预告商品开关"""

return self.driver.find_element_by_xpath("//*[text()=\"预告商品:\"]/..//span")

def next_step_product_attribute_button_box(self):

"""下一步, 填写商品属性按钮"""

return self.driver.find_element_by_xpath("//*[text()=\"下一步,填写商品属性\"]")

def next_step_choose_product_related_button_box(self):

"""下一步, 选择商品关联按钮""" return self.driver.find_element_by_xpath("//*[text()=\"下一步,选择商品关联\"]")

def submit_product_button_box(self):

"""完成, 提交商品按钮"""

return self.driver.find_element_by_xpath("//*[text()=\"完成,提交商品\"]")

def confirm_submission_box(self):

return self.driver.find_element_by_css_selector(

"[class=\"el-button el-button--default el-button--small el-button--primary \"]")

class AddProductPageAction(AddProductPage):

def add_product_action(self, idx1, idx2, product_name, subtitle, brand_select_idx):

self.to_page(self.url)

# 点击商品分类下拉外框

self.product_classification_select_box().click()

# 选择一级分类

self.product_classification_select_box_idx1(idx1).click()

# 选择二级分类

self.product_classification_select_box_idx2(idx2).click()

# 输入商品名称

self.product_name_input_box().send_keys(product_name)

# 输入副标题

self.product_subtitle_input_box().send_keys(subtitle)

# 点击商品品牌下拉框外框

self.product_brand_select_box().click()

# 选择商品品牌一级分类

self.product_brand_select_box_option(brand_select_idx).click()

# 点击[下一步,填写商品促销]按钮

self.next_step_commodity_promotion_button_box().click()

# 点击是否预告商品开关

self.is_herald_box().click()

# 点击[下一步, 填写商品属性]按钮

self.next_step_product_attribute_button_box().click()

# 点击下一步, 选择商品关联按钮

self.next_step_choose_product_related_button_box().click()

time.sleep(0.3)

# 点击完成,提交商品按钮

self.submit_product_button_box().click()

# 确认提交

self.confirm_submission_box().click()

AddProductPageActionObj = AddProductPageAction()if __name__ == '__main__':

AddProductPageActionObj.add_product_action(1, 1, "针不戳羊毛衫", "羊毛姗姗", 1)

case.py

import time

from study.seleniumStu.day5.抽离出 basePage 版本.addProductPage import AddProductPageActionObj as

APP

from study.seleniumStu.day5.抽离出 basePage 版本.productLIstPage import ProductLIstPageActionObj as

PLP

def addProductCase():

product_name = "%s" % time.time()

# 添加一个商品

APP.add_product_action("1", "1", product_name, product_name, 1)

# 进入商品列表页面

PLP.to_page(3, PLP.url)

# 获取商品列表,第一个商品的商品名称

first_product_name = PLP.first_tr_product_name_box().text

if product_name == first_product_name:

print("测试通过")

else:

print("测试失败")

addProductCase()

6.自动化实战

7.selenium知识点梳理

8.常见面试题

selenium 中如何判断元素是否存在

元素列表

如何保证操作元素的成功率

1、网速不好,适当等待

2、被点击的元素要占有一定的空间

3、被点击元素不能被其他元素遮挡

4、被操作的元素不能在视野之外

5、测试尽量使用专用环境,避免干扰

如何提高我们脚本的执行效率

1、钞能力,使用更高配置的电脑和更快的网络环境

2、优化代码,可以直接get访问网址的,不要一步步点击,能用显示等待的,不要强制等待

3、尽量用chrome,Safari

4、尽量用效率更高的css定位,不用xpath

ui自动化的执行策略

每日执行一次,比如晚上11点,测试报告邮件团队

每次冒烟测试或回归测试的时候执行

动态执行,开发提交代码就执行一次(成本比较高

ui自动化不做数据库验证,这是接口测试要做的事情

Selenium学习笔记相关推荐

  1. selenium学习笔记之元素定位

    selenium学习笔记之元素定位 Selenium是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样. 首先需要创建浏览器驱动: from sele ...

  2. 【selenium学习笔记】selenium自动化测试环境安装

    工作中需要用到selenium,因此将学习和工作过程中的笔记整理 下. [Install selenium] 联网情况下,直接利用pip安装按照如下命令安装selenium.[如何安装pip?]--- ...

  3. selenium学习笔记(4)——自动点击美团上面的美食中的代金券

    想要系统学习python selenium自动化测试,请关注我的专栏: https://blog.csdn.net/column/details/29112.html 自动点击美团上面的美食中的代金券 ...

  4. selenium学习笔记(一)

    备注:摘自<selenium2 python  自动化测试实战>- 虫师 (一)什么样的项目适合自动化测试 1.软件需求变动不频繁 测试脚本的稳定性决定了自动化测试的维护成本.如果软件需求 ...

  5. Python+Selenium学习笔记8 - 多表单多窗口切换

    1.多表单切换 下图为待测页面:内嵌百度首页 切换到百度首页进行操作 1 #coding = utf-8 2 3 from selenium importwebdriver4 importos5 im ...

  6. 基于Java的Selenium学习笔记——Assert

    用assert来判断一个表达式,返回true或者false,若表达式返回false,则会导致AssertionError. 注意Eclipse中assert默认是关闭的,需手动开启,如下图: 第一个简 ...

  7. Python+Selenium学习笔记10 - send_keys上传文件

    在火狐浏览器上传文件 上传前,同一个HTML文件在火狐和Edge浏览器显示有些不同 这是Firefox浏览器的显示 这是Edge浏览器 上传后 1 # coding = utf-8 2 3 from ...

  8. Python+Selenium学习笔记5 - python官网的tutorial - 交互模式下的操作

    这篇笔记主要是从Python官网的Tutorial上截取下来,再加上个人理解 1. 在交互模式下,下划线'_'还可以表示上一步的计算结果 2.引号转义问题. 从下图总结的规律是,字符串里的引号如果和引 ...

  9. 【selenium学习笔记一】python + selenium定位页面元素的办法。

    1.什么是Selenium,为什么web测试,大家都用它? Selenium设计初衷就是为web项目的验收测试再开发.内核使用的是javaScript语言编写,几乎支持所以能运行javaScript的 ...

  10. 基于Java的Selenium学习笔记——启动Chrome

    用Selenium 打开Chrome浏览器,需下载对应的chromedriver.exe,并将chromedriver放到lib文件夹下. 打开浏览器的代码如下: package com.seleni ...

最新文章

  1. 揭开Socket编程的面纱
  2. python xpath语法-Python爬虫基础之XPath语法与lxml库的用法详解
  3. [BOI2019][第K大问题][暴力剪枝]D2T1 Olympiads
  4. best wavelet guide
  5. mongodb导出查询结果
  6. [BUUCTF-pwn]——suctf_2018_stack
  7. Javascript模块模式学习分享
  8. IIS负载均衡-Application Request Route详解第五篇:使用ARR来配置试点项目
  9. 在Makefile中创建文件夹指令
  10. Windows服务器上使用phpstudy部署PHP程序
  11. Extjs6(六)——增删查改之查询
  12. Jersey学习笔记
  13. onpropertychange
  14. allegro17.4绘制PCB封装-R0603
  15. nxdn标准简介_标准活动介绍
  16. 好文推荐:努力是没有用的
  17. 腾讯应用宝正式开放 手游渠道争抢首发
  18. mysql基础命令(一)
  19. SpringCloud微服务实战——搭建企业级开发框架(三十一):自定义MybatisPlus代码生成器实现前后端代码自动生成
  20. 大数据之数据清洗之爬取数据后如何根据地名或者公司名获取经纬度信息-地址逆解析经纬度

热门文章

  1. TensorRT安装及使用--通用模型
  2. 吉首大学校赛 A SARS病毒 (欧拉降幂)
  3. 智能手环功能模块设计_智能手环毕业设计
  4. 【Windows】windows生成rsa密钥对
  5. 2018第三方支付牌照公司
  6. java连连看倒计时_javascrpit开发连连看记录-小游戏
  7. ios 判断打开相机权限_iOS 获取用户是否有(相册/相机)权限
  8. 联想商务机M8000T风扇狂转解决方法
  9. cisco881配置连接计算机,Cisco
  10. [Tushare] 通过复权因子计算前复权价格、后复权价格