testcontainers-junit5

How to "make friends" TestContainers Webdriver Containers and ParameterizedTest (JUnit5)


I have a problem with running @ParameterizedTest via TestContainers. @Test running via TestContainers, but as soon as I change to @ParameterizedTest, then everything starts running on my local Сhrome instance. In TestContainers's documentation I didn't find some information about @ParameterizedTest.

This is working:

import com.codeborne.selenide.WebDriverRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testcontainers.containers.BrowserWebDriverContainer;

import static com.codeborne.selenide.Condition.visible;
import static com.codeborne.selenide.Selenide.*;
import static conf.Configuration.BASE_URL;

public class Test {

    private final SelenideElement errorAuth = $(By.xpath(ErrorNotifications.ERROR_AUTH));
    @Rule
    public BrowserWebDriverContainer chrome =
            new BrowserWebDriverContainer()
                    .withCapabilities(new ChromeOptions());

    @Before
    public void setUp() {
        RemoteWebDriver driver = chrome.getWebDriver();
        WebDriverRunner.setWebDriver(driver);
    }

    @After
    public void tearDown() {
        WebDriverRunner.closeWebDriver();
    }

    @org.junit.Test
    public void search() {
        open(BASE_URL);
        new StartPage()
                .clickEnterButton()
                .enterLogin("var1")
                .enterPassword("password")
                .clickEnterButton();
        errorAuth.shouldBe(visible);
        sleep(1000);
    }
}

This isn't working:

import com.codeborne.selenide.WebDriverRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testcontainers.containers.BrowserWebDriverContainer;

import static com.codeborne.selenide.Condition.visible;
import static com.codeborne.selenide.Selenide.*;
import static conf.Configuration.BASE_URL;

public class Test {

    private final SelenideElement errorAuth = $(By.xpath(ErrorNotifications.ERROR_AUTH));
    @Rule
    public BrowserWebDriverContainer chrome =
            new BrowserWebDriverContainer()
                    .withCapabilities(new ChromeOptions());

    @Before
    public void setUp() {
        RemoteWebDriver driver = chrome.getWebDriver();
        WebDriverRunner.setWebDriver(driver);
    }

    @After
    public void tearDown() {
        WebDriverRunner.closeWebDriver();
    }

    @ParameterizedTest
    @CsvSource({"var1, var1", "var2, var2", "null, null"})
    public void search(String email, String password) {
        open(BASE_URL);
        new StartPage()
                .clickEnterButton()
                .enterLogin(email)
                .enterPassword(password)
                .clickEnterButton();
        errorAuth.shouldBe(visible);
        sleep(1000);
    }
}

Solution

  • You're mixing JUnit4 and JUnit5 annotations:

    // These are JUnit 4 classes
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Rule;
    
    // These are JUnit 5 classes
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.CsvSource;
    

    So when you run your tests with the @ParameterizedTest annotation in place you're using the JUnit 5 runtime which will ignore the JUnit 4 annotations (@Before, @After and @Rule).

    One way to make your parameterized test work is to replace the JUnit 4 annotations with appropriate JUnit 5 counterparts.

    For that to work you'll first need the Testcontainers JUnit 5 integration. E.g. as a Maven dependency:

    <dependency>
        <groupId>org.testcontainers</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>1.17.2</version>
        <scope>test</scope>
    </dependency>
    

    Then you:

    so your class would look something like this:

    @Testcontainers
    public class Test {
    
        ...
    
        @Container
        public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer()
                        .withCapabilities(new ChromeOptions());
    
        @BeforeEach
        public void setUp() {
            ...
        }
    
        @AfterEach
        public void tearDown() {
            ...
        }
    
        @ParameterizedTest
        @CsvSource({"var1, var1", "var2, var2", "null, null"})
        public void search(String email, String password) {
          ...
        }
    }