个性化阅读
专注于IT技术分析

2019年的增压测试技巧:Java自动化测试教程

本文概述

每年, 全球的测试自动化工程师将研究最新的工具和技术, 以使他们的测试自动化框架更加稳定, 更快, 更易于使用和维护。这对于确保在公司内部继续广泛采用其框架至关重要。通常, 过时的, 过时的框架很快就会过时。

在本文中, 我们将介绍一些你可以在2019年更新框架的方法以及如何为2020年做准备。为了改进我的框架, 我始终专注于”痛点”。这些是设置复杂或导致最多故障的领域。我确定了三个要简化或改进的主要领域:

  1. Selenium Grid
  2. 等待
  3. Chrome DevTools

众所周知, Selenium Grid的设置非常棘手, 并且可能在没有警告的情况下失败。我想看看这里有什么改进。我还想调查Selenium API是否添加了新的等待, 以提高我创建的任何测试的稳定性。最后, 我想看看是否可以通过Selenium与Chrome DevTools进行交互, 而Selenium已经成为任何测试人员工具包中必不可少的一部分。

提示1:Docker化你的Selenium Grid

众所周知, 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文件描述了网格的设置。有关创建Docker Compose文件的更多信息, 请参阅官方文档。

要启动网格, 只需使用任何终端窗口(Windows中的powershell或cmd窗口)从项目的根目录中运行以下命令:

docker-compose up

连接到网格

因为集线器正在侦听本地计算机的端口4444, 所以你可以以与通常相同的方式连接到Selenium Grid。这是一个示例, 其中我们设置了驱动程序以使用我们的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文件的调试版本来下载调试浏览器节点。它们包含一个VNC服务器, 因此你可以在测试运行时观察浏览器。

也可以无头运行浏览器以提高速度(通常的方式), 并且Selenium还提供了图像的基本版本, 因此, 如果需要安装其他软件, 则可以构建自己的图像。

为了为CI管道创建稳定的Grid版本, 还可以将Grid部署到Kubernetes或Swarm上。这样可以确保所有Docker发生故障时都可以快速恢复或更换。

提示2:智能等待

任何测试自动化工程师都知道, 等待对于你的测试自动化框架的稳定性至关重要。他们还可以通过提供任何睡眠或暂停来加速你的测试, 并克服缓慢的网络和跨浏览器问题。以下是一些使你的等待更有弹性的提示。

Java自动化测试教程#2:等待中的逻辑运算符:具体针对你的等待

ExpectedConditions类随着时间的推移而增长, 现在涵盖了几乎所有可以想象的情况。尽管ExpectedConditions.presenceOfElementLocated(locator)通常就足够了, 但最佳做法是使用ExpectedCondition类中的方法将每个用户操作嵌入到Actions.java类中, 以覆盖每个用户操作。这将使你的测试免受大多数跨浏览器或网站缓慢问题的影响。

例如, 如果单击链接导致打开新标签页, 则使用ExpectedConditions.numberOfWindowsToBe(2)。这将确保在尝试切换到该选项卡之前, 该选项卡已存在。

你还可以等待以确保在使用findElements时捕获了页面上存在的所有元素。如果搜索页面需要花费一些时间来返回其结果, 则此功能尤其有用。例如, 这一行:

List<WebElement> results = driver.findElements(locators.RESULTS);

如果你的搜索结果尚未加载, 则可能会导致列表数组为空。相反, 最好使用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网站), 此等待对查找单个元素也很有用。创建这样的方法将保护你的测试, 使其更加稳定。

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);    
}

甚至可以等待元素不再可见。如果你在继续测试之前单击”确定”或”保存”按钮, 然后等待弹出窗口消失, 则此功能特别有用。

WebElement okButton = driver.findElement(locators.OK_BUTTON);
okButton.click();
 
new WebDriverWait(driver, 30)
	.until(
		ExpectedConditions
			.invisibilityOfElementLocated(locators.POPUP_TITLE)
);

