Selenium 4 no longer loading Firefox Driver - selenium

After updating a Java application based on Selenium to version 4, I found code packaged as an UberJar failed with the error:
Driver info: driver.version: FirefoxDriver
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at org.openqa.selenium.firefox.FirefoxDriver.toExecutor(FirefoxDriver.java:230)
at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:186)
at com.octopus.decorators.FirefoxDecorator.init(FirefoxDecorator.java:72)
Interestingly all tests passed though. How can I fix this?

The issue was because my application was packaged as an UberJAR with the Shade plugin. Selenium 4 must use a different service for locating dependencies based on service lookup, which requires META-INF/service files.
My configuration for building the UberJAR did not correctly capture these service files. The solution was to add the ServicesResourceTransformer to my Shade plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${shade.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</plugin>

Related

Unable to run JUnit 4 tests successfully when using Jacoco

We have recently upgraded our project to JDK 11 and have noticed that Surefire no longer generates the .exec file for Jacoco. Casting around for a solution, we modifier our Maven POM file to pick up the arg from Jacoco and give it to Surefire, as shown below:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<!-- gets the aguament from here -->
<configuration>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<outputDirectory>./codeCoverage/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7</version>
<configuration>
<!-- and uses it here -->
<argLine>
${surefireArgLine}
-Xmx1024m
-javaagent:"${settings.localRepository}"/org/jmockit/jmockit/1.9/jmockit-1.9.jar
--add-reads java.base=java.logging
--add-reads java.xml=java.logging
</argLine>
</configuration>
</plugin>
Now, although the .exec is produced for Jacoco, the unit tests fail with the following:
java.lang.ArrayIndexOutOfBoundsException: Index 110 out of bounds for length 110
      at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
      at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
      at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
      at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
      at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
      at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
We've tried upgarding various parts (JMockit to 1.23, Surefire to 2.22.2), but to no avail: they produce variations on the above.
Has anyone come across a similar situation and have any useful suggestions? It all worked fine under JDK 1.8
Update: and surefireArgLine gets set to
[INFO] --- jacoco-maven-plugin:0.8.3:prepare-agent (coverage-initialize) ---
[INFO] surefireArgLine set to -javaagent:.m2/repository/org/jacoco/org.jacoco.agent/0.8.3/org.jacoco.agent-0.8.3-runtime.jar=destfile=/target/jacoco.exec
And I figured out a solution.
Firstly, as above, add the parameter to allow Jacoco to add an argument to the argLine of Surefire.
Then make sure this is the line after the javaagent parameter for JMockit (otherwise, this blocks the JMockit line and you get an error saying that JMockit requires JDB 6+):
<argLine>
-Xmx1024m
-javaagent:"${settings.localRepository}"/org/jmockit/jmockit/1.9/jmockit-1.9.jar
${surefireArgLine}
--add-reads java.base=java.logging
--add-reads java.xml=java.logging
</argLine>
Finally, make sure that Jacoco is version 0.8.3, as there is a problem with 0.8.4 (called the "condy" problem) See GitHub issue comment

Selenium - Maven - Can Selenium configuration be changed to detect browser version and download webdriver automatically?

I have to automate the test cases run confugration in maven. Downloading the appopriate Chrome or Firefox webdriver is also one part of it.
In the pom.xml under the build tag
<plugin>
<groupId>com.github.webdriverextensions</groupId>
<artifactId>webdriverextensions-maven-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<goals>
<goal>install-drivers</goal>
</goals>
</execution>
</executions>
<configuration>
<installationDirectory>${testbench.driver.path}/drivers</installationDirectory>
<drivers>
<driver>
<name>geckodriver</name>
<platform>windows</platform>
<version>0.29.0</version>
</driver>
<driver>
<name>chromedriver</name>
<platform>windows</platform>
<version>90.0.4430.24</version>
</driver>
</drivers>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.17</version>
<executions>
<execution>
<id>failsafe-integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>failsafe-verify</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<trimStackTrace>false</trimStackTrace>
<systemPropertyVariables>
<webdriver.chrome.driver>${testbench.driver.path}/drivers/chromedriver-windows-32bit.exe</webdriver.chrome.driver>
<webdriver.gecko.driver>${testbench.driver.path}/drivers/geckodriver-windows-64bit.exe</webdriver.gecko.driver>
</systemPropertyVariables>
</configuration>
</plugin>
<!-- The Jetty plugin allows us to easily test the development build by
running jetty:run on the command line. -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<scanIntervalSeconds>2</scanIntervalSeconds>
<stopKey>STOP</stopKey>
<stopPort>8005</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
Here I have manually enter the version of the chrome driver to be downloaded and installed. But I want the oorwser version to be automatically detected in the developer's machine and download appropriate driver automatically. If I do not mention the driver version, I am getting error during the build.
How can this be brought? I need support for both Chrome and Firefox webdriver.
You can use WebDriver Manager API.
-It downloads the driver.exe to your /m2/repository/webdriver folder(while using Maven). It also automatically checks your browser version and download the matching version of driver.exe.
To use Webdriver Manager API,
Include below lines in your pom.xml file:
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>3.6.2</version>
<scope>test</scope>
</dependency>
-Then in your code just call this line before initialing the Webdriver object:
//Call any of the line based on which browser you are using.
WebDriverManager.chromedriver().setup();
WebDriverManager.firefoxdriver().setup();
WebDriverManager.iedriver().setup();
WebDriverManager.operadriver().setup();
WebDriverManager.phantomjs().setup();
WebDriverManager.edgedriver().setup();
So you can eliminate below steps:
1)Downloading the driver binaries manually and placing in the location
2)Below line of code also needs to be removed:
System.setProperty("webdriver.chrome.driver", "path to your driver location");
More info here
Adding latest answer.
From version Selenium 4.6.0, there is no necessity to use third WebDriverManager. Instead selenium has in built support for the same with class SeleniumManager. Selenium manager supports all the browser including Chrome, Edge and Firefox. No need to manually download any drivers as it will be handled automatically from SeleniumManager.
Steps to Implement:
Upgrade Selenium in your POM file to 4.6.0.
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java ->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.6.0</version>
</dependency>
Code implementation example for chrome as below where no need of adding any extra lines of code to handle it, similarly implementation follows for other browsers as well[Currently it is in beta]. Refer link for more information.
WebDriver driver = new ChromeDriver();
driver.get("https://someurl");

