2019 年的增压测试技巧:Java 自动化测试教程
已发表: 2022-03-11每年,来自全球的测试自动化工程师都会研究最新的工具和技术,以使他们的测试自动化框架更稳定、更快、更易于使用和维护。 这对于确保在公司内继续广泛采用他们的框架至关重要。 一般来说,臃肿、过时的框架很快就会过时。
在这篇文章中,我们将了解一些可以为 2019 年更新框架的方法以及如何为 2020 年做好准备。为了改进我的框架,我总是专注于“痛点”。 这些是设置复杂或导致最多故障的区域。 我确定了三个我想简化或改进的主要领域:
- 硒网格
- 等待
- Chrome 开发者工具
Selenium Grid 的设置是出了名的棘手,并且可能会在没有警告的情况下失败。 我想看看这里有什么改进。 我还想调查是否向 Selenium API 添加了任何新的waits
,以提高我创建的任何测试的稳定性。 最后,我想看看我是否可以通过 Selenium 开始与 Chrome DevTools 进行交互,Selenium 已成为任何测试人员工具包的重要组成部分。
提示 #1:Dockerize 你的 Selenium 网格
Selenium Grid 是出了名的难以在 CI 管道上设置、不稳定且难以部署或版本控制。 一种更简单、稳定且可维护的方法是使用预先构建的 Selenium Docker 映像。
注意:这种方法的一个缺点是不支持 IE (Internet Explorer),因为它还不能容器化 Windows 操作系统。
开始设置
要启动并运行,首先你需要在你的机器上安装 Docker 和 Docker Compose。 如果您运行的是 Windows 10 或 Mac,那么它们都将通过 Docker 桌面安装。
开始你的网格
Docker Hub 上的官方 Selenium 存储库包含为您的 Selenium Hub 以及 Firefox 和 Chrome 节点预先构建的 Docker 映像。
在本地 Selenium Grid 中使用它们的最简单方法是在项目的根目录中构建一个 Docker Compose 文件。 将文件命名为docker-compose.yml
以保持简单。
我在下面包含了一个示例,该示例创建了以下网格:
- 单个 Selenium 集线器
- 一个 Chrome 节点
- 一个 Firefox 节点
#docker-compose.yml version: "3" services: selenium-hub: image: selenium/hub:3.141.59-neon container_name: selenium-hub ports: - "4444:4444" chrome: image: selenium/node-chrome:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444 firefox: image: selenium/node-firefox:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444
Docker Compose 文件描述了 Grid 的设置。 有关创建 Docker Compose 文件的更多信息,请参阅官方文档。
要启动 Grid,只需使用任何终端窗口(Windows 中的powershell
或cmd
窗口)从项目的根目录运行以下命令:
docker-compose up
连接到电网
您可以像往常一样以完全相同的方式连接到 Selenium Grid,因为 Hub 正在侦听本地计算机的端口 4444。 这是一个示例,我们将驱动程序设置为使用我们的 Chrome 节点。
// Driver.java protected static RemoteWebDriver browser; DesiredCapabilities cap = new DesiredCapabilities(); ChromeOptions chromeOptions = new ChromeOptions(); cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions); cap.setBrowserName("chrome"); driver = new RemoteWebDriver(cap);
然后,您可以像往常一样使用 TestNG 库在多个节点上并行运行测试。
值得注意的是,可以在每个节点上运行多个浏览器。 然而,这是不鼓励的,每个节点使用一个浏览器被认为是最佳性能的最佳实践。
其他提示和技巧
如果您想查看浏览器上发生了什么以便调试您的测试,那么值得拥有一个docker-compose.yml
文件的debug
版本来下载debug
浏览器节点。 它们包含一个 VNC 服务器,因此您可以在测试运行时观看浏览器。
也可以无头运行浏览器以提高速度(通常的方式),Selenium 还提供图像的base
版本,因此如果您需要安装其他软件,您可以构建自己的图像。
要为您的 CI 管道创建一个稳定的网格版本,也可以将您的网格部署到 Kubernetes 或 Swarm 上。 这确保了任何 Docker 在它们发生故障时都能快速恢复或替换。
提示 #2:智能等待
任何测试自动化工程师都知道, waits
对于测试自动化框架的稳定性至关重要。 他们还可以通过渲染任何冗余的sleeps
或pauses
来加速您的测试,并克服缓慢的网络和跨浏览器问题。 以下是一些让您的waits
更有弹性的提示。
Java 自动化测试教程 #2:等待中的逻辑运算符:特定于等待
ExpectedConditions
类随着时间的推移而发展壮大,现在几乎涵盖了所有可以想象的情况。 虽然ExpectedConditions.presenceOfElementLocated(locator)
通常就足够了,但最佳实践是使用ExpectedCondition
类中的方法通过将它们嵌入到Actions.java
类中来涵盖每个用户操作。 这将使您的测试免受大多数跨浏览器或慢速网站问题的影响。
例如,如果单击链接导致新选项卡打开,则使用ExpectedConditions.numberOfWindowsToBe(2)
。 这将确保该选项卡在尝试切换到它之前就在那里。
您还可以使用wait
来确保在使用findElements
时捕获页面上存在的所有元素。 如果search
页面需要时间来返回其结果,这将特别有用。 例如,这一行:
List<WebElement> results = driver.findElements(locators.RESULTS);
如果您的搜索结果尚未加载,它可能会导致一个空的List
数组。 相反,最好使用numberOfElementsToBeMoreThan
预期条件等待结果大于零。 例如:
WebElement searchButton = driver.findElement(locators.SEARCH_BUTTON); searchButton.click(); new WebDriverWait(driver, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locators.RESULTS, 0)); List<WebElement> results = driver.findElements(locators.RESULTS); results.get(0).click();
现在,您的findElements
命令只会在搜索结果返回后运行。
当您处理与 Selenium 不兼容的前端(例如,Angular 网站)时,这种wait
对于查找单个元素也很有用。 创建这样的方法将保护您的测试,使它们更加稳定。
protected static WebElement waitForElement(By locator){ try { new WebDriverWait(browser, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locator, 0)); } catch (TimeoutException e){ e.printStackTrace(); Assert.fail("Timeout: The element couldn't be found in " + WAIT + " seconds!"); } catch (Exception e){ e.printStackTrace(); Assert.fail("Something went wrong!"); } return browser.findElement(locator); }
甚至可以等待元素不再可见。 如果您在继续测试之前单击“ OK
”或“ Save
”按钮后等待弹出窗口消失,这将特别有用。
WebElement okButton = driver.findElement(locators.OK_BUTTON); okButton.click(); new WebDriverWait(driver, 30) .until( ExpectedConditions .invisibilityOfElementLocated(locators.POPUP_TITLE) );
上述所有方法以及更多方法都列在官方文档中。 花十分钟阅读所有可能性并提高框架的稳定性是非常值得的。
Java 自动化测试教程 #2:等待中的逻辑运算符
在waits
中建立弹性的一个好方法是使用逻辑运算符。 例如,如果您想检查一个元素是否已被定位并且它是可点击的,您将使用以下代码(请注意,这些示例返回一个布尔值):
wait.until(ExpectedConditions.and( ExpectedConditions.presenceOfElementLocated(locator), ExpectedConditions.elementToBeClickable(locator) ) );
如果您不确定页面的标题是否会更改,则 OR 运算符将是合适的。 然后,如果第一个条件失败,您可以检查 URL,以确认您确实在正确的页面上。
wait.until(ExpectedConditions.or( ExpectedConditions.titleIs(expectedTitle), ExpectedConditions.urlToBe(expectedUrl) ) );
或者,如果您想确保在页面上执行操作后不再启用复选框,则 NOT 运算符是合适的。

