java - 如果我通过 testng.xml 运行测试,则会出现 NullPointerException,但它一次可以正常工作

标签 java selenium testing automated-tests testng

序言:我是自动化测试新手

我有两个测试有问题,我尝试通过 testng.xml 作为一个套件运行。但如果我单独运行它们,它们会工作得很好。 这是我的代码: BasePage.java

public class BasePage {
    protected WebDriver driver;
    public BasePage(WebDriver driver) {
        this.driver = driver;
    }
}

BaseTest.java

public class BaseTest {
    private WebDriver driver;
    private final String chromeDriverPath = "src//main//resources//chromedriver.exe";
    private final String firefoxDriverPath = "src//main//resources//geckodriver.exe";

    public WebDriver getDriver() {
        return driver;
    }

    @BeforeTest
    @Parameters({"browser", "baseURL"})
    public void setUp(@Optional String browser, @Optional String baseURL) {
        driver = getBrowserType(browser);
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        driver.navigate().to(baseURL);
    }

    private WebDriver getBrowserType(String browserType) {
        if (driver == null ) {
            if (browserType.equalsIgnoreCase("firefox")) {
                 System.setProperty("webdriver.gecko.driver", firefoxDriverPath);
                 return  new FirefoxDriver();
            }
            else if (browserType.equalsIgnoreCase("chrome")) {
                System.setProperty("webdriver.chrome.driver", chromeDriverPath);
                return new ChromeDriver();
            }
        }
        return driver;
    }

    @AfterTest
    public void tearDown() {
        if (driver != null)
            driver.quit();
    }
}

HomePage.java

public class HomePage extends BasePage {

    public HomePage(WebDriver driver) {
        super(driver);
    }

    public boolean verifyHomePage() {
        return driver.getCurrentUrl().contains("url");
    }
}

NavigationMenuComponent.java

public class NavigationMenuComponent extends BasePage{

    public NavigationMenuComponent(WebDriver driver) {
        super(driver);
    }

    @FindBy(xpath = "//ul[@class='right']//a[contains(@href, '/about')]")
    private WebElement aboutLink;

    public void test() {
         aboutLink.click();
    }
}

HomePageTest.java

public class HomePageTest extends BaseTest {

    private HomePage homePage;

    @BeforeClass(alwaysRun = true)
    public void init() {
        homePage = PageFactory.initElements(getDriver(), HomePage.class);
    }

    @Test(groups = "home-page")
    public void verifyFirstPage() {
        Assert.assertTrue(homePage.verifyHomePage());
    }
    }

NavigationMenuTest.java

public class NavigationMenuTest extends BaseTest{

    private NavigationMenuComponent navigationMenuComponent;

    @BeforeClass
    public void init() {
        navigationMenuComponent = PageFactory.initElements(getDriver(), NavigationMenuComponent.class);
    }

    @Test(groups = "about-page")
    public void verifyAboutLink() {
       navigationMenuComponent.test();
    }
}

还有我的testng.xml

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="suite" parallel="tests" thread-count="2">
    <parameter name="baseURL" value="https://www.foodpanda.com/"></parameter>
    <test name="chromeTest" >
        <parameter name="browser" value="chrome"></parameter>
        <classes>
            <class name="tests.HomePageTest"></class>
            <class name="tests.NavigationMenuTest"></class>
        </classes>
    </test>
    <test name="firefoxTest">
        <parameter name="browser" value="firefox"></parameter>
        <classes>
            <class name="tests.HomePageTest"></class>
            <class name="tests.NavigationMenuTest"></class>
        </classes>
    </test>
</suite>

这是堆栈跟踪

java.lang.NullPointerException
    at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:69)
    at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
    at com.sun.proxy.$Proxy9.click(Unknown Source)
    at utils.NavigationMenuComponent.test(NavigationMenuComponent.java:36)
    at tests.NavigationMenuTest.verifyAboutLink(NavigationMenuTest.java:25)
    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:497)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    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:334)
    at org.testng.SuiteRunner.access$000(SuiteRunner.java:37)
    at org.testng.SuiteRunner$SuiteWorker.run(SuiteRunner.java:368)
    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)

我被困在这个问题上了。我应该单独运行它们还是我做错了?

最佳答案

问题在于您如何初始化 webdriver 实例。下面的代码片段

@BeforeTest
@Parameters({"browser", "baseURL"})
public void setUp(@Optional String browser, @Optional String baseURL) {
    driver = getBrowserType(browser);
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
    driver.manage().window().maximize();
    driver.navigate().to(baseURL);
}

导致setUp每个 <test> 只调用一次方法标记,因为它是两个测试类的公共(public)基类的一部分。

因此,如果您的 <test> 中有两个测试类标签如

<test name="chromeTest" >
    <parameter name="browser" value="chrome"></parameter>
    <classes>
        <class name="tests.HomePageTest"></class>
        <class name="tests.NavigationMenuTest"></class>
    </classes>
</test>

然后是 setUp方法只会为 HomePageTest 调用并在执行 NavigationMenuTest 时被跳过

这就解释了为什么您会看到 NullPointerException <test> 中的第二个测试类标签。您可能需要通过注释 setUp 来更改它使用 @BeforeClass 的方法而不是 @BeforeTest

关于java - 如果我通过 testng.xml 运行测试,则会出现 NullPointerException,但它一次可以正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44873168/

相关文章:

c# - 如何使用 Selenium WebDriver 滚动到元素

testing - 哪个目录放模拟?

ruby - 我可以在 Ruby 中 stub "raise"吗?

java - getString() 在扩展应用程序的类中导致空指针引用

java - 为什么在尝试访问类时会生成 java.lang.IllegalStateException?

java - 当我的 Java 小程序在较旧的 Java 版本上运行但使用新类时会发生什么情况?

django - 如何测试模型方法django

java - 编译错误 "Sample1.java:1: error: class, interface, or enum expected Import java.util.Scanner;"

python - 无法从我的脚本中消除硬编码延迟以获得准确的结果

testing - Protractor 预期条件 visibilityOf() 在未显示元素时返回 true