Selenium
Selenium是一个基于Driver的包含一系列工具和库的大型项目,这些工具和库支持web浏览器的自动化测试。使用Selenium Grid能够在多个远程机器上同时并行执行自动化测试。
Selenium包含以下几个主要组件:
- Library: 用于支持不同语言的类库, 包含各种language bindings, 如Java, Python, JavaScript等等。
- Driver: 用于浏览器的直接操作, 类似于真实用户; 不同的浏览器有不同的驱动。
- WebDriver: Library和Driver的统称, 包含了language bindings和对浏览器操作的封装实现。 WebDriver提供了一组接口,用于查找和操作web文档中的DOM元素,模拟人工操作浏览器,能够跨平台和跨语言执行,是web浏览器进程外的程序。它的主要目的是允许编写测试脚本,自动化测试Web。
- Selenium IDE: 用于录制测试脚本, 用于辅助用户快速创建测试。
各组件之间关系如下图:
工作原理
Selenium的工作原理如下图:
具体流程如下:
- 开发者根据Selenium提供的不同的language bindings选择一种, 编写代码。
- Selenium将开发者编写的代码转成统一的操作指令。
- Selenium按照JSON格式将操作指令进行封装, 并通过HTTP协议将请求发送到Browser Driver。
- Browser Driver解析指令后驱动浏览器进行相应的操作。
环境搭建
- 下载安装JDK和配置环境变量
- 下载安装chrome浏览器 Driver
- 下载安装Maven,在Eclipse中配置Maven
- 在Eclipse中新建Maven项目,导入selenium库
- 接下来就能用Selenium自动化测试Web了。
Selenium执行效果
模拟输入input内容“UI自动化web测试selenium”,然后触发提交按钮提交。执行效果如下:
java脚本如下:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.time.Duration;
public class UiTest {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.get("https://www.selenium.dev/selenium/web/web-form.html");
driver.getTitle();
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500));
WebElement textBox = driver.findElement(By.name("my-text"));
WebElement submitButton = driver.findElement(By.cssSelector("button"));
textBox.sendKeys("Selenium1");
submitButton.click();
}
}
WebDriver - 元素
元素定位方法
传统方式定位
Selenium提供了8种传统的定位元素方法。
定位符 | 描述 |
---|---|
class名 | 根据类名定位元素(不支持符合类名) |
css选择器 | 根据CSS选择器定位元素 |
id | 根据id属性定位元素 |
name | 根据name属性定位元素 |
link文本内容 | 根据link文本内容定位元素 |
link部分内容 | 根据link部分文本内容定位元素 |
tag名 | 根据标签名定位元素 |
xpath | 根据与XPath表达式匹配定位元素,将HTML文档视为XML文档,使用xpath(遍历的路径),找到定位元素。支持相对路径和绝对路径2种方式 |
例子
<html>
<body>
<style>
.information {
background-color: white;
color: black;
padding: 10px;
}
</style>
<h2>Contact Selenium</h2>
<form action="/action_page.php">
<input type="radio" name="gender" value="m" />Male
<input type="radio" name="gender" value="f" />Female <br>
<br>
<label for="fname">First name:</label><br>
<input class="information" type="text" id="fname" name="fname" value="Jane"><br><br>
<label for="lname">Last name:</label><br>
<input class="information" type="text" id="lname" name="lname" value="Doe"><br><br>
<label for="newsletter">Newsletter:</label>
<input type="checkbox" name="newsletter" value="1" /><br><br>
<input type="submit" value="Submit">
</form>
<p>To know more about Selenium, visit the official page
<a href ="www.selenium.dev">Selenium Official Page</a>
</p>
</body>
</html>
WebDriver driver = new ChromeDriver();
//类名找元素
driver.findElement(By.className("information"));
//css选择器找元素
driver.findElement(By.cssSelector("#fname"));
//id值找元素
driver.findElement(By.id("lname"));
//name值找元素
driver.findElement(By.name("newsletter"));
//链接文本内容找元素
driver.findElement(By.linkText("Selenium Official Page"));
//链接部分文本内容找元素
driver.findElement(By.partialLinkText("Official Page"));
//标签名找元素
driver.findElement(By.tagName("a"));
//xpath找元素,找到femaile radio
driver.findElement(By.xpath("//input[@value='f']"));
使用定位元素
By
通过By定位元素。
import org.openqa.selenium.By;
WebDriver driver = new ChromeDriver();
driver.findElement(By.className("information"));
ByChained
ByChained
类能使两个By定位元素连接在一起。不用先找父元素然后再找父元素的一个子元素,可以把这两个整合在一起。例子github
By example = new ByChained(By.id("login-form"), By.id("username-field"));
WebElement username_input = driver.findElement(example);
ByAll
ByAll
类能够一次使用两个By定位,找到匹配By定位的元素。而不需要分别通过FindElement()
找到用户名和密码字段。 例子github
By example = new ByAll(By.id("password-field"), By.id("username-field"));
List<WebElement> login_inputs = driver.findElements(example);
相对定位
Selenium4引入了相对定位。对于本身不容易使用定位符找到,但是容易根据其他元素的相对位置找到的元素,很有用的。
工作原理
Selenium使用JavaScript函数getBoundingClientRect()来确定页面上元素的大小和位置,并可以使用此信息来定位相邻元素。
例子
Above
如果由于某种原因,邮箱字段元素不容易识别,但密码字段元素容易识别,那么我们可以利用它是密码元素“上方”的“input”元素这来定位邮箱字段元素。
By emailLocator = RelativeLocator.with(By.tagName("input")).above(By.id("password"));
Below
如果由于某种原因,密码字段元素不容易识别,但邮箱字段元素可以识别,那么我们可以利用它是邮箱元素“下面”的“input”元素来定位密码字段元素。
By passwordLocator = RelativeLocator.with(By.tagName("input")).below(By.id("email"));
Left of
如果由于某种原因,取消按钮不容易识别,但提交按钮元素可以识别,我们可以利用它是提交元素“左侧”的“button”元素来定位取消按钮元素。
By cancelLocator = RelativeLocator.with(By.tagName("button")).toLeftOf(By.id("submit"));
Right of
如果由于某种原因,提交按钮不容易识别,但取消按钮元素容易识别,我们可以利用它是“取消”元素右边的“button”元素来定位提交按钮元素。
By submitLocator = RelativeLocator.with(By.tagName("button")).toRightOf(By.id("cancel"));
Near
如果相对定位不明显,或者它根据窗口大小而变化,则可以使用near方法来标识距离所提供的定位最多50px的元素。一个很好的用例是处理一个表单元素,该元素没有容易构造的定位符,但它的关联输入标签元素有。
By emailLocator = RelativeLocator.with(By.tagName("input")).near(By.id("lbl-email"));
链式相对定位
有时候一个元素可能很容易根据在一个元素的上方/下方,并且在另一个元素的左方/右方,来定位。
By submitLocator = RelativeLocator.with(By.tagName("button")).below(By.id("email")).toRightOf(By.id("cancel"));
参考文献:
Selenium Overview
WebDriver
How does selenium interact with the Web browser?
使用JavaScript+Selenium玩转Web应用自动化测试
Web elements