Search code examples
javaselenium-webdriverkaratewebdrivermanager-javaselenium-jupiter

How can selenium-jupiter be used with Karate to automatically use the WebDriver matching the currently installed Chrome/Firefox etc.?


Background

Selenium-Jupiter is a JUnit 5 extension aimed to ease the use of Selenium WebDriver by downloading and caching the WebDriver binaries required for each test, depending on which locally installed web browser is to be used. It does this by wrapping WebDriverManager (which is actually for JUnit 4 tests only).

Issue

The use of the desired WebDriver is done (according to the instructions in the docs) by passing it when calling the test method in the test class. In fact, Karate can successfully launch a Chrome instance in this way, but before reaching the driver keyword in the corresponding feature file:

@ExtendWith(SeleniumJupiter.class)
public class KarateTest {
    @Test
    public void test(ChromeDriver driver) {        
        Results results = Runner.path("classpath:feature")
        generateReport(results.getReportDir());
        assertEquals(0, results.getFailCount(), results.getErrorMessages());
    }
}

Unfortunately, I can't get Karate to access and control this browser window using the driver keyword in my feature file. Is it possible to somehow use the browser instance managed by Selenium-Jupiter in Karate?

Note: I have already read this thread, which only assumed that it should be easy to use the WebDriverManager with Karate without investigating this. But apparently then you would at least have to downgrade to Junit 4. But even after that I don't understand how Karate could be able to take over the browser instance already started by WebDriverManager.

EDIT:

Thanks to @Peter, who led me on the right track!

I have now actually used the WebDriverManager (and not Selenium-Jupiter) to execute only the ChromeDriver-Setup in the test class and to transfer the executable path determined in this way into the system property which I use in my karate-config.js:

in my Java test class:

    @BeforeAll
    public static void setupClass() {
        WebDriverManager.chromedriver().setup();
        System.setProperty("driverExecutable", System.getProperty("webdriver.chrome.driver"));
    }

in karate-config.js:

  let env = karate.env; // get system property 'karate.env'
  let driverType = karate.properties['driverType']; // get system property 'driverType' optionally given on command line by "-DdriverType=..."
  let driverExecutable = karate.properties['driverExecutable']; // get system property 'driverExecutable' optionally given on command line by "-DdriverExecutable=..."


  if (env == 'win64-java-chrome-headful') {
    karate.configure(
      'driver', {
        type: driverType,
        executable: driverExecutable,
        showDriverLog: true
      }
    );
  }

With Selenium-Jupiter this does not seem to be possible, because there setup and starting of the WebDriver instance happens in one go.


Solution

  • Karate is certainly not designed for this, so let me get that out of the way first. You are on your own. Anyone is welcome to contribute code though to "improve" Karate, subject to review.

    And the driver you see in Karate has nothing to do with "WebDriver" at all. Keep in mind Karate gives you an abstraction over WebDriver - and then Playwright and Chrome (native) CDP as well. And the main reason why we don't recommend mixing a WebDriver into a Karate test is because it may be fine for a single-threaded test, but you will run into trouble if you want to run tests in parallel. The thread you linked already has links to all the gory details. And that thread says that you can (possibly) use WebDriverManager to set up the executable for a Karate test, not the actual Java WebDriver instance.

    That said, Karate has excellent Java interop, so I am sure you will be able to get a WebDriver instance into a Karate test like this:

    * def browser = MyJavaClass.someStaticMethod()
    

    And then you can do pretty much what you want and more. Any Java method can be called once you figure it out.

    For completeness, let me mention that Karate has a Java API also: https://github.com/intuit/karate#java-api