5

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?

catch23
  • 17,519
  • 42
  • 144
  • 217
  • I don't follow. I see some `static` methods in your interface, but not default methods. I also see non-`static`, non-`final` fields in your interface, so what gives? By "It doesn't work" do you mean "it doesn't compile"? Because no, it wouldn't. – John Bollinger Nov 16 '17 at 20:04
  • @JohnBollinger I fixed typo. I also tried static methods as well. – catch23 Nov 16 '17 at 20:09
  • @JohnBollinger You are wrong. I do. Also, `String baseUrl` is by default `public static final`. And type something like it isn't mandatory. To my mind, it is redundant and makes readability much more difficult. – catch23 Nov 16 '17 at 20:48

2 Answers2

5

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
catch23
  • 17,519
  • 42
  • 144
  • 217
Mihail
  • 241
  • 1
  • 6
  • excellent! I was wondering if this is still in progress on the TestNG side – Eugene Nov 16 '17 at 21:59
  • @Anton Could give more information how to take from a repository which you shared? I couldn't find `testng` there. – catch23 Nov 17 '17 at 08:46
  • Updated my answer with example for maven. The exact link where jar file can be found is https://oss.sonatype.org/content/repositories/snapshots/org/testng/testng/6.11.1-SNAPSHOT/ – Mihail Nov 17 '17 at 17:19
0

It is possible with TestNg version '6.14.2'

Alternative repo, no longer required.
I have not tried other versions.

user77115
  • 5,517
  • 6
  • 37
  • 40