代码之家  ›  专栏  ›  技术社区  ›  J91

使用TestNg和Maven的Selenium WebDriver中的NullPointerException

  •  0
  • J91  · 技术社区  · 6 年前

    我目前正在构建一个Maven项目,该项目还包括Eclipse中的TestNg库。我正在使用最新的Selenium版本3.8.1运行Java 8(我听说这导致了其他人的问题,所以从Java 9切换过来)。我的项目工作顺利,没有任何问题,测试运行得很好,然后开始抛出 NullPointerException s、 我再次尝试建造这个项目,但没有成功。

    这是我的设置:

    下面是我使用的TestBase类 @BeforeSuite @AfterSuite 实例化WebDriver。这将毫无问题地启动。

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Properties;
    
    import org.apache.log4j.Logger;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.ie.InternetExplorerDriver;
    import org.openqa.selenium.remote.DesiredCapabilities;
    import org.testng.annotations.AfterSuite;
    import org.testng.annotations.BeforeSuite;
    
    public class TestBaseMaven {
    
        public WebDriver driver;
        public static FileInputStream fis;
        public static FileInputStream fis1;
        public static Properties config = new Properties();
        public static Properties OR = new Properties();
        public static Logger log;
    
        @BeforeSuite
        public void setUp() throws IOException, InterruptedException {
            fis = new FileInputStream("C:\\Users\\Kohout\\eclipse-workspace\\MavenProjects\\MavenProject2\\src\\test\\resources\\properties\\Config.properties");
            config.load(fis);
            fis1 = new FileInputStream("C:\\Users\\Kohout\\eclipse-workspace\\MavenProjects\\MavenProject2\\src\\test\\resources\\properties\\OR.properties");
            OR.load(fis1);
    
            if(driver==null) {
                if(config.getProperty("browser").equals("chrome")) {
                    System.setProperty("webdriver.chrome.driver", "C:\\Users\\Kohout\\eclipse-workspace\\MavenProjects\\MavenProject2\\src\\test\\resources\\executables\\chromedriver.exe");
                    driver = new ChromeDriver();
                } else if(config.getProperty("browser").equals("firefox")) {
                    System.setProperty("webdriver.gecko.driver", "C:\\Users\\Kohout\\eclipse-workspace\\MavenProjects\\MavenProject2\\src\\test\\resources\\executables\\geckodriver.exe");
                    DesiredCapabilities dc = DesiredCapabilities.firefox();
                    dc.setCapability("marionette", true);
                    driver=new FirefoxDriver();
                } else if(config.getProperty("browser").equals("ie")) {
                    System.setProperty("webdriver.ie.driver", "C:\\Users\\Kohout\\eclipse-workspace\\MavenProjects\\MavenProject2\\src\\test\\resources\\executables\\IEDriverServer.exe");
                    driver = new InternetExplorerDriver();
                }
            }
    
            driver.get(config.getProperty("testUrl"));
            driver.manage().window().maximize();
            Thread.sleep(2000);
        }
    
        public boolean isElementPresent(By by) {
            try {
                driver.findElement(by);
                return true;
            } catch(Throwable t) {
                return false;
            }
        }
    
        @AfterSuite
        public void tearDown() {
            if(driver!=null) {
                driver.quit();
            }
        }
    }
    

    这是我的第一次测试,它也运行良好,正在通过。虽然有时这也会引发 空指针异常 我使用的位置 Webdriver ,例如在中 driver.findElement ...

    import org.openqa.selenium.By;
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    import com.kohout.base.TestBaseMaven;
    
    public class ManagerLoginTest extends TestBaseMaven {
    
        @Test
        public void managerLoginTest() throws InterruptedException {
            driver.findElement(By.cssSelector(config.getProperty("managerLogin"))).click();
            Thread.sleep(2000);
            Assert.assertTrue(isElementPresent(By.cssSelector(OR.getProperty("addCust"))));
        }
    
    }
    

    这是我的第二次测试。不管什么原因,这个总是 空指针异常 每当我使用实例化的驱动程序变量(在 @BeforeSuite之前 ).

    import org.openqa.selenium.By;
    import org.openqa.selenium.WebElement;
    import org.testng.annotations.Test;
    
    import com.kohout.base.TestBaseMaven;
    
    public class AddCustomerTest extends TestBaseMaven {
    
        @Test
        public void addCustomerTest() {
             driver.findElement(By.xpath("/html/body/div[3]/div/div[2]/div/div[1]/button[1]"));
        }
    
    }
    

    这是我的堆栈跟踪:

    java.lang.NullPointerException
    at com.kohout.testcases.AddCustomerTest.addCustomerTest(AddCustomerTest.java:14)
    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:124)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:571)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:707)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:979)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
    at org.testng.TestRunner.privateRun(TestRunner.java:648)
    at org.testng.TestRunner.run(TestRunner.java:505)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1187)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1116)
    at org.testng.TestNG.runSuites(TestNG.java:1028)
    at org.testng.TestNG.run(TestNG.java:996)
    at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
    

    我还想包括我的testng。xml,我也在pom中调用它。xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Bank Suite">     
      <test name="Login Test">
        <classes>
          <class name="com.kohout.testcases.ManagerLoginTest"/>
          <class name="com.kohout.testcases.AddCustomerTest"/>
        </classes>     
      </test> <!-- Test -->    
    </suite> <!-- Suite -->
    

    这是我的POM。xml也是:

    <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>com.kohout</groupId>
        <artifactId>MavenProject2</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    
    
        <dependencies>        
            <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
            <dependency>
                <groupId>org.seleniumhq.selenium</groupId>
                <artifactId>selenium-java</artifactId>
                <version>3.8.1</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.testng/testng -->
            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>6.13.1</version>
                <scope>test</scope>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml-schemas</artifactId>
                <version>3.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans -->
            <dependency>
                <groupId>org.apache.xmlbeans</groupId>
                <artifactId>xmlbeans</artifactId>
                <version>2.6.0</version>
            </dependency>
    
        </dependencies>
    
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>2.20.1</version>
                        <configuration>
                            <suiteXmlFiles>
                                <suitXmlFile>C:\Users\Kohout\eclipse-workspace\MavenProjects\MavenProject2\testng.xml</suitXmlFile>
                            </suiteXmlFiles>
                        </configuration>
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    
    </project>
    

    谢谢你的时间和帮助。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Krishnan Mahadevan    6 年前

    问题出在测试代码中。您正在使用 @BeforeSuite 基类中的注释来初始化 WebDriver 例子

    TestNG执行 @BeforeSuite之前 每个仅一次带注释的方法 <suite> 标签 两个测试类都有相同的基类,因此初始化方法 setUp() 仅为测试类调用 com.kohout.testcases.ManagerLoginTest 而且不会被要求 com.kohout.testcases.AddCustomerTest .

    请将其更改为开始使用 @BeforeClass (或) @BeforeMethod 如果测试类只有一个注释 @Test 方法

    如果您的测试类有多个 @测试 方法,那么您基本上应该使用 ThreadLocal 变体(或)您应该使用TestNG侦听器初始化webdriver,然后查询webdriver实例。

    你可以参考我的博客帖子 here 了解如何使用TestNG侦听器以促进并行执行。

    下面的示例显示了线程本地变量的外观

    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.ie.InternetExplorerDriver;
    import org.openqa.selenium.remote.DesiredCapabilities;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.BeforeMethod;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.Properties;
    import java.util.logging.Logger;
    
    public class TestBaseMavenRefactored {
    
        private static final String PREFIX = "C:\\Users\\Kohout\\eclipse-workspace\\MavenProjects\\MavenProject2";
    
        private static final ThreadLocal<WebDriver> driver = new ThreadLocal<>();
        private Properties config = new Properties();
        private Properties OR = new Properties();
        public static Logger log;
    
        protected WebDriver getDriver() {
            return driver.get();
        }
    
        protected Properties getConfig() {
            return config;
        }
    
        public Properties getOR() {
            return OR;
        }
    
        private void cleanupDriver() {
            driver.get().quit();
            driver.remove();
        }
    
        @BeforeMethod
        public void setUp() throws IOException, InterruptedException {
            FileInputStream fis = new FileInputStream(PREFIX + "\\src\\test\\resources\\properties\\Config.properties");
            config.load(fis);
    
            FileInputStream fis1 = new FileInputStream(PREFIX + "\\src\\test\\resources\\properties\\OR.properties");
            OR.load(fis1);
    
            switch (config.getProperty("browser")) {
                case "chrome":
                    System.setProperty("webdriver.chrome.driver", PREFIX + "\\src\\test\\resources\\executables\\chromedriver.exe");
                    driver.set(new ChromeDriver());
                    break;
    
                case "firefox":
                    System.setProperty("webdriver.gecko.driver", PREFIX + "\\src\\test\\resources\\executables\\geckodriver.exe");
                    DesiredCapabilities dc = DesiredCapabilities.firefox();
                    dc.setCapability("marionette", true);
                    driver.set(new FirefoxDriver());
                    break;
    
                case "ie":
                    System.setProperty("webdriver.ie.driver", PREFIX + "\\src\\test\\resources\\executables\\IEDriverServer.exe");
                    driver.set(new InternetExplorerDriver());
                    break;
            }
            getDriver().get(config.getProperty("testUrl"));
            getDriver().manage().window().maximize();
            Thread.sleep(2000);
        }
    
        public boolean isElementPresent(By by) {
            try {
                getDriver().findElement(by);
                return true;
            } catch (Throwable t) {
                return false;
            }
        }
    
        @AfterMethod
        public void tearDown() {
            cleanupDriver();
        }
    }
    

    下面是重构测试类现在的样子:

    import org.openqa.selenium.By;
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    public class ManagerLoginTest extends TestBaseMavenRefactored {
        @Test
        public void managerLoginTest() throws InterruptedException {
            getDriver().findElement(By.cssSelector(getConfig().getProperty("managerLogin"))).click();
            Thread.sleep(2000);
            Assert.assertTrue(isElementPresent(By.cssSelector(getOR().getProperty("addCust"))));
        }
    }