我正在使用硒(硒服务器独立2.47.1.jar)网格运行并行测试,该网格由Ant启动,由蚂蚁启动,并使用测试通知器适配器。屏幕截图是在侦听者的“测试失败”方法中拍摄的。问题在于,侦听器似乎对它应该使用哪个驱动程序感到困惑,有时会截取错误的浏览器窗口的屏幕截图,或者如果它认为应该使用的驱动程序已经退出,则完全失败。
当测试开始时,TestNg 的@BeforeTest和测试提示器的“onTestStart”方法在同一线程上运行,但是当测试失败时,测试提示程序的“onTestFailure”方法似乎在单独的线程上运行。似乎线程以某种方式交叉/共享,但我不知道为什么。
这里是一些框架代码,非常感谢您的帮助。
基础测试类:
public class baseClassTests{
protected AutomationUtils au;
protected DriverUtils du;
@BeforeTest(alwaysRun = true)
@Parameters({ "selenium.OS", "selenium.browser" })
public void beforeTest(String OS, String browser) {
//these call simple private methods to know where to set up the driver
String port = getPort(OS, browser);
String host = getHost(OS);
//make a driver utility object here, this makes a driver
du = new DriverUtils(browser, host, port);
//pass this driver utility object to another class of utilities
//this 'AutomationUtils' class gets a RemoteWebDriver ('driver') by calling driver=du.getDriver();
//the 'AutomationUtils' class is then the one that does all of the 'driver.findBy...' etc
au = new AutomationUtils(du);
}
@BeforeMethod(alwaysRun = true)
public void beforeMethod(Method m, ITestResult tr) {
du.deleteCookies();
testNgTestName = m.getName();
print("Method: "+testNgTestName + " Thread: "+Thread.currentThread().hashCode());
//set the attribute of the ITestResult object so we can use the same object in the listener
tr.setAttribute("du", du);
tr.setAttribute("au", au);
}
}
侦听器类
public class AmSimpleTestListener extends TestListenerAdapter {
private DriverUtils driveU;
private AutomationUtils AutoU;
private RemoteWebDriver driver;
private RemoteWebDriver augmentedDriver;
private String methodName;
private String browser;
private String browserVersion;
String testClass;
@Override
public void onTestStart(ITestResult tr) {
//pick up the correct driver utility object from the test class/method we are in
driveU = (DriverUtils) tr.getAttribute("du");
AutoU = (AutomationUtils) tr.getAttribute("au");
driver = du.getDriver();
augmentedDriver = (RemoteWebDriver) new Augmenter().augment(driver);
methodName = tr.getName();
testClass=tr.getTestClass(); //sort of, I actually parse it up a bit
browser = driveU.getBrowser();
browserVersion = driveU.getBrowserVersion();
print("Method: "+methodName + " Thread: "+Thread.currentThread().hashCode());
}
@Override
public void onTestFailure(ITestResult tr) {
print("Method: "+tr.getName() + " Thread: "+Thread.currentThread().hashCode());
try{
writeScreenshotFile();
}
catch (Exception e){
Out.error("Unable to take screen shot");
e.printStackTrace();
}
}
private String writeScreenshotFile() {
if (driver != null && driver.getSessionId() != null) {
File scrShot = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
File localPathToScreenShot = new File("/path/to/base/directory/"+testClass+"/"+methodName+".png");
try {
FileUtils.copyFile(scrShot, localPathToScreenShot);
} catch (Exception e) {
Out.error("Couldn't write screenshot to file");
}
return localPathToScreenShot.getAbsolutePath();
}
return "Could not get path.";
}
}
DriverUtils类生成/提供驱动程序
public class DriverUtils {
private RemoteWebDriver driver;
private int timeout;
private String browserVersion;
private String browser
private DesiredCapabilities caps;
public DriverUtils(String browser, String host, String port) {
String hostUrl = "http://" + host + ":" + port + "/wd/hub";
this.browser=browser;
//do some stuff here to set capabilties
driver = new RemoteWebDriver(new URL(hostUrl), caps);
browserVersion = driver.getCapabilities().getVersion();
}
public RemoteWebDriver getDriver() {
return driver;
}
public AmBrowser getBrowser() {
return browser;
}
public String getBrowserVersion() {
return browserVersion;
}
public void quitDriver() {
driver.quit();
}
public void deleteCookies(){
driver.manage().deleteAllCookies();
}
}
public class AutomationUtils extends BaseClassUtils {
public AutomationUtils(DriverUtils driverUtils) {
//pass it up to the base class utils (this is different than base class tests, above)
//do this so the driver can be accessed by other utility classes as well
super(driverUtils);
}
//All sorts of methods here to find elements, login, blah blah everything that is done with a driver object
}
public class BaseClassUtils { //this is a different class than BaseClassTests
//make the driver a protected object so all utility classes can access as nec.
protected final RemoteWebDriver driver;
public BaseClassUtils(DriverUtils driverUtils) {
driver = driverUtils.getDriver();
}
}
测试是通过ant运行的。
<suite name="Dev2 for debugging" parallel="tests" thread-count="10">-- tests here </suite>
尝试使用ThreadLocal for RemoteWebDriver,以便它可以处理并行运行:
public class DriverUtils {
private static ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<~>();
private int timeout;
private String browserVersion;
private String browser
private DesiredCapabilities caps;
public DriverUtils(String browser, String host, String port) {
String hostUrl = "http://" + host + ":" + port + "/wd/hub";
this.browser=browser;
//do some stuff here to set capabilties
driver.set(new RemoteWebDriver(new URL(hostUrl), caps));
browserVersion = getDriver().getCapabilities().getVersion();
}
public RemoteWebDriver getDriver() {
return driver.get();
}
public AmBrowser getBrowser() {
return browser;
}
public String getBrowserVersion() {
return browserVersion;
}
public void quitDriver() {
getDriver().quit();
}
public void deleteCookies(){
getDriver().manage().deleteAllCookies();
}
}
在修补了一段时间后,我得出结论,有两件事似乎很有帮助。
@AfterMethod
@前/后方法/测试方法
移动到子类中,但只需调用父类中的方法来完成所有工作。我注意到的另一件事是,对于#2,TestNG应该运行父< code>@Before方法,然后运行子< code>@Before方法;最后运行子“@After”方法,然后运行父< code>@After方法。< br >我运行了一系列简单的测试,发现所有的before/after方法都没有运行,所以对于在父级和子级中都使用< code>@Before和< code>@After方法的少数情况,我进行了合并。
现在事情似乎运行得更好了,驱动程序不会感到困惑,屏幕截图被附加到正确的浏览器/测试中。
我使用数据提供者方法和测试方法(测试方法中带有ITestContext参数)。一个简化的例子如下: 我的Retry类和RetryListener类如下: } 预期:当测试失败时,TestNG调用重试,然后数据提供程序应将相同的值返回给测试方法。 观察到:数据提供者返回相同的值,但测试方法没有运行,重试终止,下一个测试开始(数据提供者现在将返回新值) 但我的重试没有输入测试方法(测试方法不需要(in
我有一个测试类的testng套件,我正在通过一个testng.xml文件运行它。这个很管用。所有测试都是串行运行的,因此没有并行执行障碍。 当然,通过类成员变量在单个类中的测试方法之间共享状态是很容易的,但是我不知道如何在测试类之间共享状态。
Rails 程序测试指南 本文介绍 Rails 内建对测试的支持。 读完本文,你将学到: Rails 测试术语; 如何为程序编写单元测试,功能测试和集成测试; 常用的测试方法和插件; 1 为什么要为 Rails 程序编写测试? 在 Rails 中编写测试非常简单,生成模型和控制器时,已经生成了测试代码骨架。 即便是大范围重构后,只需运行测试就能确保实现了所需功能。 Rails 中的测试还可以模拟浏
我有一个Selenium项目,在本地机器上运行良好,但在Hudson运行时出现问题。问题是它不会在每次测试结束时关闭打开的驱动程序。 先决条件:此项目由Hudson在Selenium网格服务器上运行。(我也在Selenium网格服务器上的本地机器上运行了它,问题没有发生) 所以,我有一个由每个测试类实现的BeforeAndAfter类。 在BeforeAndAfter中,我有一个@BeforeCl
Vue CLI 提供了预配置的单元测试和 e2e 测试安装。 如果你有兴趣为 *.vue 文件手动设置单元测试,请查询 @vue/test-utils 的文档,这份文档涵盖了对 mocha-webpack 或 Jest 的设置。
类似问题:在Android Studio中的Android工具测试和单元测试之间共享代码 我的设置如下: 包含单元测试的< li> 文件夹。这些可以是Java或Kotlin类 包含仪器测试的< li> 。这些也可以是Java或Kotlin类 < li> 是一个文件夹,其中包含一组在单元测试和测量测试之间共享的实用程序。 这种共享在gradle中定义为: 这允许< code>src/test或< c