目录
元素的定位(以定义百度输入框,并且向输入框输入“selenium”文本内容为例)
tag name (标签名)定位和class name 定位
定义:
自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最 后评估运行结果。将人为驱动的测试行为转化为机器执行的过程
- 为什么选择selenium作为web自动化工具
selenium是开源的
selenium支持多种语言
selenium支持各种浏览器
selenium有丰富的API- 什么是自动化以及为什么要做自动化
自动化是测试人员为了提高测试效率或者保证测试质量,让代码辅助测试人员执行测试的这个过程
分类:
单元测试,接口自动化,UI自动化
selenium:
Selenium是web应用中基于UI的自动化测试框架,支持多平台、多浏览器、多语言。
原理:
webdriver API:
元素的定位(以定义百度输入框,并且向输入框输入“selenium”文本内容为例)
id定位:
browser.find_element_by_id("kw").send_keys("selenium")
name 定位:
如果这个元素有name,并且元素的name命名在整个页面是唯一的,那么我们可以用name来定位这个 元素。
browser.find_element_by_name("wd").send_keys("selenium")
tag name (标签名)定位和class name 定位:
input 就是一个标签的名字,可以通过find_element_by_tag_name("input") 函数来定位。 class="s_ipt",通过find_element_by_class_name("s_ipt")函数定位百度输入框。
browser.find_element_by_tag_name("input").send_keys("selenium")
//不能成功,因为input太多了不唯一。
CSS 定位:
CSS 使用选择器来为页面元素绑定属性。这些选择器可以被selenium 用作另外的定位策略。
CSS 的比较灵活可以选择控件的任意属性,上面的例子中: find_element_by_css_selector("#kw") 通过find_element_by_css_selector( )函数,选择取百度输入框的id 属性来定义
browser.find_element_by_css_selector("#kw").send_keys("selenium")
XPath 定位:
XPath 扩展了上面id 和name 定位方式,提供了很多种可能性。
browser.find_element_by_xpath("//*[@id='kw']").send_keys("selenium")
link text定位:
有时候不是一个输入框也不是一个按钮,而是一个文字链接,我们可以通过链接内容,也就是 link text 来定位。
#coding=utf-8
//防止乱码,在编辑器里面可以不用加,因为编辑器默认的就是UTF-8模式。
from selenium import webdriver
//导入webdriver工具包,这样就可以使用里面的API
browser = webdriver.Chrome()
browser.get("http://www.baidu.com")
browser.find_element_by_link_text("hao123").click()
browser.quit()
//quit方法不仅关闭窗口,还会彻底的退出webdriver,释放与driver
server之间的连接,与close()不同
Partial link text 定位:
通过部分链接定位
#coding=utf-8
//防止乱码,在编辑器里面可以不用加,因为编辑器默认的就是UTF-8模式。
from selenium import webdriver
//导入webdriver工具包,这样就可以使用里面的API
browser = webdriver.Chrome()
browser.get("http://www.baidu.com")
browser.find_element_by_link_text("hao").click()
browser.quit()
//quit方法不仅关闭窗口,还会彻底的退出webdriver,释放与driver
server之间的连接,与close()不同
操作测试对象
鼠标点击与键盘输入:
send_keys("xx") 用于在一个输入框里输入xx 内容。
click() 用于点击一个按钮。
clear() 用于清除输入框的内容,比如百度输入框里默认有个“请输入关键字”的信息,再比如我们的登陆 框一般默认会有“账号”“密码”这样的默认信息。clear 可以帮助我们清除这些信息。
submit 提交表单:
driver.find_element_by_id("su").submit()
如果元素在form标签中,按钮“百度一下”元素的类型type=“submit”,所以把“百度一下”的操作从click 换成submit 可以达到相同的效果;如果不在form标签中,则用submit会报错
text 用于获取元素的文本信息
添加等待
sleep休眠(指固定休眠)
time.sleep(3)
隐式等待
隐式地等待并非一个固定的等待时间,当脚本执行到某个元素定位时,如果元素可以定位,则继续执 行;如果元素定位不到,则它以轮询的方式不断的判断元素是否被定位到。直到超出设置的时长
browser.implicitly_wait(30)
浏览器的操作
浏览器最大化
browser.maximize_window()
设置浏览器宽、高
browser.set_window_size(width, high)
操作浏览器的前进、后退
#浏览器的前进
browser.forward()
#浏览器的后退
browser.back()
控制浏览器滚动条
#将浏览器滚动条滑到最顶端
document.documentElement.scrollTop=0
#将浏览器滚动条滑到最底端
document.documentElement.scrollTop=10000
键盘事件
键盘按键用法
send_keys(Keys.TAB) # TAB
send_keys(Keys.ENTER) # 回车
send_keys(Keys.SPACE) #空格键
send_keys(Keys.ESCAPE) #回退键(Esc)
键盘组合键用法
send_keys(Keys.CONTROL,'a') #全选(Ctrl+A)
send_keys(Keys.CONTROL,'c') #复制(Ctrl+C)
send_keys(Keys.CONTROL,'x') #剪贴(Ctrl+X)
send_keys(Keys.CONTROL,'v') #粘贴(Ctrl+V)
鼠标事件
要使用鼠标事件需要导入工具包:
from selenium.webdriver.common.action_chains import ActionChains
ActionChains 类:
- context_click() 右击
- double_click() 双击
- drag_and_drop() 拖动
- move_to_element() 移动
ActionChains(driver).move_to_element(element).perform()
//ActionChains(driver)
//生成用户的行为。所有的行动都存储在actionchains 对象。通过perform()存储的行为。
//move_to_element(element)
//移动鼠标到一个元素中,menu 上面已经定义了他所指向的哪一个元素
//perform()
//执行所有存储的行为
定位一组元素
应用场景:
- 批量操作对象,比如将页面上所有的checkbox 都勾上
- 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的 checkbox,然后选择最后一个
框架/窗口定位
- 定位一个框架frame :switch_to.frame(name_or_id_or_frame_element)
- 定位一个窗口window:switch_to.window(name_or_id_or_frame_element)
下拉框处理
下拉框是我们最常见的一种页面元素,对于一般的元素,我们只需要一次就定位,但下拉框里的内容需 要进行两次定位,先定位到下拉框对下拉框进行操作后,再定位到下拉框内里的选项。
以下为一个下拉框的HTML:
<html>
<body>
<select id="ShippingMethod"
onchange="updateShipping(options[selectedIndex]);" name="ShippingMethod">
<option value="12.51">UPS Next Day Air ==> $12.51</option>
<option value="11.61">UPS Next Day Air Saver ==> $11.61</option>
<option value="10.69">UPS 3 Day Select ==> $10.69</option>
<option value="9.03">UPS 2nd Day Air ==> $9.03</option>
<option value="8.34">UPS Ground ==> $8.34</option>
<option value="9.25">USPS Priority Mail Insured ==> $9.25</option>
<option value="7.45">USPS Priority Mail ==> $7.45</option>
<option value="3.20" selected="">USPS First Class ==> $3.20</option>
</select>
</body>
</html>
先定位到下拉框对下拉框进行操作后,再定位到下拉框内里的选项:
#coding=utf-8
from selenium import webdriver
import os,time
driver= webdriver.Chrome()
file_path = 'file:///' + os.path.abspath('drop_down.html')
driver.get(file_path)
time.sleep(2)
#先定位到下拉框
m=driver.find_element_by_id("ShippingMethod")
#再点击下拉框下的选项
m.find_element_by_xpath("//option[@value='10.69']").click()
time.sleep(3)
driver.quit()
alert、confirm、prompt 的处理
- text 返回alert/confirm/prompt 中的文字信息
- accept 点击确认按钮
- dismiss 点击取消按钮,如果有的话
- send_keys 输入值,如果alert 没有对话框就不能用了,不然会报错
//当alert中有对话框,在alert的对话框中输入信息
#点击“请点击”
driver.find_element_by_xpath("html/body/input").click()
#输入内容
driver.switch_to.alert().send_keys('webdriver')
driver.switch_to.alert().accept()
sleep(5)
driver.quit()
DIV对话框的处理
如果页面元素比较多,利用元素的属性无法准确的定位这个元素的时候,我们可以先定位元素所在的 div块,再去定位这个元素。
上传文件操作
#定位上传按钮,添加本地文件
driver.find_element_by_name("file").send_keys('D:\\PycharmProjects\\test\\upload
.txt')
单元测试工具Junit
自动化就是 selenium 脚本来实现的,junit 是 java 的单元测试工具,只不过在实现自动化的时候需要借用一下 junit 库里面提供的一些注解(junit5)
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
@Test(测试方法)、
@BeforeEach(每个测试用例前执行一次)、
@BeforeAll(所有测试用例前执行一次)、( 注解的方法必须为静态方法)
@AfterEach(每个测试用例之后执行一次)、
@AfterAll(所有测试用例之后执行一次)( 注解的方法必须为静态方法)
通过 order 注解来排序
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
//按随机运行
//@TestMethodOrder(MethodOrderer.Random.class)(则不用order)
public class JunitTest3 {
@Order(2)
@Test
void test01(){
System.out.println("tset01");
}
@Order(1)
@Test
void test02(){
System.out.println("tset02");
}
@Order(3)
@Test
void test03(){
System.out.println("tset03");
}
}
执行结果:
参数化
单参数:
@ParameterzedTest + @ValueSource(数据类型方法/加s = {参数1,参数2,参数3,…})
@ParameterizedTest
@ValueSource(ints={1,2,3})
void Test01(int num){
System.out.println(num);
}
执行结果:
多参数:
@parameterizedTest + @CsvSource({“”, “”, '", …}) 每个双引号就是一组测试用例
@ParameterizedTest
@CsvSource({"张三,22","李四,25","王五,35"})
void muchParamsTest(String name,int age) {
System.out.println("name: " + name + ",age: " + age);
}
执行结果:
@parameterizedTest + @CsvFileSource({“”, “”, '", …}) 每个双引号就是一组测试用例
@ParameterizedTest
@CsvFileSource(resources = "test02.csv")
void test03(int num,String name){
System.out.println("学号:"+num+"姓名:"+name);
}
执行结果:
动态参数方法:
// 通过动态方法来提供数据源
@ParameterizedTest
@MethodSource("methodParams")
void dynamicMethodParamsTest(String name,int age) {
System.out.println("name: " + name + ",age: " + age);
}
static Stream<Arguments> methodParams() throws InterruptedException {
// 构造动态参数
String[] arr = new String[5];
for (int i = 0; i < arr.length; i++) {
Thread.sleep(500);
arr[i] = System.currentTimeMillis() + "";
}
return Stream.of(
Arguments.arguments(arr[0],20),
Arguments.arguments(arr[1],20),
Arguments.arguments(arr[2],20),
Arguments.arguments(arr[3],20),
Arguments.arguments(arr[4],20)
);
}
执行结果:
static Stream<Arguments> methodParams() throws InterruptedException {此处返回的数据类型如果是统一的,就写具体的数据类型;如果不统一,就返回Arguments的流
@MethodSource("methodParams")当不指定数据源方法名时,会自动找和用例方法名(dynamicMethodParamsTest())相同的静态方法
断言 Assertions
断言匹配 assertEquals,断言不匹配 assertNotEquals
@ParameterizedTest
@ValueSource(ints = {1})
void test01(int num){
//判断是否为1,不是会报错
Assertions.assertEquals(1,num);
//判断是否不为1,是1会报错
//Assertions.assertNotEquals(1,num);
//判断字符串是否为空
//Assertions.assertNull();
}
执行结果:
断言结果为真 assertTrue,断言结果为假 assertFalse
断言结构为空 assertNull,断言结果不为空 assertNotNull