元素定位
这里学习和记录 Web UI自动化的元素定位方式
前言
实现自动化则需要准确定位到html页面的元素控件,然后再进行操作,下面记录几种常用元素定位方法
一、元素定位
常用元素定位格式:
WebElement 元素对象 = driver.findElement(By.元素定位方式(“定位元素”))
基本用法
- classname: class属性定位元素
- name
- id :通过id来定位元素
- link text:a标签超链接文本
- partial link text
- tag name
css selector
css基础语法:
标签名:
$('input')
,标签 : input、button 等
class属性名:$('.classname')
,class属性的名称前面加英文点
id属性值:$('#id')
,id属性的名称前面加井号
属性值:$('[name="wd"]')
,一个元素可能有多个属性例如id name class以及其他的属性
元素关系定位:
并集:取两个属性的并集,则使用英文逗号间隔两属性
$('#属性1,#属性2')
,代表找到属性1或者属性2
邻近关系:'元素1+元素2
,两元素是同一个父亲(他俩平级),并且他们相邻
兄弟关系:元素1~元素2
,这两个元素是平级,不一定相邻
父子关系:元素1>元素2
,元素1是元素2的父亲
后代关系:元素1 元素2
,元素1是元素2的祖先,可以是父亲可以是爷爷…
父子关系+顺序关系:会存在子元素的标签名相同属性名也相同,可以通过子元素的顺序来定位第几个子元素:$(‘#father>标签:nth-child(2)’)
Xpath
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
xpath的表达式都写在中括号里面
在浏览器中的写法:$x('//*[@id='id']/')
基本语法:
高级用法:
and:[@属性1=‘属性值’ and @属性2= ‘属性值’],查找两个元素的交集,既满足属性1也满足属性2
or:[@属性1=‘属性值’ or @属性2= ‘属性值’],查找两个元素的并集,表示或的关系,满足其一 查找最后一个元素:[last()]
查找文本信息:[test()=‘文本信息’]
查找包含的元素:用来进行模糊查询,查询包含某值的元素,[contains(@属性,‘包含的属性值’)],例:查找包含某文本的元素[contains(test(),‘文本信息’)],查找包含id属性值:[contains(@id,‘idvalue’)],
二、浏览器复用
为什么进行浏览器复用
- 1.当运行 selenium 自动化时,要求已经登录才能才做。这个时候我们可以提前登录,运行脚本的时候复用已经打开的浏览器。
- 2.当调试了某个步骤很多的测试用例,前面N-1步已经成功,只需调试第N步。如果从头开始运行脚本,耗时过多,这时我们可以直接复用浏览器只操作第N步。
- 3.复用浏览器的特点: webdriver启动时将不再创建新的浏览器窗口 将运用已打开的浏览器的当前页面,对元素的进行操作
浏览器配置到Path
先将谷歌浏览器的安装路径 添加至path环境变量:
在浏览器上右键属性 复制安装路径,找到Application的路径
C:\Program Files\Google\Chrome\Application
添加至系统环境变量 path中
在cmd中输入 :chrome 会自动启动谷歌浏览器,否则就是没配置成功
关闭浏览器所有页面,这一步很重要,打开cmd 使用命令如下 :
chrome –remote-debugging-port=9222
启动了浏览器,在浏览器输入 localhost:9222 ,会出现一个空白页面,如果前面没有关闭浏览器的所有页面,这一步会失败
代码实现
使用java代码进行设置:
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
/**
* 浏览器复用
*/
public class RemoteTest {
@Test
void remoteLogin(){
// 设置chromeOptions实例对象
ChromeOptions chromeOptions = new ChromeOptions();
// 配置debug地址
chromeOptions.setExperimentalOption("debuggerAddress","localhost:9222");
// 初始化浏览器并添加配置信息
WebDriver driver = new ChromeDriver(chromeOptions);
driver.get("https://baidu.com/");
}
}
三、page object 设计模式
官网文档:https://www.selenium.dev/zh-cn/documentation/test_practices/encouraged/page_object_models/
传统UI自动化出现的问题
- 无法适应 UI 频繁变化
- 无法清晰表达业务用例场景
- 大量的样板代码 driver/find/click
PO模式的优势:
- 降低 UI 变化导致的测试用例脆弱性问题
- 让用例清晰明朗,与具体实现无关
PO的建模原则:
- 字段意义 :
1.不要暴露页面内部的元素给外部
2.不需要建模 UI 内的所有元素 - 方法意义
1用公共方法代表 UI 所提供的功能
2.方法应该返回其他的PageObject 或者返回用于断言的数据
3.同样的行为不同的结果可以建模为不同的方法
4.不要在方法内加断言
使用:将元素信息和操作的细节封装到Page Object类中,并根据业务逻辑,在测试用例中链式调用
例如一个登录功能,创建PageObject类,将 定位元素和给元素赋值封装在PO类中
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
/**
* Page Object encapsulates the Sign-in page.
*/
public class SignInPage {
protected WebDriver driver;
// <input name="user_name" type="text" value="">
private By usernameBy = By.name("user_name");
// <input name="password" type="password" value="">
private By passwordBy = By.name("password");
// <input name="sign_in" type="submit" value="SignIn">
private By signinBy = By.name("sign_in");
public SignInPage(WebDriver driver){
this.driver = driver;
}
/**
* Login as valid user
*
* @param userName
* @param password
* @return HomePage object
*/
public HomePage loginValidUser(String userName, String password) {
driver.findElement(usernameBy).sendKeys(userName);
driver.findElement(passwordBy).sendKeys(password);
driver.findElement(signinBy).click();
return new HomePage(driver);
}
}
在测试用例中写对po类的调用以及用例断言
/***
* Tests login feature
*/
public class TestLogin {
@Test
public void testLogin() {
SignInPage signInPage = new SignInPage(driver);
HomePage homePage = signInPage.loginValidUser("userName", "password");
assertThat(homePage.getMessageText(), is("Hello userName"));
}
}