I am trying to find a solution for this from the past one week and have posted a question regarding the same.
I have created a simple Maven Project. And have written a feature file which is open browser, go to facebook and close the browser.
First of all, below is the project structure,
Below is my feature file. Name of the feature file is Testing.feature
Feature: Open FB
Scenario: Open FB
Given User opens "facebookURL" on "ChromeBr"
When User is on facebook
Then close the browser
Then I wrote a stepdefinition for the above feature file. Name of the step definition file is Testing.java
package stepDefinitions;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import util.WebConnector;
public class Testing {
WebConnector wc = WebConnector.getInstance();
@Given("^User opens \"([^\"]*)\" on \"([^\"]*)\"$")
public void user_opens_on(String URL, String Browser) throws Throwable {
wc.openBrowser(Browser);
wc.navigateURL(URL);
System.out.println("Browser Opened & navigated to FB");
}
@When("^User is on facebook$")
public void user_is_on_facebook() throws Throwable {
System.out.println("User is on FB");
}
@Then("^close the browser$")
public void close_the_browser() throws Throwable {
wc.quitBrowser();
System.out.println("Browser Closed");
}
}
And config.properties contains only one property
facebookURL=https://www.facebook.com
I written a common class file which is WebConnector.java which will have a constructor for initializing the property file and few methods like open browser and URL etc
package util;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebConnector {
public Properties OR = null;
public Properties CONFIG = null;
public static WebDriver driver;
static WebConnector w;
private WebConnector() {
if(CONFIG==null) {
try {
CONFIG = new Properties();
FileInputStream fis = new FileInputStream(System.getProperty("user.dir")+"\\src\\test\\java\\config\\config.properties"); **//Here only I get error when I export as Runnable Jar and Run**
CONFIG.load(fis);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static WebConnector getInstance() {
if(w==null)
w=new WebConnector();
return w;
}
public void openBrowser(String browserName) throws IOException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
}
public void navigateURL(String URL) throws IOException {
driver.get(CONFIG.getProperty(URL));
}
public void quitBrowser() {
driver.quit();
}
}
And this is my test runner class which has a main method. It can be run using Junit as well Java Application
package util;
import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
@RunWith(Cucumber.class)
@CucumberOptions(
features = "classpath:feature",
glue = "stepDefinitions"
)
public class RunCukesTest {
public static void main(String[] args) {
JUnitCore.main("util.RunCukesTest");
}
}
Pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Jar_Testing</groupId>
<artifactId>Jar_Testing</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.5.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/info.cukes/cucumber-java -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/info.cukes/cucumber-core -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>1.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/info.cukes/cucumber-junit -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>util.RunCukesTest</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Problem: When I run RunCukesTest.java, using Junit or Java Application, it runs perfectly. That is, it opens the browser, goes to fb and closes the browser.
But when I create an executable Jar and run, it does not run as expected.
I export as Runnable Jar by following below Steps:
1) Run--> Run Configuration--> Java Application-->New Launch Configuration-->And selects the main class as RunCukesTest.java-->Apply
2) Right click the project-->Export
3) Java--> Runnable JAR File -->Next
4) Under Launch Configuration select the RunCukesTest.java and give the export destination
5) And I have selected the option "Extract required Libraries into Jar"
5) click finish
Say I have saved this Jar in My desktop. desktop path-->"C:\Users\PC\Desktop" When I run this Jar from command prompt, it shows the below
C:\Users\PC\Downloads>java -jar Maven.jar
JUnit version 4.12
.java.io.FileNotFoundException: C:\Users\PC\Downloads\src\test\java\config\c
onfig.properties (The system cannot find the path specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at util.WebConnector.<init>(WebConnector.java:19)
at util.WebConnector.getInstance(WebConnector.java:30)
at stepDefinitions.Testing.<init>(Testing.java:9)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstruct
orAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at cucumber.runtime.java.DefaultJavaObjectFactory.cacheNewInstance(Defau
ltJavaObjectFactory.java:41)
at cucumber.runtime.java.DefaultJavaObjectFactory.getInstance(DefaultJav
aObjectFactory.java:33)
at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.j
ava:38)
at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java
:37)
at cucumber.runtime.Runtime.runStep(Runtime.java:300)
at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:44)
at cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.ja
va:102)
at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63)
at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at cucumber.runtime.junit.FeatureRunner.run(FeatureRunner.java:70)
at cucumber.api.junit.Cucumber.runChild(Cucumber.java:95)
at cucumber.api.junit.Cucumber.runChild(Cucumber.java:38)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at cucumber.api.junit.Cucumber.run(Cucumber.java:100)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
at util.RunCukesTest.main(RunCukesTest.java:16)
.EEII
←[31mFailed scenarios:←[0m
←[31mfeature/Testing.feature:3 ←[0m# Scenario: Open FB
1 Scenarios (←[31m1 failed←[0m)
3 Steps (←[31m1 failed←[0m, ←[36m2 skipped←[0m)
0m0.314s
java.lang.IllegalStateException: The driver executable does not exist: C:\Users\
PC\Downloads\chromedriver.exe
at com.google.common.base.Preconditions.checkState(Preconditions.java:53
4)
at org.openqa.selenium.remote.service.DriverService.checkExecutable(Driv
erService.java:136)
at org.openqa.selenium.remote.service.DriverService.findExecutable(Drive
rService.java:131)
at org.openqa.selenium.chrome.ChromeDriverService.access$000(ChromeDrive
rService.java:32)
at org.openqa.selenium.chrome.ChromeDriverService$Builder.findDefaultExe
cutable(ChromeDriverService.java:137)
at org.openqa.selenium.remote.service.DriverService$Builder.build(Driver
Service.java:329)
at org.openqa.selenium.chrome.ChromeDriverService.createDefaultService(C
hromeDriverService.java:88)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:124)
at util.WebConnector.openBrowser(WebConnector.java:36)
at stepDefinitions.Testing.user_opens_on(Testing.java:12)
at ?.Given User opens "facebookURL" on "ChromeBr"(feature/Testing.featur
e:4)
Time: 0.359
There were 2 failures:
1) Given User opens "facebookURL" on "ChromeBr"(Scenario: Open FB)
java.lang.IllegalStateException: The driver executable does not exist: C:\Users\
PC\Downloads\chromedriver.exe
at com.google.common.base.Preconditions.checkState(Preconditions.java:53
4)
at org.openqa.selenium.remote.service.DriverService.checkExecutable(Driv
erService.java:136)
at org.openqa.selenium.remote.service.DriverService.findExecutable(Drive
rService.java:131)
at org.openqa.selenium.chrome.ChromeDriverService.access$000(ChromeDrive
rService.java:32)
at org.openqa.selenium.chrome.ChromeDriverService$Builder.findDefaultExe
cutable(ChromeDriverService.java:137)
at org.openqa.selenium.remote.service.DriverService$Builder.build(Driver
Service.java:329)
at org.openqa.selenium.chrome.ChromeDriverService.createDefaultService(C
hromeDriverService.java:88)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:124)
at util.WebConnector.openBrowser(WebConnector.java:36)
at stepDefinitions.Testing.user_opens_on(Testing.java:12)
at ?.Given User opens "facebookURL" on "ChromeBr"(feature/Testing.featur
e:4)
2) Scenario: Open FB
java.lang.IllegalStateException: The driver executable does not exist: C:\Users\
PC\Downloads\chromedriver.exe
at com.google.common.base.Preconditions.checkState(Preconditions.java:53
4)
at org.openqa.selenium.remote.service.DriverService.checkExecutable(Driv
erService.java:136)
at org.openqa.selenium.remote.service.DriverService.findExecutable(Drive
rService.java:131)
at org.openqa.selenium.chrome.ChromeDriverService.access$000(ChromeDrive
rService.java:32)
at org.openqa.selenium.chrome.ChromeDriverService$Builder.findDefaultExe
cutable(ChromeDriverService.java:137)
at org.openqa.selenium.remote.service.DriverService$Builder.build(Driver
Service.java:329)
at org.openqa.selenium.chrome.ChromeDriverService.createDefaultService(C
hromeDriverService.java:88)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:124)
at util.WebConnector.openBrowser(WebConnector.java:36)
at stepDefinitions.Testing.user_opens_on(Testing.java:12)
at ?.Given User opens "facebookURL" on "ChromeBr"(feature/Testing.featur
e:4)
FAILURES!!!
Tests run: 2, Failures: 2
I understand that it is trying to find the file and it is failing. When I open Jar, it is in the below structure.
How do I maintain the same folder structure so that I don't get File Not Found Exception or Is there any other way to run this successfully?
My suggestion is, you can run the jar file using batch file.
First you can create jar file of your project by using maven build. Below are the steps
Right click on Maven project -> Run As -> Maven Build -> in target give clean package -> Run
After successful execution, jar file will be created in target folder of your project. Now create one batch file in your project location like
run.bat
. Below is the code you need to write in batch fileyou can change jar name. Now go to batch file location and double click on it. Your project will execute and console report will be displayed in command prompt.
It is not a problem of the structure of jar, but it is about reading a location to find a file.
Assume you have a simple java file that have code code (pseudo) like below:
Now if you are running the
Main
class from your IDE (eclipse), you do have"src"
folder and all requiredsub folders
. Hence there won't be an exception.But if you create a jar, and place the jar in a different "new folder" (jarFolder e.g), then when you will run the code, you will see the exception directory not found. That is obvious.
So it is upto you, and only you to follow which approach you want.
1) Some ship the properties/config file with the jar (least recommended when the content of config file is dynamic and needs to be changed.)
2) Some keep their config files under just config layer and then wherever you copy a jar, create a config folder and put config file there. In that case you may have to read it like
System.getProperty("user.dir")+File.separator+"config"+File.separator+"config.properties"; // Offcourse, using \\ is a bad way to use File.separtor as it will not work on unix again
3) Another thing, I would suggest is that people don't shop their "src" but ship their binaries which normally reside it in classes folder, not in src folder. So putting anything from src folder in binary jar shall be avoided.
We cannot maintain the same structure of the project. Best solution, I have found is, while running executable jar from anyother path, I made sure that those folders(which are not part of jar but a part of project) exists in the same path where my executable jar is.