0

我目前正在研究 Runner 类的黄瓜自动化并行执行,我遇到了这个不错的框架http://comcast.github.io/zucchini/ ,我在并行运行我的 AndroidDriver 测试用例时遇到了一些问题。当我使用通过 pom 文件运行我的代码时,它显示所有两个测试都已在浏览器堆栈中开始,并且总是最新的一个完成并且前一个超时。这是我的代码。很高兴有人能提供帮助。

Pom 文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.dimaj</groupId>
    <artifactId>zucchini-sample</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Zucchini Sample Project</name>
    <description>A sample project that demonstrates how to use Zucchini against multiple web browsers</description>

    <contributors>
        <contributor>
            <name>Dmitry Jerusalimsky</name>
            <url>http://blog.dimaj.net</url>
        </contributor>
    </contributors>

    <properties>
        <cucumber.version>1.2.4</cucumber.version>
    </properties>

    <dependencies>


        <!-- https://mvnrepository.com/artifact/com.comcast.zucchini/zucchini -->
<dependency>
    <groupId>com.comcast.zucchini</groupId>
    <artifactId>zucchini</artifactId>
    <version>2.3.1</version>
</dependency>



        <!-- <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-firefox-driver</artifactId>
            <version>2.46.0</version>
            <scope>test</scope>
        </dependency> -->

        <dependency>
            <groupId>io.appium</groupId>
            <artifactId>java-client</artifactId>
            <version>5.0.4</version>
            <!--<exclusions>-->
            <!--<exclusion>-->
            <!--<groupId>com.google.guava</groupId>-->
            <!--<artifactId>guava</artifactId>-->
            <!--</exclusion>-->
            <!--</exclusions>-->
        </dependency>
          <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.0.1</version>
            <scope>test</scope>
        </dependency>

          <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-picocontainer</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

         <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.5</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/info.cukes/cucumber-testng -->
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-testng</artifactId>
            <version>${cucumber.version}</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                     <!--  <parallel>classes</parallel> -->
                      <threadCount>2</threadCount>
                        <reuserForks>false</reuserForks>
                        <includes>
                            <include>**/*Test.java</include>
                        </includes>
                    </configuration>

                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

跑步者类:

 package net.dimaj.zucchini.tests;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.comcast.zucchini.AbstractZucchiniTest;
import com.comcast.zucchini.TestContext;
import com.comcast.zucchini.ZucchiniOutput;

import cucumber.api.CucumberOptions;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import net.dimaj.zucchini.utils.Constants;

import org.openqa.selenium.remote.DesiredCapabilities;

@CucumberOptions(features = { "src/test/resources/StartPage.feature" }, glue = { "net.dimaj.zucchini.sample.glue" })
public class FirstZucchiniTest extends AbstractZucchiniTest {

    String USERNAME = "<>";
    String ACCESS_KEY = "<>";
    String url = "https://" + USERNAME + ":" + ACCESS_KEY + "@hub.browserstack.com/wd/hub";

      private TestContext createContext(String name, String device, String os) throws MalformedURLException {
          DesiredCapabilities caps = new DesiredCapabilities();
          caps.setCapability("device", device);
          caps.setCapability("os_version", os);
          caps.setCapability("deviceName", "Android Device");
          caps.setCapability("build", "Android_Browser Stack Pharellel");
          caps.setCapability("name", "Pharellel Testing");
          caps.setCapability("app", "bs://dlslldlfll");
          caps.setCapability("networkLogs", true);

          AndroidDriver<MobileElement> driver = new AndroidDriver<MobileElement>(new java.net.URL(url), caps);
          TestContext context = new TestContext(name);
          context.set(Constants.CONTEXT_ANDROID, driver);

          return context;
        }

        @Override
        public List<TestContext> getTestContexts() {
            List<TestContext> driverList = new ArrayList<TestContext>();
            try {
              driverList.add(createContext("Remote1", "Google Pixel", "7.1"));
              driverList.add(createContext("Remote2", "Google Nexus 6", "6.0"));
            }
            catch (MalformedURLException e) {
              throw new RuntimeException("Couldn't create driver", e);
            }

            return driverList;
        }

        @Before
        public void setupTests(Scenario scenario) {
            TestContext.getCurrent().set(Constants.CONTEXT_SCENARIO, scenario);
        }

        @Override
        public void cleanup(TestContext out) {
            AndroidDriver<MobileElement> driver = out.get(Constants.CONTEXT_ANDROID);
            if (null != driver) {
                driver.quit();
            }
        }

}

我的步骤定义类

 package net.dimaj.zucchini.sample.glue;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import com.comcast.zucchini.TestContext;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.When;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.pagefactory.AndroidBy;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.WithTimeout;
import io.appium.java_client.pagefactory.iOSFindBy;
import net.dimaj.zucchini.utils.Constants;

public class StartPageSteps{
    AppiumDriver<MobileElement> androidDriver;


    @AndroidFindBy(id = "intro_login")
    @WithTimeout(time = 5, unit = TimeUnit.SECONDS)
    private MobileElement logInButton;

    public StartPageSteps(){
        androidDriver = TestContext.getCurrent().get(Constants.CONTEXT_ANDROID);
    }

    @Before
    public void setup(Scenario scenario) {
        TestContext.getCurrent().set("scenario", scenario);
    }


    private By loginBtn = By.id("intro_login");

    @Given("Sign Up is displayed")
    public void sign_Up_is_displayed() {

        androidDriver.findElement(loginBtn).isDisplayed();

    }

    @When("user taps Sign Up button")
    public void user_taps_Sign_Up_button() {
        //androidDriver.findElement(loginBtn).click();
        assert(androidDriver.findElement(loginBtn).isDisplayed());
    }
}

这是我的日志:

    Session ID: ebed1cfaf948d20a2c715e39711b672e6feca130
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:214)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:166)
    at org.openqa.selenium.remote.http.JsonHttpResponseCodec.reconstructValue(JsonHttpResponseCodec.java:40)
    at org.openqa.selenium.remote.http.AbstractHttpResponseCodec.decode(AbstractHttpResponseCodec.java:82)
    at org.openqa.selenium.remote.http.AbstractHttpResponseCodec.decode(AbstractHttpResponseCodec.java:45)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:164)
    at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:89)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:586)
    at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:46)
    at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
    at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
    at io.appium.java_client.HasSessionDetails.getSessionDetails(HasSessionDetails.java:38)
    at io.appium.java_client.HasSessionDetails.getSessionDetail(HasSessionDetails.java:55)
    at io.appium.java_client.HasSessionDetails.getPlatformName(HasSessionDetails.java:62)
    at io.appium.java_client.DefaultGenericMobileDriver.toString(DefaultGenericMobileDriver.java:156)
    at io.appium.java_client.AppiumDriver.toString(AppiumDriver.java:1)
    at io.appium.java_client.android.AndroidDriver.toString(AndroidDriver.java:1)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractMap.toString(AbstractMap.java:559)
    at com.comcast.zucchini.TestContext.toString(TestContext.java:107)
    at com.comcast.zucchini.AbstractZucchiniTest.runParallel(AbstractZucchiniTest.java:181)
    at com.comcast.zucchini.AbstractZucchiniTest.run(AbstractZucchiniTest.java:129)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
    at org.testng.SuiteRunner.run(SuiteRunner.java:254)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:77)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:110)
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:106)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)

07:27:38.000 [Thread-1] WARN  c.c.zucchini.ZucchiniShutdownHook - There are 0 features run

Results :

Failed tests:   run(net.dimaj.zucchini.tests.FirstZucchiniTest): Session not started or terminated (WARNING: The server did not provide any stacktrace information)(..)

Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
4

1 回答 1

0

如果你改变你的会发生什么FirstZucchiniTest

package net.dimaj.zucchini.tests;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import com.comcast.zucchini.AbstractZucchiniTest;
import com.comcast.zucchini.TestContext;
import cucumber.api.CucumberOptions;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import net.dimaj.zucchini.utils.Constants;
import org.openqa.selenium.remote.DesiredCapabilities;

@CucumberOptions(features = { "src/test/resources/StartPage.feature" }, glue = { "net.dimaj.zucchini.sample.glue" })
public class FirstZucchiniTest extends AbstractZucchiniTest {

    String USERNAME = "<username>";
    String ACCESS_KEY = "<access key>";
    String url = "https://" + USERNAME + ":" + ACCESS_KEY + "@hub.browserstack.com/wd/hub";

    private TestContext createContext(String name, String device, String os) throws MalformedURLException {
      DesiredCapabilities caps = new DesiredCapabilities();
      caps.setCapability("device", device);
      caps.setCapability("os_version", os);
      caps.setCapability("deviceName", "Android Device");
      caps.setCapability("build", "Android_Browser Stack Pharellel");
      caps.setCapability("name", "Pharellel Testing");
      caps.setCapability("app", "bs://48da5beeef475d0c1716b7d2eaad3e18d2e8ebf8");
      caps.setCapability("networkLogs", true);

      AndroidDriver<MobileElement> driver = new AndroidDriver<MobileElement>(new java.net.URL(url), caps);
      TestContext context = new TestContext(name) {
         @Override
         public String toString() {
           return this.name;
         }
      };
      context.set(Constants.CONTEXT_ANDROID, driver);

      return context;
    }

    @Override
    public List<TestContext> getTestContexts() {
        List<TestContext> driverList = new ArrayList<TestContext>();
        try {
          driverList.add(createContext("Remote1", "Google Pixel", "7.1"));
          driverList.add(createContext("Remote2", "Google Nexus 6", "6.0"));
        }
        catch (MalformedURLException e) {
          throw new RuntimeException("Couldn't create driver", e);
        }

        return driverList;
    }

    @Before
    public void setupTests(Scenario scenario) {
        TestContext.getCurrent().set(Constants.CONTEXT_SCENARIO, scenario);
    }

    @Override
    public void cleanup(TestContext out) {
        AndroidDriver<MobileElement> driver = out.get(Constants.CONTEXT_ANDROID);
        if (null != driver) {
            driver.quit();
        }
    }

}

此处更改的主要内容是在 AndroidDriver 初始化失败时对异常的处理。

我的想法是,您的第二个驱动程序无法初始化,它被添加到 TestContext 作为null. 然后,当TestContext.toString()被调用时,它会调用已添加到 TestContexttoString()的所有内容,如果失败,则最终会出现异常。Object这是我的意思的一个例子:http: //tpcg.io/EonKtS

在上面更新的响应中,我重写了toString函数的定义以避免打印出当前上下文的内容。如果您仍然会失败,那么我会研究浏览器堆栈。

于 2019-04-23T19:15:14.407 回答