Cucumber-Appium-如果在@Before中初始化驱动程序,则在哪里存储Hooks

时间:2019-03-20 17:21:13

标签: java cucumber appium cucumber-jvm

我将尝试解释我是如何构建的,我想可能会出现一些明显的问题。

对此我还比较陌生,但我正在建立一个黄瓜-鸦片框架,并遇到了一些麻烦。目前,我在@Before挂钩中初始化Appium驱动程序,该挂钩位于GlobalHooks类中,该类包含所有挂钩。我已经更改了挂钩,因此它的一部分仅在测试运行开始时运行,因为Cucumber不支持全局挂钩,而且我不明白为什么要在每次测试之前初始化驱动程序(我使用的是Junit,所以不能TestNG的@BeforeSuite功能的优势)。

要利用Appium的并行会话,我现在想使我的驱动程序(在GlobalHooks类中声明,并在该类的@Before方法中定义)处于非静态状态,并在整个套件中提出问题。

如果我希望我的页面类使用此驱动程序,在这样的Hook中定义驱动程序是否明智?还是有人对如何初始化非静态驱动程序有任何建议,以便可以使用它们运行并行的Appium会话?

这可能是Java问题,而不是有关Cucumber或Appium。

2 个答案:

答案 0 :(得分:1)

这是并行使用硒驱动程序的简化版本。对appium驱动程序应采用类似的方法。这将使用pico容器在场景之间创建对象和共享。需要添加黄瓜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();
    }   
}

仅存在以允许pico容器创建所需的驱动程序。检查驱动程序是否已经存在以供线程重用。为避免这种情况,您可以查看扩展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类需要添加到项目中的任何一步定义构造函数中。当黄瓜初始化每个场景的所有step和hook类时,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>

答案 1 :(得分:0)

@Grasshopper。回到您身边,是因为我说过在我有适合自己的设置的时候会选择。再次感谢您的输入,它非常宝贵。我按照您的建议设置了SharedDriver类,但更改了一两件事,以考虑到我将在不同的连接设备上运行每个线程,这意味着每次使用一个单独的AppiumDriver而不是一个新的WebDriver。

我通过放入BeforeClass方法解决了这个问题,该方法是一个类,用于创建一个我已连接的所有设备的池。然后,我的SharedDriver使用AtomicIntecger遍历它们,以保持线程安全,并将相关的驱动程序添加到工厂。

我还喜欢在第一个连接的设备上从IDE运行测试以进行调试和快速测试的想法。因为从IDE中运行之前,BeforeClass不能运行,所以我的SharedDriver类会对此进行检查,如果尚未运行,则会为第一个连接的设备添加一个AppiumDriver,然后在该设备上运行测试。

很抱歉延迟回来,此后我一直在从事其他工作。再次感谢您的帮助