Static initialization of properties files fails with ant build - java

I have a small java project which I execute using TestNG + Eclipse, and it works well.
I have externalized test data using properties file and I initialize it in one static block of my test class -
public class SanityTest extends SelTestCase {
static Properties properties = new Properties();
static String pickUp;
static String dropOff;
static {
try {
properties
.load(SanityTest.class
.getResourceAsStream("/com/product/testdata/testdata.properties"));
pickUp = properties.getProperty("pickUp");
dropOff = properties.getProperty("dropOff");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Verifies the booking of car on car hire market
* #throws Exception
*/
#Test
public void testBookingModule() throws Exception {
// Some tests here
}
But when I execute same using ant build (1.8) I encounter following exception on target "run" -
[testng] Caused by: java.lang.NullPointerException
[testng] at java.util.Properties$LineReader.readLine(Properties.java:418)
[testng] at java.util.Properties.load0(Properties.java:337)
[testng] at java.util.Properties.load(Properties.java:325)
I could not figure out much and also checked that "bin" is created and has all respective files.
Is there any thing I missed?

It seems strange to me that you have to use the package/directory name to retrieve your file loaded as a resource by the class loader.
Usually when you use getResourceAsStream, you put your data file where your class is, where the .class file is (or in the resource directory and eclipse will copy it at build time), and the you load it by specifying only the name of the file.
Try
properties.load(SanityTest.class.getResourceAsStream("testdata.properties"));
where testdata.properties is in the same folder as SanityTest.class
Regards,
stéphane

It seems like you get the stream from the property file.
Could this exception come from badly formatted prop file, which leads to null being returned somewhere?

Related

Design idempotent unit test

I'm designing unit tests for the following method:
public void loadFile(Path filename) throws IOException {
try {
// do something
} catch (RuntimeException ex) {
Files.move(filename, filename.resolveSibling("ERROR_" + filename.getFileName()));
return;
}
Files.delete(filename);
}
And I'm looking for a way of testing it without producing different results, since the input file is going to be either renamed or deleted after the execution test:
If RuntimeException takes place, file is renamed.
If execution goes as expected, file is deleted.
Either way, consecutive runs of the test will make it fail because file will be named different or it won't exist... How could I prevent that? Also, is there a way to verify Files#move(Path, Path, CopyOption...) and Files#delete(Path) were invoked?
I would recommend to use new #TempDir annotation from junit 5.
Docs:
When the end of the scope of a temporary directory is reached, i.e. when the test method or class has finished execution, JUnit will attempt to recursively delete all files and directories in the temporary directory and, finally, the temporary directory itself.
In that case you test cases will look as the next:
#Test
void loadsFileCorrectly(#TempDir Path temp) {
final Path file = temp.resolve("testable.file");
loadFile(file);
Assertions.assertTrue(Files.notExists(file));
}
#Test
void loadsFileWithException(#TempDir Path temp) {
final Path file = temp.resolve("testable.file");
loadFile(file);
Assertions.assertTrue(Files.exists(file.resolveSibling("ERROR_" + file.getFileName())));
}
In both scenarios, the created files will be automatically deleted after execution.

Java Cucumber: Take #CucumberOptions from external source like a property file

Is it possible to take cucumber option values from a java .properties file?
In this SO post, it shows that it is being passed from CLI.
Here's my sample class:
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"resources/features/"},
glue = {"classpath:com/"},
tags = {"#foo, #bar"}
)
public class UITestRunner {
}
Instead of hardcoding the tags here, I'd like to take it from a property file.
Any help is appreciated!
Cucumber will initially look for arguments provided by cucumber.api.cli.Main or #CucumberOptions
But you can override them providing (in this particular order):
The OS environment variable CUCUMBER_OPTIONS
The Java system property cucumber.options
The Java resource bundle cucumber.properties with a cucumber.options property
Once one of described above options is found, it will be used. Overrides are provided in a variable (or property) called cucumber.options or CUCUMBER_OPTIONS. All values, except plugin arguments will override values provided by cucumber.api.cli.Main or #CucumberOptions. Plugin option will add up to the plugins specified by cucumber.api.cli.Main or #CucumberOptions.
Hope you are aware that if running from the command line, you can use system properties
mvn test -Dcucumber.options="--features resources/features/ --tags ~#ignore" -Dtest=AnimalsTest
Which means that you can programmatically set these properties:
#RunWith(Cucumber.class)
public class CatsRunner {
#BeforeClass
public static void before() {
System.setProperty("cucumber.options", "--features resources/features/ --tags ~#ignore");
}
}
Hope that gives you some ideas. For example, you can manually read the properties from a file and then achieve what you want.
Edit: apparently the above does not work. So here's my next idea, implement your own JUnit Cucumber runner by extending the Cucumber class. Refer to this for an example. So in the constructor you should have full control.
I solved this by extending the Cucumber runner. You can find examples here:
For cucumber-jvm 4.0.0: https://github.com/martinschneider/yasew/blob/master/src/main/java/io/github/martinschneider/yasew/junit/YasewRunner.java
For cucumber-jvm 2.4.0: https://github.com/martinschneider/yasew/blob/db8cd74281139c14603e9ae05548530a7aebbade/src/main/java/io/github/martinschneider/yasew/junit/YasewRunner.java
The key part, as discussed in some of the replies and comments, is to set the cucumber.options system property:
String cucumberOptions =
"--tags #"
+ getProperty(PLATFORM_KEY, DEFAULT_PLATFORM)
+ " --glue io.github.martinschneider.yasew.steps --glue "
+ getProperty(STEPS_PACKAGE_KEY)
+ " --plugin pretty --plugin html:report --plugin json:"
+ getProperty(CUCUMBER_REPORT_DIRECTORY_KEY,
DEFAULT_CUCUMBER_REPORT_DIRECTORY)
+ "/cucumber.json"
+ " "
+ getProperty(FEATURES_DIRECTORY_KEY);
LOG.info("Setting cucumber options ({}) to {}", CUCUMBER_OPTIONS_KEY, cucumberOptions);
System.setProperty(CUCUMBER_OPTIONS_KEY, cucumberOptions);
I'm using a setup with Spring and JUnit and I'm not sure if there's a better place to put this code.
Overwriting the runner is not very elegant but it works like a charm!
An example for an override feature source line in cucumber.properties file in project tree is:
cucumber.options=-g StepDefs src\\test\\resources\\Testfeature.feature
The Cucumber for Java Book is cool. I got it after reading this post.
I experimented some time to see what path the CucumberOptions property accepts... so here above is the quick solve. ;)
StepDefs is the folder where my step definitions are located in the project tree.
I prefer this way to have everything in one place. Maybe for porting the testsuite to another system it is more common to set a System variable in the target system so the possible customer has always one directory where to place feature-files.
I was searching for a solution how to pass(over write) feature file path glue (steps) path in command line in Dcucumber options. It was quite challenging and I was unable to find the exact solution in many of the forums. Finally found a working solution
Just posting here it could help anybody.
gradle -Dcucumber.options="-g XX.XXX.XXX.steps --tags #xxxxxx featurefilepath/features/" test
You must follow this order having -g as a first option. Thaanks
I am doing like this:-
cucmberOption.properties
#cucumber.options=--plugin html:output/cucumber-html-report
#src/test/resources
cucumber.options.feature =src/test/resources
cucumber.options.report.html=--plugin html:output/cucumber-html-report
Java Class: CreateCucumberOptions.java
Method to load properties file:-
private static void loadPropertiesFile(){
InputStream input = null;
try{
String filename = "cucumberOptions.properties";
input = CreateCucumberOptions.class.getClassLoader().getResourceAsStream(filename);
if(input==null){
LOGGER.error("Sorry, unable to find " + filename);
return;
}
prop.load(input);
}catch(IOException e){
e.printStackTrace();
}finally{
if(input!=null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
method to get and set CucumberOptions
private String createAndGetCucumberOption(){
StringBuilder sb = new StringBuilder();
String featureFilesPath =
prop.getProperty("cucumber.options.feature");
LOGGER.info(" featureFilesPath: " +featureFilesPath);
String htmlOutputReport =
prop.getProperty("cucumber.options.report.html");
LOGGER.info(" htmlOutputReport: " +htmlOutputReport);
sb.append(htmlOutputReport);
sb.append(" ");
sb.append(featureFilesPath);
return sb.toString();
}
private void setOptions(){
String value = createAndGetCucumberOption();
LOGGER.info(" Value: " +value);
System.setProperty(KEY, value);
}
And main method to run this:-
public static void main(String[] args) {
CreateCucumberOptions cucumberOptions = new CreateCucumberOptions();
JUnitCore junitRunner = new JUnitCore();
loadPropertiesFile();
cucumberOptions.setOptions();
junitRunner.run(cucumberTest.runners.RunGwMLCompareTests.class);
}
And RunGwMLCompareTests.class is my Cucumber class
#RunWith(Cucumber.class)
#CucumberOptions(
monochrome = true,
tags = {"#passed"},
glue = "cucumberTest.steps")
public class RunGwMLCompareTests {
public RunGwMLCompareTests(){
}
}
So basically nopw you get set output report and feature folders through properties files and others options like glue definations java class. And to run the test cases just run your main class.
Regards,
Vikram Pathania

Parameter 'directory' is not a directory for a parameter which is a directory

I'm getting a strange error where the parameter I supply to a method complains that it's not a directory but it IS in fact a directory with files in it...I don't understand what's wrong...
Toplevel:
public static File mainSchemaFile = new File("src/test/resources/1040.xsd");
public static File contentDirectory = new File("src/test/resources/input");
public static File outputDirectory = new File("src/test/resources/output");
DecisionTableBuilder builder =constructor.newInstance(log, contentDirectory, outputDirectory);
// Here is where the error occurs
builder.compile(mainSchemaFile);
The class I'm using:
public class DecisionTableBuilder {
public void compiler(File schemaFile) {
...
// It's complaining about contentDirectory, it goes to FileUtils class for this
Collection<File> flowchartFiles = FileUtils.listFiles(contentDirectory, mapExtension, true);
...
}
}
Here is the apache FileUtils class:
public class FileUtils {
private static void validateListFilesParameters(File directory, IOFileFilter fileFilter) {
if (!directory.isDirectory()) {
throw new IllegalArgumentException("Parameter 'directory' is not a directory");
}
if (fileFilter == null) {
throw new NullPointerException("Parameter 'fileFilter' is null");
}
}
}
Output: Parameter 'directory' is not a directory
Which is the error output I am getting...
Anyone have any idea what is happening here I'm super confused...any help will be greatly appreciated.
EDIT:
In my toplevel I added the following line:
if(contentDirectory.isDirectory()) {
System.out.println("Content Directory: "+contentDirectory);
}
Output: src/test/resources/input
You're pointing to the file and not a directory in mainSchemaFile variable. Reduce the path to the folder containing 1040.xsd - it should resolve the issue.
Error is thrown if paths cannot be reached
The file paths that you show do not tell where you try to run the code. If you are in your workspace, but you want to run it on a server, and the paths are meant to be on the server, see as follows:
I saw during debugging in the error logs of the console output of my own project that the code tried to get the data from my workspace. While coding, I thought that it would reach the files on the production server, but it did not.
Exception in thread "my_project" java.lang.IllegalArgumentException: Parameter 'directory' is not a directory
at org.apache.commons.io.FileUtils.validateListFilesParameters(FileUtils.java:545)
at org.apache.commons.io.FileUtils.listFiles(FileUtils.java:521)
at org.apache.commons.io.FileUtils.listFiles(FileUtils.java:691)
With the needed file copied to my workspace and the right path in the code, the error was gone since it found the directory.
In my program, my working directory was the repository from where I ran the code. I had to pull the repository on the server to run it with the working directory on the server, so that it could find the production directory for the input files.

JUnit Test Cases not changing even though files change

I use Eclipse and Maven and have made a single JUnit test, just to test if it works. The first time I ran the test everything went as expected, but since then, every time I run it, I get the same result, even though I'm changing the actual test-file's content.
I tried just emptying the file, then it said that there are no JUnit test files. But as long as I just have #Test in front of a method in that file, I always get the same results.
Anyone know why that could be?
I tried restarting eclipse.
EDIT:
Just realized that I'm not getting the test results since there is an exception before it gets tested. So, the problem is that I'm always getting the exception even though I changed the file.
Testclass:
public class zipTester {
/**
* The class to be tested on.
*/
private Generator generator;
/**
* Sets up the generator.
*/
#Before
public void setUp() {
generator = new Generator(null, 0);
}
/**
* Creates a zip file and tests whether it exists.
*/
#Test
public void testCreateZip() {
File file = new File("/Users/nicola/Documents/trunk);
generator.createZip(file, new Vector<File>());
}
}
Changed TestClass:
public class zipTester {
#Test
public void heyo() {
}
}
Always getting the following Exception:
java.io.FileNotFoundException: /Users/nicola/Documents/trunk (No such file or directory)
...
1 May be you should clean your project
2 and then recheck project-BuildAutomatically
if still have something wrong,
you can right-click your project "java build path" and open the first tab Source
set default output folder content "test/target/classes"
good luck :)
i think your code was not compiled by eclipse
Seems that happen when there is no file in the relevant location.Because you are passing the file to Generator and try to access that file.Then this exception happen as there are no file to access with generator.
You can follow the below steps to avoid this scenario.
First check is that file exist in that location as below,
File file = new File("/Users/nicola/Documents/trunk");
assertTrue(file.exists());
Then check with your Generator.

this.getClass().getResource("").getPath() returns an incorrect path

I am currently making a small simple Java program for my Computer Science Final, which needs to get the path of the current running class. The class files are in the C:\2013\game\ folder.
To get this path, I call this code segment in my main class constructor:
public game(){
String testPath = this.getClass().getResource("").getPath();
//Rest of game
}
However, this command instead returns this String: "/" despite the correct output being "C:/2013/game"
Additionally, I attempted to rectify this by using this code:
public game(){
String testPath = this.getClass().getClassLoader().getResource("").getPath();
}
This returns a NullPointerException, which originates from the fact that getClassLoader() returns null, despite working on my Eclipse IDE. Any Ideas?
If you want to load a file in the same path as the code then I suggest you put it in the same root folder as the code and not the same path as the class.
Reason : class can be inside a jar, data file can be put in same jar but its more difficult to edit and update then.
Also suggest you see the preferences class suggested in comments : http://www.javacodegeeks.com/2011/09/use-javautilprefspreferences-instead-of.html though in some cases I think its okay to have your own data/ excel/csv/ java.util.Properties file
Not sure about why it is working in eclipse but I would suggest you focus on running it from a command prompt/ terminal as that is the 'real mode' when it goes live
You could just ask for your class
String s = getClass().getName();
int i = s.lastIndexOf(".");
if(i > -1) s = s.substring(i + 1);
s = s + ".class";
System.out.println("name " +s);
Object testPath = this.getClass().getResource(s);
System.out.println(testPath);
This will give you
name TstPath.class
file:/java/Projects/tests3b/build/classes/s/TstPath.class
Which is my eclipse build path ...
need to parse this to get the path where the class was loaded.
Remember:
App could be started from elsewhere
class can be in jar then path will be different (will point to a jar and file inside that
classpaths can be many at runtime and point 1
a class might be made at runtime via network/ Proxy / injection etc and thus not have a file source, so this is not a generic solution.
think what you want to acheive at a higher level and post that question. meaning why do you want this path?
do you want the app path :-
File f = new File("./");
f.getCanonicalPath();//...
So an app can be started from folder c:\app1\run\
The jar could be at c:\app1\libsMain\myapp.jar
and a helper jar could be at c:\commonlibs\set1
So this will only tell you where the JVM found your class, that may or maynot be what you need.
if inside a jar will give you some thing like this in unix or windows
jar:file:c:\app\my.jar!/s/TstPath.class
If package is s and class is TstPath, you can be sure this will work as the class has to be there ...
now to parse this you can look for your class name and remove / or \ till you get path you want. String lastIndexOf will help
You can use :
URL classURL = getClass().getProtectionDomain().getCodeSource().getLocation();
The call to getResource([String]) requires a path relative to the folder that contains the class it is being called from. So, if you have the following, anything you pass into MyClass.class.getResource([path]); must be a valid path relative to the com/putable/ package folder and it must point to a real file:
package com.putable;
public class MyClass{}
Using the empty string simply isn't valid, because there can never be a file name that equals the empty string. But, you could do getResource(getClass().getSimpleName()). Just remove the file name from the end of the path returned by that call and you will have the class directory you want.
ClassLoader loader = Test.class.getClassLoader();
System.out.println(loader.getResource("Test.class"));
also
Test.class.getProtectionDomain().getCodeSource().getLocation().getPath());
Try this.
import java.io.File;
public class TT {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String path = TT.class.getResource("").getPath();
File file = new File(path);
System.out.println(file.getAbsolutePath());
}
}
Try use this code
public game()
{
String className = this.getClass().getSimpleName();
String testPath = this.getClass().getResource(className+".class");
System.out.println("Current Running Location is :"+testPath);
}
visit the link for more information
Find where java class is loaded from
Print out absolute path for a file in your classpath i.e. build/resources/main/someFileInClassPath.txt Disclaimer, this is similar to another solution on this page that used TT.class..., but this did not work for me instead TT..getClassLoader()... did work for me.
import java.io.File;
public class TT {
/**
* #param args
*/
public static void main(String[] args) {
String path = TT.getClassLoader().getResource("someFileInClassPath.txt").getPath();
File file = new File(path);
System.out.println(file.getAbsolutePath());
}
}
Because you used class.getResource(filePath).getpath() in a *.jar file. So the path includes "!". If you want to get content of file in *.jar file, use the following code:
MyClass.class.getResourceAsStream("/path/fileName")

Categories

Resources