【问题标题】:How to maintain folder structure while exporting to Runnable Jar in Eclipse?在 Eclipse 中导出到 Runnable Jar 时如何维护文件夹结构?
【发布时间】:2017-10-02 12:42:37
【问题描述】:

我正在尝试从过去一周中找到解决方案,并发布了一个关于此问题的问题。

我创建了一个简单的 Maven 项目。 并编写了一个打开浏览器的功能文件,去facebook并关闭浏览器。

首先,下面是项目结构,

Project Structure

以下是我的功能文件。功能文件的名称是 Testing.feature

Feature: Open FB
Scenario: Open FB
    Given User opens "facebookURL" on "ChromeBr"
    When User is on facebook
    Then close the browser

然后我为上面的特征文件写了一个stepdefinition。步骤定义文件的名称是 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");
    }
}

而 config.properties 只包含一个属性

facebookURL=https://www.facebook.com

我编写了一个通用类文件,它是 WebConnector.java,它将有一个用于初始化属性文件的构造函数和一些方法,如打开浏览器和 URL 等

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();
    }
}

这是我的测试运行器类,它有一个 main 方法。它可以使用 Junit 以及 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>

问题: 当我使用 Junit 或 Java 应用程序运行 RunCukesTest.java 时,它运行良好。也就是打开浏览器,去fb,然后关闭浏览器。

但是当我创建一个可执行的 Jar 并运行时,它并没有按预期运行。

我按照以下步骤导出为 Runnable Jar:

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

假设我已将这个 Jar 保存在我的桌面中。桌面路径-->“C:\Users\PC\Desktop” 当我从命令提示符运行这个 Jar 时,它显示如下

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

我了解它正在尝试查找文件并且失败了。当我打开 Jar 时,它在下面的结构中。

Jar Structure after Exporting

如何保持相同的文件夹结构,以免出现 File Not Found Exception 或有没有其他方法可以成功运行?

【问题讨论】:

    标签: java maven selenium jar cucumber


    【解决方案1】:

    不是jar结构的问题,而是读取位置找文件的问题。

    假设您有一个简单的 java 文件,其中包含如下代码(伪):

    1. 获取当前目录
    2. 在当前目录中查找名为 src/test/java/config 的子目录
    3. 如果找不到目录,则抛出异常。

    现在,如果您从 IDE (eclipse) 运行 Main 类,您确实有 "src" 文件夹和所有必需的 sub folders。因此不会有例外。

    但是,如果您创建一个 jar,并将该 jar 放在不同的“新文件夹”(例如 jarFolder)中,那么当您运行代码时,您将看到找不到异常目录。 这是显而易见的

    所以这取决于你,只有你可以遵循你想要的方法。

    1) 一些将properties/config 文件与jar 一起提供(当配置文件的内容是动态的并且需要更改时,最不推荐使用。)

    2)有些人将他们的配置文件保存在配置层下,然后无论您复制一个jar,创建一个配置文件夹并将配置文件放在那里。在这种情况下,您可能需要像

    一样阅读它

    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) 另一件事,我建议人们不要购买他们的“src”,而是运送他们的二进制文件,这些二进制文件通常驻留在 classes 文件夹中,而不是 src 文件夹中。因此,应避免将 src 文件夹中的任何内容放入二进制 jar 中。

    【讨论】:

      【解决方案2】:

      我的建议是,您可以使用批处理文件运行 jar 文件。

      首先,您可以使用 maven build 创建项目的 jar 文件。以下是步骤

      右键单击Maven项目->运行方式->Maven构建->在目标中给出clean package->运行

      成功执行后,jar 文件将在您的项目的目标文件夹中创建。现在在您的项目位置创建一个批处理文件,例如run.bat。以下是您需要在批处理文件中编写的代码

      java -Xms512m -Xmx512m -jar execute.jar -0 true
      pause
      

      您可以更改 jar 名称。现在转到批处理文件位置并双击它。您的项目将执行,控制台报告将显示在命令提示符中。

      【讨论】:

        【解决方案3】:

        我们无法保持项目的相同结构。我发现的最佳解决方案是,在从任何其他路径运行可执行 jar 时,我确保这些文件夹(不是 jar 的一部分,而是项目的一部分)存在于我的可执行 jar 所在的同一路径中。

        【讨论】:

          猜你喜欢
          • 2012-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-15
          • 2014-08-05
          • 2011-09-15
          • 2015-02-01
          • 1970-01-01
          相关资源
          最近更新 更多