wait.until(ExpectedConditions.not( ExpectedConditions.elementToBeClickable(locator) ) );
使用运算符可以使您的waits
更有弹性,并导致测试不那么脆弱。
提示 #3:Chrome DevTools:模拟网络条件
在 localhost 或本地网络上运行您的 Web 应用程序可能会在野外运行时对其性能产生错误的印象。 限制各种上传和下载速度的能力将使您更好地了解您的应用程序将如何在 Internet 上运行,其中超时可能导致操作失败。 我们可以开始使用 Chrome 的 DevTools 来模拟这个。
以下代码将使用不同的下载和上传速度打开 Toptal 主页。 首先,我们将使用以下代码将速度存储在 TestNG 数据提供程序中:
import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "networkConditions") public static Object[][] networkConditions() throws Exception { return new Object[][] { // Upload Speed, Dowload Speed in kb/s and latency in ms. { 5000 , 5000, 5 }, { 10000, 7000, 5 }, { 15000, 9000, 5 }, { 20000, 10000, 5 }, { 0, 0 }, }; } }
注意:上传和下载节流以kb/s
为单位,延迟以ms
为单位。
然后,我们可以使用这些数据在不同的网络条件下运行我们的测试。 在测试中, CommandExecutor
将在浏览器的当前会话中执行命令。 这反过来将激活 Chrome 开发者工具功能中的必要设置,以模拟我们的慢速网络。 在运行一组测试时, if
语句中的代码可以包含在@BeforeClass
方法中。
import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandExecutor; import org.openqa.selenium.remote.Response; public class TestClass { // load our data provider @Test(dataProvider = "networkConditions") public void test(int download, int upload, int latency) throws IOException { // only run if the network is throttled if (download > 0 && upload > 0) { CommandExecutor executor = driver.getCommandExecutor(); // create a hashmap of the required network conditions Map map = new HashMap(); // you can even test 'offline' behaviour map.put("offline", false); map.put("latency", latency); map.put("download_throughput", downloadThroughput); map.put("upload_throughput", uploadThroughput); // execute our code Response response = executor.execute( new Command(driver.getSessionId(), "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map)))); } // Open the website driver.get("https://www.toptal.com/"); // You can then check that elements are loaded etc. // Don't forget to use waits! } }
额外提示:如何管理您的 Cookie
浏览器 cookie 可能会在您的应用程序中导致不同的行为,具体取决于它们是否已从先前的会话中保存(例如,应用程序可能会在用户已登录的情况下加载)。 在每次测试运行之前清除您的 cookie 以确保它们不会导致问题是一种很好的做法。
下面的代码允许您删除所有 cookie:
driver.manage().deleteAllCookies();
您还可以按名称删除 cookie:
driver.manage().deleteCookieNamed("CookieName");
或者获取 cookie 的内容:
String myCookie = driver.manage().getCookieNamed("CookieName").getValue();
或者获取所有的 cookie:
List<Cookie> cookies = driver.manage().getCookies();
2020 年的测试自动化:展望未来
Selenium 4 将在未来几个月内发布。 它仍在开发中,但由于已经发布了 alpha 版本,因此值得看看它将提供哪些改进。
注意:您可以通过查看路线图来跟踪他们的进度。
W3C WebDriver 标准化
Selenium 不再需要通过 JSON 有线协议与浏览器通信; 相反,自动化测试将直接与浏览器通信。 这应该解决 Selenium 测试著名的不稳定特性,包括防止浏览器升级。 希望测试速度也会提高。
更简单的 Selenium 网格
Selenium Grid 在 Selenium 4 中将更加稳定,更易于设置和管理。用户将不再需要单独设置和启动集线器和节点,因为网格将充当组合节点和集线器。 此外,将对 Docker 提供更好的支持,本机将包含并行测试,并将提供更多信息的 UI。 使用 Hooks 进行请求跟踪也将帮助您调试网格。
文档
自 Selenium 2.0 发布以来,Selenium 文档将得到急需的大修,尚未更新。
API 的更改
对 Opera 和 PhantomJS 浏览器的支持将被删除。 可以使用 Chrome 或 Firefox 执行无头运行,并且 Opera 是基于 Chromium 构建的,因此 Chromium 测试对于这个浏览器来说已经足够了。
WebElement.getSize()
和WebElement.getLocation()
现在替换为单个方法WebElement.getRect()
。 但是,由于这些通常用于创建单个元素的屏幕截图,因此值得知道的是,在 Selenium 4 中还将有一个 API 命令来捕获元素的屏幕截图。
对于 WebDriver Window
, getPosition
和getSize
方法将被getRect
方法替换, setPosition
和setSize
方法将被setRect
方法替换。 fullscreen
和minimize
方法将可用,因此可以在您的测试中执行这些操作。
其他显着变化:
- 现在,每个浏览器的
Options
类都将扩展Capabilities
类。 - 添加了
driver.switchTo().parentFrame()
方法以使框架导航更容易。 - 将包括在当前定位器更高级别上运行的
nice
定位器。 它们将是By
的子类。 - 将有一个
DevTools
API 的实现,允许用户利用使用 Chrome 调试协议(以及其他浏览器上的等效协议)提供的功能。 这些包括:- 整页截图(包括屏幕外元素)。
- 流式传输日志。
- 等待页面上的突变事件。
- 许多不推荐使用的方法和类也将被删除。
注意:您可以从 Maven 存储库获取 Selenium 4 的 Alpha 版本。 强烈建议您针对您当前的框架(最好在沙箱分支上)尝试此操作,以便您为更改做好准备。
结论
在本文中,我介绍了一些我改进了我的测试自动化框架的领域。 它现在比以前更加稳定和可用,这将对参与软件交付生命周期的每个人产生积极影响。
进行我上面概述的更改是一个好的开始,但是,我强烈建议您查看整个框架的“痛点”,因为您可能会做出我没有涵盖的改进。 例如,您是使用 WebDriver Manager 来管理驱动程序还是仍在手动更新它们?
我还建议设置一个日期,至少每年一次,尽管理想情况下是每六个月一次。 在文章中,我介绍了 Selenium 4.0 中即将发生的变化。 请自己查看 Selenium 的alpha
版本。 这些变化将是巨大的,您需要做好准备。 我希望你发现这很有用。 如果你在对你的框架进行一些春季大扫除时发现了任何新的方法或技术,请通过将它们添加到下面的评论部分与本博客的其他读者分享。
此外,如果您想了解 Selenium 中的自动化测试,以及如何使用页面对象模型来编写可维护和可重用的测试例程,请查看Selenium 中的自动化:页面对象模型和页面工厂。