Domanda

I am having some trouble with TestNG annotations, and I haven't found a good answer either on stackoverflow or in the testng documentation. What I'm trying to do is add a testng listener as well as parameters from a testng.xml file to a "test base" superclass. All testng tests will inherit the superclass. This will alleviate a lot of code redundancy in the testng test class files. But when I have the @Listeners and @Parameters annotation in the superclass, and not the class that contains the @Test method(s), the annotations do not work. In other words, the listener does not seem to "see" the tests, and the parameters from testng.xml do not get pulled in to the superclass during runtime.

My "test base" (the superclass) has a testng listener from the Sauce Labs api that will listen for tests and update the success/failure of the test to Sauce Labs during remote execution. It also uses the @Parameters annotation to pull parameters from the current test run's testng.xml.

TestBase superclass:

@Listeners(SauceOnDemandTestListener.class)
public class TestBase implements SauceOnDemandSessionIdProvider, SauceOnDemandAuthenticationProvider {
    private SauceOnDemandAuthentication authentication;
    private DesiredCapabilities capabilities;
    protected ParallelWebDriver parallelWebDriver;

    @Parameters({"sauce_username", "sauce_accesskey", "platform", "browser", "version"})
    @BeforeClass(alwaysRun = true)
    public void setUp(String userName, String accessKey, String platform, String browser, String version) {   
        // Set up Sauce Auth
        if (userName != null && accessKey != null) {
            this.authentication = new SauceOnDemandAuthentication(userName, accessKey);
        } else {
            this.authentication = new SauceOnDemandAuthentication();
        }

        // Set up the DesiredCapabilities
        if (platform != null) {
            this.capabilities.setCapability("platform", platform);
        } else {
            throw new NullArgumentException("[Parameter] platform does not exist or is not a valid value in testng.xml:");
        }

        if (browser != null) {
            this.capabilities.setCapability("browser", browser);
        } else {
            throw new NullArgumentException("[Parameter] browser does not exist or is not a valid value in testng.xml:");
        }

        if (version != null) {
            this.capabilities.setCapability("version", version);
        } else {
            throw new NullArgumentException("[Parameter] version does not exist or is not a valid value in testng.xml:");
        }

        // Set up the ParallelWebDriver for the test run
        parallelWebDriver = new ParallelWebDriver(new RemoteParallelDriver(), this.testingPlatform, capabilities);
        parallelWebDriver.setUserName(userName);
        parallelWebDriver.setAccessKey(accessKey);
    }

    @Override
    public String getSessionId() {
        SessionId sessionId = ((RemoteWebDriver)((WebDriver)parallelWebDriver.getDriver())).getSessionId();
        return (sessionId == null) ? null : sessionId.toString();
    }

    @Override
    public SauceOnDemandAuthentication getAuthentication() {
        return authentication;
    }
}

Here is an example test class that inherits the TestBase.

public class SauceLabsRemote_Test extends TestBase {
    @BeforeTest
    public void testSetUp() throws MalformedURLException {
        parallelWebDriver.openBrowser();
    }

    public void searchGoogle(String searchText) throws InterruptedException {
        parallelWebDriver.getDriver().get("https://google.com");
        WebElement searchBox = parallelWebDriver.getDriver().findElement(By.id("gbqfq"));
        searchBox.sendKeys(searchText);
        WebElement searchButton = parallelWebDriver.getDriver().findElement(By.id("gbqfb"));
        searchButton.click();

        Assert.assertEquals(searchBox.getText(), "banjo");
    }

    @Test
    public void searchGoogle_Test1() throws InterruptedException {
        searchGoogle("banjo");
    }

    @Test
    public void searchGoogle_Test2() throws InterruptedException {
        searchGoogle("guitar");
    }

    @AfterTest
    public void testTearDown() {
        parallelWebDriver.closeBrowser();
    }
}

And here is a mockup of my testng.xml.

<suite name="Base Framework Unit Test Suite" verbose="1" >   

    <!-- Parameters required for Sauce Labs run -->
    <parameter name="sauce_username" value="testuser" />
    <parameter name="sauce_accesskey" value="acc3-55k3y-t3st-t3st-t3st" />

    <test name="Sauce Labs Remote Execution Test" >
        <parameter name="platform" value="OS X 10.6" />
        <parameter name="browser" value="firefox" />
        <parameter name="version" value="26" />
        <classes>
            <class name="unittest.SauceLabsRemote_Test" />
        </classes>
    </test>

</suite>

So, is there any way to get TestNG's @Listeners and @Parameters to work on a superclass that does not contain @Test? Thanks in advance! And sorry for any bad coding practices; all this code was mocked up on-the-fly.

È stato utile?

Soluzione

@Listeners and @Parameters annotations in a superclass will be inherited in the subclass. I have tested this and verified that it works. So, like my code example, the @Listeners annotation used in my TestBase parent class listened for any @Test annotations for a child class that inherited TestBase.

The issue I was having was related to Sauce Labs test execution vs. Selenium Grid test execution vs. local test execution. I had to add logic to Sauce Lab's SauceOnDemandTestListener class to figure out if the test execution was indeed routing to Sauce Labs VM browser jobs. That logic is outside of the scope of my original question, so I won't post it here.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top