selenium java 自动化Web UI测试

92 阅读5分钟

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: 用于录制测试脚本, 用于辅助用户快速创建测试。

各组件之间关系如下图:

20200821232213.png

工作原理

Selenium的工作原理如下图:

20200821232445.png

具体流程如下:

  • 开发者根据Selenium提供的不同的language bindings选择一种, 编写代码。
  • Selenium将开发者编写的代码转成统一的操作指令。
  • Selenium按照JSON格式将操作指令进行封装, 并通过HTTP协议将请求发送到Browser Driver。
  • Browser Driver解析指令后驱动浏览器进行相应的操作。

环境搭建

  1. 下载安装JDK和配置环境变量
  2. 下载安装chrome浏览器 Driver
  3. 下载安装Maven,在Eclipse中配置Maven
  4. 在Eclipse中新建Maven项目,导入selenium库
  5. 接下来就能用Selenium自动化测试Web了。

Selenium执行效果

模拟输入input内容“UI自动化web测试selenium”,然后触发提交按钮提交。执行效果如下:

auto-test.gif

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 &nbsp;
  <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()来确定页面上元素的大小和位置,并可以使用此信息来定位相邻元素。

例子

relative_locators.png

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