我在执行包含多个类的TestNG文件时遇到问题
我有一个启动appiumserver和webdriver的安装程序类。此方法使用@BeforeTest
进行注释我使用每个页面具有不同类的pageobject模型以及我的方案的不同类。
我的Scenarioclasses扩展了安装类。
当我执行SetupClass时,第一个类中的方法被执行得很好。但是从第二个类启动方法时失败,因为driver = null。
我可以通过让我的驱动程序保持静态来修复一个设备,但之后我再也无法执行并行测试了。
我也可以使用@BeforeClass作为我的安装方法修复它,但是为每个类启动一个新的webdriver。我不想要这个,因为我想在同一个云设备上执行我的测试。
有人知道如何解决这个问题或任何提示吗?
代码示例
这是我的testng文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite" parallel="tests" thread-count="2">
<test name="Device1">
<parameter name="device_id" value="ef13de46"/>
<parameter name="device_name" value="samsung"/>
<parameter name="platformVersion" value="6.0.1"/>
<parameter name="platformName" value="Android"/>
<classes>
<class name="scenarios.Activation">
<methods>
<include name="testActivationFlow"/>
</methods>
</class>
<class name="scenarios.MenuBeforeActivation"/>
</classes>
</test>
<test name="Device2">
<parameter name="device_id" value="ZX1G423C29"/>
<parameter name="device_name" value="Nexus"/>
<parameter name="platformVersion" value="7.0"/>
<parameter name="platformName" value="Android"/>
<classes>
<class name="scenarios.Activation">
<methods>
<include name="testActivationFlow"/>
</methods>
</class>
<class name="scenarios.MenuBeforeActivation"/>
</classes>
</test>
</suite>
&#13;
这是我的设置类:
package setup;
public class DriverInit
{
private String appiumServiceUrl;
public AppiumDriver driver;
public void startAppium()
{
final AppiumDriverLocalService service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingAnyFreePort());
service.start();
this.appiumServiceUrl = service.getUrl().toString();
}
public void DriverInit(final String device_id, final String device_name, final String platformVersion, final String platformName) throws Exception
{
final DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("app", System.getProperty("user.dir") + "/src/test/resources/app/" + "App.apk");
capabilities.setCapability("deviceName", device_name);
capabilities.setCapability("udid", device_id);
capabilities.setCapability("platformName", platformName);
capabilities.setCapability("platformVersion", platformVersion);
capabilities.setCapability("appPackage", "<packagename>");
capabilities.setCapability("appActivity", "<Appactivity>");
capabilities.setCapability("autoGrantPermissions", true);
//capabilities.setCapability("autoAcceptAlerts", true);
capabilities.setCapability("noReset", true);
capabilities.setCapability("fullReset", false);
this.driver = new AndroidDriver(new URL(this.appiumServiceUrl), capabilities);
}
@Test
@BeforeTest(alwaysRun = true)
@Parameters({"device_id", "device_name", "platformVersion", "platformName"})
public AppiumDriver setDriver(final String device_id, final String device_name, final String platformVersion, final String platformName) throws Exception
{
startAppium();
DriverInit(device_id, device_name, platformVersion, platformName);
this.driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
return this.driver;
}
public AppiumDriver getDriver()
{
return this.driver;
}
public void tearDown() throws Exception
{
this.driver.quit();
}
}
&#13;
我还有一个带有一些基本动作的基础类
public class Basis
{
public AppiumDriver driver;
public Basis(final AppiumDriver driver)
{
this.driver = driver;
}
...
}
&#13;
我在页面对象模型之后有一些页面类
public class NamePage extends Basis
{
public NamePage(final AppiumDriver driver)
{
super(driver);
}
By nameField = By.id("edittext_name");
By checkBox = By.id("checkbox_wallet_tac");
By text = By.id("textview_wallet_tac");
By buttonNext = By.id("button_next");
By buttonCancel = By.id("button_cancel");
public void enterName(final String strName)
{
this.driver.findElement(this.nameField).sendKeys(strName);
this.driver.hideKeyboard();
}
public void acceptTerms()
{
this.driver.findElement(this.checkBox).click();
}
public void confirmName()
{
this.driver.findElement(this.buttonNext).click();
}
}
&#13;
我有测试课程
public class Activation extends DriverInit
{
@Test
public void testActivationFlow() throws Exception
{
this.driver.resetApp();
new Basis(this.driver).swipeLeft();
new Basis(this.driver).swipeLeft();
new Basis(this.driver).swipeLeft();
new Basis(this.driver).swipeLeft();
new WelcomePage(this.driver).startActivation();
new NamePage(this.driver).enterName("Tester");
new NamePage(this.driver).acceptTerms();
new NamePage(this.driver).confirmName();
new PinCodePage(this.driver).setPinCode();
new PinHelper(this.driver).setPin();
Thread.sleep(10000);
}
}
public class MenuBeforeActivation extends DriverInit
{
@Test
public void testWhereCanIPay()
{
new MainMenuPage(this.driver).openMenu();
new MainMenuPage(this.driver).openWherePay();
//TODO Add assertions Webpage is opened (Title + Content)
}
@Test
public void testInfoMenu()
{
new MainMenuPage(this.driver).openMenu();
new MainMenuPage(this.driver).openInfo();
new InfoPage(this.driver).openFAQ();
//TODO Add assertions FAQ Webpage is opened
new Basis(this.driver).back();
new InfoPage(this.driver).openPrivacy();
// Add assertions Privacy Text is shown
new Basis(this.driver).back();
}
}
&#13;
Error log :
java.lang.NullPointerException
at pages.menuPages.MainMenuPage.openMenu(MainMenuPage.java:31)
at scenarios.MenuBeforeActivation.testWhereCanIPay(MenuBeforeActivation.java:21)
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:104)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:756)
at org.testng.TestRunner.run(TestRunner.java:610)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
at org.testng.SuiteRunner.access$000(SuiteRunner.java:39)
at org.testng.SuiteRunner$SuiteWorker.run(SuiteRunner.java:421)
at org.testng.internal.thread.ThreadUtil$2.call(ThreadUtil.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
答案 0 :(得分:0)
在开始第二堂课之前 - 检查司机是否可用。 - 检查第一个类是否正在调用tearDown()方法并进行清理。 驱动程序。 - 如果第二类独立于第一类,则在setup()方法之前初始化驱动程序。
要并行执行: - 设置xml文件以传递参数 - 从CLI传递参数。
答案 1 :(得分:0)
以下是使用TestNG解决此问题的方法
将初始化逻辑移动为
的一部分org.testng.ITestListener
- 如果您希望每<test>
个代码只执行一次设置(即,而不是使用@BeforeTest
)org.testng.ISuiteListener
- 如果您希望每<suite>
个代码只执行一次设置(即,而不是使用@BeforeSuite
)setAttribute()
方法将初始化数据保留为ITestContext
(此代表<test>
代码)或ISuite
的属性(此代表<suite>
1}}标签)。<listeners>
代码(或)@Listeners
注释(或)您可以在我的this博文中看到一些示例。
您可以从我的this博客中了解有关侦听器和布线的更多信息。
答案 2 :(得分:0)
尝试将@BeforeSuite用于DriverInit,这样它将在所有测试之前启动一次