官方文档中列出了上述所有方法以及更多方法。花十分钟阅读所有可能的方法并改善框架的稳定性是值得的。

Java自动化测试教程2:等待中的逻辑运算符

在等待中建立弹性的一种好方法是使用逻辑运算符。例如, 如果要检查是否已找到某个元素并且该元素是可单击的, 则可以使用以下代码(请注意, 这些示例返回一个布尔值):

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)
	)
);

使用运算符可以使你的等待更有弹性, 并减少测试的难度。

提示3:Chrome DevTools:模拟网络条件

在本地环境或本地网络上运行Web应用程序可能会对其在野外运行时的性能产生错误的印象。可以限制各种上载和下载速度的功能将使你更好地表示你的应用程序将如何在Internet上运行, 超时可能导致操作失败。我们可以开始使用Chrome的DevTools进行模拟。

以下代码将使用不同的下载和上传速度打开srcmini主页。首先, 我们将使用以下代码将速度存储在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.srcmini02.com/");

        // You can then check that elements are loaded etc.
        // Don't forget to use waits!
}
}

相关:建立信心:JUnit测试指南

额外提示:如何管理你的Cookies

浏览器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年的测试自动化:展望未来

Selenium4将在未来几个月内发布。它仍在开发中, 但是由于已经发布了Alpha版本, 因此值得一看的是它将提供哪些改进。

注意:你可以通过查看路线图来跟踪他们的进度。

W3C WebDriver标准化

Selenium不再需要通过JSON Wire协议与浏览器进行通信;相反, 自动化测试将直接与浏览器通信。这应该解决Selenium测试著名的易碎特性, 包括防止浏览器升级。希望测试速度也会提高。

一个更简单的Selenium Grid

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窗口, getPosition和getSize方法将由getRect方法替换, 而setPosition和setSize方法将由setRect方法替换。全屏和最小化方法将可用, 因此可以在测试中执行这些操作。

其他值得注意的变化:

  • 现在, 每个浏览器的Options类都将扩展Capabilities类。
  • 添加了driver.switchTo()。parentFrame()方法以使框架导航更加容易。
  • 好的定位器将被包括在内, 并在当前定位器的更高级别上运行。它们将是By的子类。
  • 将实现DevTools API的实现, 使用户可以利用通过Chrome调试协议(以及其他浏览器上的等效功能)提供的功能。这些包括:
    • 整页的屏幕截图(包括屏幕外元素)。
    • 流日志。
    • 等待页面上的突变事件。
  • 许多不推荐使用的方法和类也将被删除。

注意:你可以从Maven存储库中获得Selenium 4的Alpha版本。强烈建议你针对当前框架(最好是在沙盒分支上)进行尝试, 以便为更改做好准备。

总结

在本文中, 我涵盖了一些领域, 这些领域需要改进我的测试自动化框架。现在它比以前更稳定和可用, 这将对软件交付生命周期中涉及的每个人产生积极影响。

进行上面概述的更改是一个好的开始, 但是, 我强烈建议你查看整个框架以了解”痛点”, 因为你可能会做出一些我无法涵盖的改进。例如, 你是使用WebDriver Manager来管理驱动程序还是仍在手动更新它们?

我还建议你设置一个日期, 使其至少每年一次, 尽管理想情况下, 应该是每六个月一次。在本文中, 我包括了Selenium 4.0中即将进行的更改。请自己检查Selenium的Alpha版本。变化将是巨大的, 你需要做好准备。希望你发现这很有用。如果你在对框架进行一些春季清理时发现了任何新方法或技术, 请​​通过将它们添加到下面的评论部分中, 与本博客的其他读者分享它们。

另外, 如果你希望了解Selenium中的自动化测试以及如何使用Page Object模型编写可维护和可重用的测试例程, 请查看Selenium中的Automation:页面对象模型和Page Factory。

相关文章:Dart语言:Java和C#不够清晰时

赞(0)
未经允许不得转载:srcmini » 2019年的增压测试技巧:Java自动化测试教程

评论 抢沙发

评论前必须登录!