我会试着解释一下我是如何构建这个的,我想象一些明显的东西可能会跳出来。
我对此比较陌生,但我正在构建一个黄瓜-appium框架,并遇到了一些麻烦。目前,我在我的@Before钩子中初始化我的Appium驱动程序,该钩子位于包含所有Hook的GlobalHooks类中。我已经改变了钩子,所以它的一部分只在测试运行开始时运行,因为Cucumber不支持全局钩子,我不明白为什么我应该在每次测试之前初始化驱动程序(我使用Junit所以不能采取TestNG的@BeforeSuite功能的优势)。
为了利用Appium的并行会话,我现在想要使我的驱动程序(在GlobalHooks类中声明并在该类中的@Before方法中定义)非静态,并且它在整个套件中呈现问题。
如果我希望我的Page Classes使用这个驱动程序,那么在Hook中定义我的驱动程序是明智的吗?或者有没有人对如何初始化非静态驱动程序有任何建议,以便它们可用于运行并行的Appium会话?
这可能是关于Cucumber或Appium的Java问题。
这是一个并行使用selenium驱动程序的精简版本。应该类似于采用appium驱动程序。这使用pico-container在场景中创建和共享对象。需要添加cuc-picocontainer依赖。
DriverFactory
将所有驱动程序存储在ThreadLocal变量drivers
中。
public final class DriverFactory {
private static ThreadLocal<WebDriver> drivers = new ThreadLocal<>();
//To quit the drivers and browsers at the end only.
private static List<WebDriver> storedDrivers = new ArrayList<>();
static {
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
storedDrivers.stream().forEach(WebDriver::quit);
}
});
}
private DriverFactory() {}
public static WebDriver getDriver() {
return drivers.get();
}
public static void addDriver(WebDriver driver) {
storedDrivers.add(driver);
drivers.set(driver);
}
public static void removeDriver() {
storedDrivers.remove(drivers.get());
drivers.remove();
}
}
仅存在允许微型容器创建所需驱动程序的存在。检查驱动程序是否已存在以供重用的线程。为避免这种情况,您可以查看扩展ThreadLocal
类并设置initialValue()
方法。
public class SharedDriver {
public SharedDriver() {
if (DriverFactory.getDriver() == null) {
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver.exe");
DriverFactory.addDriver(new ChromeDriver());
}
}
}
public class GoogleHomePO extends LoadableComponent<GoogleHomePO>{
@FindBy(name="q")
private WebElement searchTextBox;
public GoogleHomePO() {
DriverFactory.getDriver().get("https://www.google.com/");
PageFactory.initElements(DriverFactory.getDriver(), this);
}
public void enterSearch(String search) {
searchTextBox.sendKeys(search);
}
}
需要将SharedDriver
类添加到项目中的任何一个步骤定义构造函数中。当黄瓜初始化每个场景的所有步骤和钩子类时,picocontainer将根据需要实例化驱动程序对象并将其存储在DriverFactory中。
public class StepDefinition {
private GoogleHomePO gmPO;
public StepDefinition(SharedDriver driver, GoogleHomePO gmPO) {
this.gmPO = gmPO;
}
@Given("Go to google page")
public void given() {
gmPO.get();
}
@When("Enter search {string}")
public void when(String search) {
gmPO.enterSearch(search);
}
}
功能文件1
Feature:
Scenario: First
Given Go to google page
When Enter search "From Feature One"
Scenario: First Again
Given Go to google page
When Enter search "From Feature One Again Again"
功能文件2
Feature:
Scenario: Second
Given Go to google page
When Enter search "From Feature Two"
POM设置
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
<configuration>
<includes>
<include>**/*Runner.java</include>
</includes>
<parallel>methods</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
@蚱蜢。回到你身边因为我说当我有适合我的设置的东西时我会的。再次感谢您的投入,这是非常宝贵的。我按照你的建议设置了一个SharedDriver类,但改变了一两件事,考虑到我将在不同的连接设备上运行每个线程,这意味着每次都是一个单独的AppiumDriver而不是一个新的WebDriver。
我通过放入我的BeforeClass方法解决了这个问题,这是一个用于创建我已连接的所有设备的池的类。我的SharedDriver然后使用AtomicIntecger迭代它们以保持线程安全并将相关的驱动程序添加到工厂。
我也喜欢在第一台连接设备上从IDE运行测试以进行调试和快速测试的想法。因为在IDE中运行时,BeforeClass不运行,所以我的SharedDriver类会检查它,如果它没有运行,那么它会为第一个连接的设备添加一个AppiumDriver,并在其上运行测试。
对于延迟回来感到抱歉,我从那时起就开始研究其他项目了。再次感谢您的帮助