Cannot skip repackage goal of spring-boot-maven-plugin

I have a multi-module Maven project that contains an application consisting of several Spring Boot services. I am trying to set up integration and end-to-end tests for the services and am using a combination Maven plugins to orchestrate this.
I have one module that is intended to contain only end-to-end tests for groups of collaborating services that perform some work. It contains only test code and resources. I'm using the failsafe plugin (org.apache.maven.plugins:maven-failsafe-plugin) to perform the integration tests, the Spring Boot Maven plugin (org.springframework.boot:spring-boot-maven-plugin) to start and stop the "main" service and the Maven exec plugin (org.codehaus.mojo:exec-maven-plugin) to start the other services that are being used in the end-to-end tests.
I'm running into a problem that appears to be related to the repackage goal of the Spring Boot plugin. The e2e module has nothing that needs to be repackaged, so I want to skip this goal. Shouldn't be too hard, right?
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
<execution>
...
Well, this doesn't work. It runs repackage despite this.
The problem with this, is that the Maven build fails because it can't find a "main" class to repackage (as an executable jar, I believe). Well, there is no main class for this module.
The more important question is: why is <skip>true</skip> being ignored?
You need to add <id>repackage</id> after execution above goals.
I was also facing the same issue. I resolved it by using <pluginManagement> tag above <plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>

How to use Sesame Rio with maven-shade-plugin?

When I try to use Sesame Rio in a standalone Java application packaged with the maven-shade-plugin, I get
Exception in thread "main" org.openrdf.rio.UnsupportedRDFormatException: Did not recognise RDF format object N-Triples (mimeTypes=application/n-triples, text/plain; ext=nt)
at org.openrdf.rio.Rio.lambda$unsupportedFormat$0(Rio.java:630)
at org.openrdf.rio.Rio$$Lambda$1/736709391.get(Unknown Source)
at java.util.Optional.orElseThrow(Optional.java:290)
at org.openrdf.rio.Rio.createParser(Rio.java:119)
at org.openrdf.rio.Rio.createParser(Rio.java:137)
at org.openrdf.repository.util.RDFLoader.loadInputStreamOrReader(RDFLoader.java:318)
at org.openrdf.repository.util.RDFLoader.load(RDFLoader.java:222)
at org.openrdf.repository.util.RDFLoader.load(RDFLoader.java:105)
at org.openrdf.repository.base.AbstractRepositoryConnection.add(AbstractRepositoryConnection.java:255)
Running the application from Eclipse succeeds. How can I fix this?
The RDF format handlers in Rio are implemented as services, so the service descriptors have to be included in the shaded JAR. This is achieved with the ServicesResourceTransformer:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
More info:
Dependency on sesame-runtime with shade onejar packaging
sesame-assembly-2.8.2.pom

How to open a browser with a url from maven build

I'm building a web-application with Maven3 and run it via mvn jetty:run-war. Now I'd like to open the web-app from my maven build in the system browser.
I solved my problem on os windows, which is currently my only build system. After the jetty server is started and hosting my web-app the build makes a start call via antrun:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>Run URL in system browser.</id>
<phase>install</phase>
<configuration>
<target>
<exec executable="start" vmlauncher="false">
<arg line="http://localhost:8080/rap?startup=entrypoint"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
I have written a Maven plugin that can open browser on each platform/JDK as part of my bck2brwsr VM work. It can be used to show any static page in your project. Following example opens browser with content of pom.xml file:
<plugin>
<groupId>org.apidesign.bck2brwsr</groupId>
<artifactId>bck2brwsr-maven-plugin</artifactId>
<version>0.22</version>
<executions>
<execution>
<id>show-a-file</id>
<phase>verify</phase>
<goals>
<goal>show</goal>
</goals>
<configuration>
<directory>${basedir}</directory>
<startpage>pom.xml</startpage>
</configuration>
</execution>
</executions>
</plugin>
I know opening a static page isn't perfect, but it can contain appropriate redirect, right? Moreover, if there is an interested, the plugin can easily be improved to open any URL. Pull Requests welcomed.
Use Jetty server. Add Jetty plugin in your pom.xml under build tag like this:
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webApp>
<contextPath>/shinchan</contextPath>
</webApp>
</configuration>
</plugin>
<!-- more plugin tags if any -->
<plugins>
now build using
mvn clean install jetty:run
this will start Jetty server at port 8080, and you can access using http://localhost:8080/shinchan URL on the machine the mvn command is executed.
PS:
For more details read Jetty wiki here: http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin
you may want to consider jetty:deploy-war, but I think it's an overkill.