Background:
I am currently working on a project in eclipse that programatically executes JUnit tests that are pushed to a server.
So far everything works but I would like to know the results of the tests (specifically any failures) so I can push them out to an email. Right now the tests just output to the console but that doesn't seem to give me much output to actually use.
Right now I use the Runtime class to call the tests but that doesn't seem to have the functionality I need for getting results.
I have looked into the JUnitCore class but can't call any tests outside of the current java project.
So my main question would be how can I use JUnitCore to run junit tests in a specific JAR file? Or is there an easier way to approach this problem using a different class?
This is the only thing I've been able to get to work:
RunTests()
{
junitCore = new JUnitCore();
junitCore.run(AllTests.class);
}
But I would like to do something along the lines of this:
RunTests()
{
junitCore = new JUnitCore();
junitCore.run("C:\\$batch\\test\\hil research\\201507071307\\CommsTestRunner\\plugins\\TestSuite\\US35644.class");
}
I would appreciate any suggestions to this problem I am having. I'm an EE and was just introduced to java last month so this has been quite the challenge for me.
JUnitCore expects to read loaded classes, not class files in a JAR. Your real question is likely how to load the JAR (or directory of .class files) so it can be run.
Poke around with URLClassLoader; once you've amended the classpath appropriately, you can get a Class out of findClass and pass it into the JUnitCore methods you've found.
Since the tests might have classes that are also used by your server (but not necessarily at the same version) I would suggest not having your server directly run the tests. Instead, you can have your server start a new JVM that runs the tests. This is how IDEs like Eclipse run tests. You simply need to write a main class that has JUnit run the tests, and serializes the results on disk.
Your main class would look something like this:
public class MyRunner {
public static void main(String... args) throws IOException {
String path = System.getProperty("resultPath");
if (path == null) {
throw new NullPointerException("must specify resultPath property");
}
// Possibly install a security manager to prevent calls to System.exit()
Result result = new JUnitCore().runMain(new RealSystem(), args);
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path)) {
out.writeObject(result);
}
System.exit(result.wasSuccessful() ? 0 : 1);
}
}
Then your server simply needs to construct a java command line with the jars that include the tests, the JUnit jar file, and a jar that contains MyRunner.
Related
Im currently trying to get Evosuite to work with JNA. Consider the following basic example:
import com.sun.jna.ptr.IntByReference;
public class Example {
public static int foo(int x) {
IntByReference c = new IntByReference(x);
if (c.getValue() == 100) {
return 100;
} else {
return 0;
}
}
}
Im running Evosuite from the command line with these options:
java32 -jar evosuite.jar -projectCP "src;E:\evosuite\test\lib\jna-5.2.0.jar" -class Example -criterion branch
Evosuite wont reach 100% branch coverage (only the trivial 33%), but notifies me with this message after the timeout:
* Permissions denied during test execution:
- java.io.FilePermission:
write C:\Users\PC\AppData\Local\Temp\jna--2025216854: 1
I found out that JNA needs to write some temp files in order to work, but Evosuite will block any atempt of file writing during test generation. I understand that this is a reasonable policy in most cases because you dont want Evosuite to write random files to your disk while generating tests for a saveFile() function, but in my case this shouldn't be a problem.
Is there a way to tell Evosuite to allow file writing during test generation or a different approach to generate tests for java programms using the JNA library?
I figured out how to run JNA without the need of writing temporary files thanks to cubrr.
copy the system specific jnidispatch.[dll, ...] file to a folder
add -Djna.boot.library.path=folder -Djna.nounpack=true to the command
Note: the jna.boot.library.path should only point to the containig folder, do not write folder/jnidispatch.
Solution to the initial question:
Setting the evosuite option -Dsandbox=false will remove most restrictions for test generation and finally allowed me to generate my tests!
I still have some misunderstanding about the way vertx suppose you'll deploy/start yor app. Still there are two questions, but they are hardly related for me.
Question 1: I there a way to make your app launchable from both: command line and IDEA?
In one hand there is a Starter class (provided by Vert.x) to launch our application from command line. It provides main method for you. But if I launch it from shell I won't have an ability to debug it, right?
In other hand to lanch your app in IDEA you need to create main method manually. Also some features like configurations file are described only for command line way. I.e. java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar -conf src/main/conf/my-application-conf.json
Question 2: How to set configuration file programmatically?
I have a ServerVerticle, all questions there:
public class ServerVerticle extends AbstractVerticle {
//QUESTION 1: I need this method for IDEA debugging, but don't need when launch app from command line. How to be??
public static void main(String[] args) {
Consumer<Vertx> runner = vertx -> {
try {
vertx.deployVerticle("server.ServerVerticle", new DeploymentOptions());
} catch (Throwable t) {
t.printStackTrace();
}
};
Vertx vertx = Vertx.vertx(new VertxOptions());
runner.accept(vertx);
}
#Override
public void start() {
vertx.deployVerticle(...); //deploy another verticles
//QUESTION 2: how to pass configuration file programmaticaly in vertx? I can parse json file with java I/O, but if some configs are used accross the whole app?
vertx.createNetServer()
.connectHandler(this::handleMessage)
.listen(8080, "localhost");
}
}
In order to run your application from IntelliJ all you need to do is to add a run configuration where:
main class: io.vertx.core.Launcher
arguments: run ServerVerticle -conf /path/to/your/config.json
In order to set the configuration programmatically you need to pass a Json object to your deployment options as explained on the javadocs.
I have a Java code that produces directories and files within them after execution. The directory names are like:
ef3487f7457-43gfggf545-tgrg4536363-53345
ef3487f7457-43gfggf545-tgrg4536363-53462
ef3487f7457-43gfggf545-tgrg4536363-45742
With files inside each directory.
How in java code can I delete these directories? I have no use for them and they are just increasing my diskspace usage. This is for a few unit tests I run before I check anything in.
Something like this:
#After
public void afterUnitTestExecution() {
logger.info("Deleting bullshit files...");
try {
java.lang.Runtime.getRuntime().exec("rm -r *-*");
} catch (IOException e) {
e.printStackTrace();
}
}
This code seems like it should work, but it does not. Manually executing rm -r *-* it works but doing it in Java (as shown above) does not. What is wrong? Any help or assistance would be much appreciated. Thanks
Edit:
Thanks for the suggestions guys. However I'd like not to use something specific to JUnit, I prefer to accomplish my goal using standard conventional Java not Junit
Using JUNit TemporaryFolder
You should use junit rules designed to clean up files. JUnit comes with a TemporaryFolder thats exactly designed for this kind of unit tests.
The TemporaryFolder Rule allows creation of files and folders that
should be deleted when the test method finishes (whether it passes or
fails). Whether the deletion is successful or not is not checked by
this rule. No exception will be thrown in case the deletion fails.
It is easy to integrate it in your unit test:
public static class HasTempFolder {
#Rule
public TemporaryFolder folder= new TemporaryFolder();
#Test
public void testUsingTempFolder() throws IOException {
File createdFolder= folder.newFolder("subfolder");
// Run your code here
}
}
Using shell code
The reason your code isn't working, is because java isn't doing pattern expanding like the shell does, you can emulate this by starting a shell that executes your deletion:
new ProcessBuilder("sh", "-c", "rm -r *-*").inheritIO().start().waitFor();
Using pure java code to delete the directory
You can also use pure java code to delete the directory, use File.listFiles() to list the files in combination with a pattern matcher, then call File.delete() to delete the files.
Java 1.8
File f = new File("."); // Cuncurrent directory
Arrays.stream(f.listFiles(fi->fi.getName().match("[0-9a-f-]{36}"))).forEach(File::delete);
Java 1.6 and higher
File f = new File("."); // Cuncurrent directory
File[] files = f.listFiles(new FileFilter() {
public boolean accept(File fi) {
return fi.getName().match("[0-9a-f-]{36}");
}
});
for(File file : files) {
file.delete();
}
The above code uses regex to find the files, then calls delete on them.
I ran into library loading problems after creating a jar from my code via maven. I use intelliJ idea on Ubuntu. I broke the problem down to this situation:
Calling the following code from within idea it prints the path correctly.
package com.myproject;
public class Starter {
public static void main(String[] args) {
File classpathRoot = new File(Starter.class.getResource("/").getPath());
System.out.println(classpathRoot.getPath());
}
}
Output is:
/home/ted/java/myproject/target/classes
When I called mvn install and try to run it from command line using the following command I'm getting a NullPointerException since class.getResource() returns null:
cd /home/ted/java/myproject/target/
java -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
same for calling:
cd /home/ted/java/myproject/target/
java -Djava.library.path=. -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
It doesn't matter if I use class.getClassLoader().getRessource("") instead. Same problem when accessing single files inside of the target directory instead via class.getClassLoader().getRessource("file.txt").
I want to use this way to load native files in the same directory (not from inside the jar). What's wrong with my approach?
The classpath loading mechanism in the JVM is highly extensible, so it's often hard to guarantee a single method that would work in all cases. e.g. What works in your IDE may not work when running in a container because your IDE and your container probably have highly specialized class loaders with different requirements.
You could take a two tiered approach. If the method above fails, you could get the classpath from the system properties, and scan it for the jar file you're interested in and then extract the directory from that entry.
e.g.
public static void main(String[] args) {
File f = findJarLocation("jaxb-impl.jar");
System.out.println(f);
}
public static File findJarLocation(String entryName) {
String pathSep = System.getProperty("path.separator");
String[] pathEntries = System.getProperty("java.class.path").split(pathSep);
for(String entry : pathEntries) {
File f = new File(entry);
if(f.getName().equals(entryName)) {
return f.getParentFile();
}
}
return null;
}
I am trying to build a Dynamic web project where user can practice Java code.
I got success on writing the code written by user in a .java file, compile the code & get error messages using Java Compile API.
Now, I need to run JUnit 1.4 Compatible test on that code.
I researched for it, and found something like parameterized junit testing. But my view on how should it be done isn't still clear.
UPDATE
This (http://codingbat.com/prob/p171896) is the exact thing what I'm trying to implement.
I solved this problem with the following steps:
Compile the JUnit TestClass and the ClassToTest
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilerResult = compiler.run(null, null, null,"/path/to/TestClass.java", "/path/to/ClassToTest.java");
System.out.println("Compiler result code: " + compilerResult);
Load the compiled classes into the classloader
File dir = new File("/path/to/class/files/");
URL url = dir.toURI().toURL();
URL[] urls = {url};
ClassLoader classLoader = new URLClassLoader(urls);
Run the tests (make sure that you add junit as a dependency of your project)
Class<?> junitTest = Class.forName("TestClass", true, classLoader);
Result result = junit.run(junitTest);
Edit: If you're not needing the JUnit tests to be dynamic you can skip the compilation of those tests and add them here: junit.run(JunitTest.class)