1

I am using intellij for creating tests using selenium and testng.

Below is my code which I using to switch between local run and jar preparation

public class Constants {

//I am uncommenting the below lines to run in intellij locally

//    public static String currentDirectory = new File("").getAbsolutePath();
//    public static final String myPath = currentDirectory + "/src/test/java/myproject/data/";
//    public static final String Env = myPath + "Environments.xls";

//For JAR File generation I am uncommenting below line and commenting the above lines

    public static final String Env = "Environments.xls";

//
}

Whenever I need to run locally I need to comment and uncomment above variables for local run or to prepare jars and I am doing every now and then, it is getting harder and harder as I have 4 different packages which has similar structure to debug and fix then generate Jars. In each package I have data folder and in the data folder I have Environments.xls (4 xls files)

When I prepare my jars - I am adding ('Add copy of') the data files to my artifact and generating the jars. I am creating 4 jars and each time I create a Jar I am adding my data folder. (sounds silly for many but I am novice in java sorry... I don't know how to automate this process)

My question: Is there any way to declare variables in order to use in both ways (for local run and jar preparation) without changing them manually?

I using Maven project. Intellij 2016.1.2 community edition

Thank you

user790049
  • 1,154
  • 1
  • 9
  • 21
  • Possible duplicate of [adding resources in intellij for java project](http://stackoverflow.com/questions/18717038/adding-resources-in-intellij-for-java-project) – Meo Jul 31 '16 at 23:42
  • Meo, did you get a chance to read my problem- I can't use 4 similar name files in one resource folder - if it is possible then you are correct it is duplicate – user790049 Jul 31 '16 at 23:51
  • Why don't you use some parameter when running the program to choose which file to load? – Meo Aug 01 '16 at 00:01
  • Or this http://stackoverflow.com/questions/7353585/maven-include-resource-file-based-on-profile or http://stackoverflow.com/a/29564441/685796 – Meo Aug 01 '16 at 00:07
  • Thank you Meo, I will check the above link. Just to make it clear what I am doing... My end goal is to deliver my jar to manual testers so that they can run them locally on their machines. I am preparing this jar with all the data files and dependencies. I have 4 projects and created 4 packages and each package has its data folder to use. Looks like I made this bit complicated as my knowledge in this area is very limited – user790049 Aug 01 '16 at 00:11

1 Answers1

4

Instead of reading a file by its pathname, resolve it regarding the classpath. You simply put the file in src/main/resources or src/test/resources depending on your case, and get an input stream on the file by:

    InputStream is = MyClass.class.getResourceAsStream("Environments.xls");

In most cases, you don't really need a java.io.File, but a means to read it.

And by reading the file this way, you can package your resources in JARs (Maven does it) and the code will still work.

Now if the location of the file to load depends on the target environment (this is a example), here's what I do:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>demo</groupId>
    <artifactId>maven-environment-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>maven-environment-demo</name>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.8</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <phase>process-resources</phase>
                        <configuration>
                            <target>
                                <copy file="${environment.dir}/environment.properties" todir="${project.build.outputDirectory}" />
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <profiles>
        <profile>
            <id>development</id>
            <properties>
                <environment.dir>${project.basedir}/src/main/environment/development</environment.dir>
            </properties>
        </profile>
        <profile>
            <id>staging</id>
            <properties>
                <environment.dir>${project.basedir}/src/main/environment/staging</environment.dir>
            </properties>
        </profile>
        <profile>
            <id>production</id>
            <properties>
                <environment.dir>${project.basedir}/src/main/environment/production</environment.dir>
            </properties>
        </profile>
    </profiles>
</project>

Here, I'm working with properties, but it's for the sake of testing. I'm defining 3 profiles each defining the same property with a different value. This property defines the location of my environment-specific files. Then, during the process-resources phase I'm copying environment.properties to its proper location for classpath retrieval. Maven does the rest.

Now in order to active one profile, I need to run:

mvn clean install -Pstaging

In the IDE I need to set the profile I wish to work on. In NetBeans, it is done with the dropdown box that appears at the top of the window.

Here is the test class that I used to verify the configuration (here no caching of the properties is done, so don't you use this in production!):

package demo.maven.environment;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class EnvironmentProperties {

    public String getProperty(String key) throws IOException {
        Properties props = new Properties();
        try (InputStream is = EnvironmentProperties.class.getResourceAsStream("/environment.properties")) {
            props.load(is);
        }
        return props.getProperty(key);
    }

    public static void main(String[] args) throws IOException {
        System.out.println(new EnvironmentProperties().getProperty("env.name"));
    }

}
Arthur Noseda
  • 2,534
  • 19
  • 28
  • 1
    Thank you Arthur, but it works only for one package and one data file correct? what if I need to prepare jar/run locally for another package do I need to remove the file and add the corresponding data file to resource and use it... if that is the case it doesn't solve my problem. If I miss your point sorry for that my knowledge in this area is zero... – user790049 Aug 01 '16 at 00:02
  • Your point is valid but I would resolve it with another trick. Since you're using Maven, you can describe profiles in the pom.xml. Each profile can be active or inactive as you please. Your notion of environments would have me believe that you could benefit from profiles named dev, staging, production, for example. Then each profile could activate an Ant task to copy their respective XLS to the target XLS. For example copy Environments-dev.xls to Environments.xls before the packaging is done. – Arthur Noseda Aug 01 '16 at 00:07
  • Thank you Arthur, I will do some R&D on profile usage, but why I need to use ANT I am confused with all different tools and usages. Sorry I am travelling in a dark zone where most people has passed through with their efforts... at least some info I got from you to research and try... – user790049 Aug 01 '16 at 00:19
  • I don't have the snippet available right now, but the elements to guide you are the following: define a profile, define a build element inside the profile, configure the maven-antrun-plugin (maybe you can find something you're more familiar with) to execute the copy / rename: the configuation will look something like this: `` – Arthur Noseda Aug 01 '16 at 00:25
  • I've edited the answer so you can see a complete working yet minimal example. – Arthur Noseda Aug 01 '16 at 09:32