Does TestNG test @BeforeSuite methods before @BeforeTest methods?

BACKGROUND: My goal is to encode the TestNG-Selenium system, which works autonomously (no lines for maven or ant plugins, just java). It should allow test cases to accept parameters, including the browser and domain URL. When the TestRunner instance these test cases, the browser and domain are used to get the Selenium object to perform this test.

PROBLEM: only one test class for each package successfully receives a domain parameter (in @BeforeSuite) before trying to get a Selenium object (in @BeforeTest). Test classes that do not receive a domain have a null selenium b / c object, which it cannot be created.

CODE: XmlClasses are each contained in its own XmlTest, and all three are in the same XmlSuite. The set contains, in order, TestClass1, TestClass2, then TestClass3. The tests themselves are subclasses of 2 layers of abstract base classes, which include functionality to initialize the entered variables and then get an instance of Selena. The goal of this is to test one or more applications (on multiple domains) with minimal repetitive code (for example: a Selenium instance in the root base class, because it is common to all tests). See Methods below for details.

// Top-most custom base class abstract public class WebAppTestBase extends SeleneseTestBase { private static Logger logger = Logger.getLogger(WebAppTestBase.class); protected static Selenium selenium = null; protected String domain = null; protected String browser = null; @BeforeTest(alwaysRun = true) @Parameters({ "selenium.browser" }) public void setupTest(String browser) { this.browser = browser; logger.debug(this.getClass().getName() + " acquiring Selenium instance ('" + this.browser + " : " + domain + "')."); selenium = new DefaultSelenium("localhost", 4444, browser, domain); selenium.start(); } } // Second level base class. public abstract class App1TestBase extends WebAppTestBase { @BeforeSuite(alwaysRun = true) @Parameters({"app1.domain" }) public void setupSelenium(String domain) { // This should execute for each test case prior to instantiating any Selenium objects in @BeforeTest logger.debug(this.getClass().getName() + " starting selenium on domain '" + domain+ "'."); this.domain = domain; } } // Leaf level test class public class TestClass1 extends App1TestBase { @Test public void validateFunctionality() throws Exception { // Code for tests go here... } } // Leaf level test class public class TestClass2 extends App1TestBase { @Test public void validateFunctionality() throws Exception { selenium.isElementPresent( ... // Rest of code for tests go here... // .... } } // Leaf level test class public class TestClass3 extends App1TestBase { @Test public void validateFunctionality() throws Exception { // Code for tests go here... } } 

OUTPUT: TestCase3 is working correctly. TestCase1 and TestCase2 fail. A stack trace is generated ...

  10:08:23 [DEBUG RunTestCommand.java:63] - Running Tests. 10:08:23 [Parser] Running: Command line suite Command line suite [DEBUG App1TestBase.java:49] - TestClass3 starting selenium on domain 'http://localhost:8080'. 10:08:24 [DEBUG WebAppTestBase.java:46] - TestClass2 acquiring Selenium instance ('*firefox : null'). 10:08:24 [ERROR SeleniumCoreCommand.java:40] - Exception running 'isElementPresent 'command on session null 10:08:24 java.lang.NullPointerException: sessionId should not be null; has this session been started yet? at org.openqa.selenium.server.FrameGroupCommandQueueSet.getQueueSet(FrameGroupCommandQueueSet.java:216) at org.openqa.selenium.server.commands.SeleniumCoreCommand.execute(SeleniumCoreCommand.java:34) at org.openqa.selenium.server.SeleniumDriverResourceHandler.doCommand(SeleniumDriverResourceHandler.java:562) at org.openqa.selenium.server.SeleniumDriverResourceHandler.handleCommandRequest(SeleniumDriverResourceHandler.java:370) at org.openqa.selenium.server.SeleniumDriverResourceHandler.handle(SeleniumDriverResourceHandler.java:129) at org.openqa.jetty.http.HttpContext.handle(HttpContext.java:1530) at org.openqa.jetty.http.HttpContext.handle(HttpContext.java:1482) at org.openqa.jetty.http.HttpServer.service(HttpServer.java:909) at org.openqa.jetty.http.HttpConnection.service(HttpConnection.java:820) at org.openqa.jetty.http.HttpConnection.handleNext(HttpConnection.java:986) at org.openqa.jetty.http.HttpConnection.handle(HttpConnection.java:837) at org.openqa.jetty.http.SocketListener.handleConnection(SocketListener.java:245) at org.openqa.jetty.util.ThreadedServer.handle(ThreadedServer.java:357) at org.openqa.jetty.util.ThreadPool$PoolThread.run(ThreadPool.java:534) 

I appreciate any information you can get on this issue.

+4
source share
1 answer

I think the problem is that your @BeforeSuite method assigns a value to the field, but you have three different instances, so the other two are never initialized.

Remember that @BeforeSuite only starts once, no matter what class it belongs to. Thus, @ Before / AfterSuite methods are usually defined in classes that are outside the entire test environment. These methods should be really static, but I decided not to apply this requirement because it is sometimes impractical.

I think the best way to get closer to your problem is to look at your domain field as an embedded resource that each of your tests will receive from Guice or another dependency injection infrastructure.

+8
source

All Articles