我目前正在研究 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