Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call default method from interface with TestNG tests and Selenium?

I want to know if it is possible to use default methods from interface with TestNG @BeforeMethod annotation?

Here is sample, which I tried:

@Listeners(TestListener.class)
public interface ITestBase {
    String baseUrl = Config.getProperty(Config.TEST_HOST);
    String driverName = Config.getProperty(Config.BROWSER);
    DriversEnum driverInstance = DriversEnum.valueOf(driverName.toUpperCase());

    @BeforeMethod(alwaysRun = true)
    default public void start() {
        try {
            driver.init();
            DriverUnit.preconfigureDriver(Driver.driver.get());
            driver.get().manage().deleteAllCookies();
            driver.get().get(baseUrl);
        } catch (TimeoutException e) {
            Logger.logEnvironment("QT application is not available");
        }
    }

    @AfterMethod(alwaysRun = true)
    default public void end() {
        if (driver.get() != null) {
            try {
                driver.get().quit();
            } catch (UnreachableBrowserException e) {
                Logger.logDebug("UnreachableBrowser on close");
            } finally {
                driver.remove();
            }
        }
    }

When I run typical TestNG test method, like:

public class AppUiDemo implements ITestBase {
    @Test(enabled = true)
    public void checkWebDriverCreation() {
      ...
    }

start() and end() methods aren't called. Driver instance isn't created for test execution.

Is it possible to make something like it with default method and TestNG methods?

If I change the interface to a regular class, before and after methods are called (driver instance is created fine):

public class TestBase {
    protected final String baseUrl = Config.getProperty(Config.TEST_HOST);
    protected final String driverName = Config.getProperty(Config.BROWSER);
    protected final DriversEnum driverInstance = DriversEnum.valueOf(driverName.toUpperCase());

    @BeforeMethod(alwaysRun = true)
    public void start() {
    ....

The problem is that my test class is already extending another class:

public class MainTest extends ExecutionContext

Thus I can't extend TestBase.

Is it possible to use interface with any implementation for execution code before and after test methods?

like image 854
catch23 Avatar asked Nov 16 '17 19:11

catch23


1 Answers

Yes, it is possible but the version of TestNG that allow using interface methods in tests is not released yet. You need to download it from this repository.

If you use Maven you can specify additional repository in your pom.xml:

<repository>
    <id>testng</id>
    <name>testng</name>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>

And then add TestNG dependency:

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.11.1-SNAPSHOT</version>
</dependency>

Example:

package test;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class DummyTest implements ITest {

    @BeforeMethod
    public void beforeTest() {
        System.out.println("before from class");
    }

    @Test
    public void test1() {
        System.out.println("I am test1");
    }
}

and ITest interface

package test;

import org.testng.annotations.BeforeMethod;

public interface ITest {

    @BeforeMethod
    default void beforeDefaultInterface() {
        System.out.println("before from default interface method");
    }
    @BeforeMethod
    static void beforeStaticInterface() {
        System.out.println("before from static interface method");
    }
}

The output of the test above will be:

    before from default interface method
    before from static interface method
    before from class
    I am test1
like image 60
Mihail Avatar answered Nov 14 '22 21:11

Mihail