Running command line tools inside of a Java program - java

Hello StackOverflow Community,
I have this JUnit Tests that need to run a Server with the command mvn exec:java, and I need to delete the contents of a directory before the tests are executed. Otherwise, the JUnit test will fail. Is there any way I can include these steps into my source code?
Ejay

You should use JUnit's #BeforeClass notation which will be called before the first test starts to clean up the target directory. You should also use the commons-io library avoid unnecessary coding.
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.junit.BeforeClass;
import org.junit.Test;
public class DeleteDirectoryTest {
private static final String DIRECTORY_PATH = "C:/TEMP";
#BeforeClass
public static void cleanUp() throws IOException {
FileUtils.deleteDirectory(new File(DIRECTORY_PATH));
}
#Test
public void doSomeTest() {
// Test code goes here
}
}

You can place a recursive delete for your directory in your JUnit '#BeforeClass' init method.

public static boolean emptyDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i=0; i<children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return true;
}

you can use ProcessBuilder to execute commands from java applications

Related

How to run a gradle task from a java code?

I need to run the gradle eclipse task to an external gradle project from a java method, is it possible to do it using the Gradle Tooling API ?
The Gradle forum gives a nice example for doing this programmatically but since it disregards the projects individual gradle wrapper, it can't guarantee the smooth execution of your build and even break your application. For more information why you always should rely on the gradle wrapper read here and here.
Using the Gradle wrapper
The recommended approach is to run exec and call the projects wrapper while passing the task as a parameter. This example calls the current projects wrapper and passes jar as a parameter:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Main
{
private static String PATH_TO_GRADLE_PROJECT = "./";
private static String GRADLEW_EXECUTABLE = "gradlew.bat";
private static String BLANK = " ";
private static String GRADLE_TASK = "jar";
public static void main(String[] args)
{
String command = PATH_TO_GRADLE_PROJECT + GRADLEW_EXECUTABLE + BLANK + GRADLE_TASK;
try
{
Runtime.getRuntime().exec(command);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Using the Gradle Tooling API
To use the Gradle tooling api on a external project, you simply have to define the property forProjectDirectory of your GradleConnectorobject. To run a task call run() on the BuildLauncher object. The example below demostrates the basic principle:
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;
import java.io.File;
public class ToolingAPI
{
private static final String GRADLE_INSTALLATION = "C:\\Program Files\\Gradle";
private static final String GRADLE_PROJECT_DIRECTORY = "path_to_root_of_a_gradle_project";
private static final String GRADLE_TASK = "help";
private GradleConnector connector;
public ToolingAPI(String gradleInstallationDir, String projectDir)
{
connector = GradleConnector.newConnector();
connector.useInstallation(new File(gradleInstallationDir));
connector.forProjectDirectory(new File(projectDir));
}
public void executeTask(String... tasks)
{
ProjectConnection connection = connector.connect();
BuildLauncher build = connection.newBuild();
build.forTasks(tasks);
build.run();
connection.close();
}
public static void main(String[] args)
{
ToolingAPI toolingAPI = new ToolingAPI(GRADLE_INSTALLATION, GRADLE_PROJECT_DIRECTORY);
toolingAPI.executeTask(GRADLE_TASK);
}
}
The downside of this approach is the location unawareness of gradle when executing a task. In case you call any file creation or modification method in a custom task like new File("somefile") a exception will be raised.

Selenium grid with Java - user input

I am writing automatic tests using Java with Selenium Grid and JUnit framework and I have encountered a problem with user input. So my code looks like this:
package com.example.tests;
import com.thoughtworks.selenium.DefaultSelenium;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Scanner;
import static org.junit.Assert.fail;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
public class test {
private DefaultSelenium selenium;
#Before
public void setUp() throws Exception {
selenium = new DefaultSelenium("localhost", 5555, "*googlechrome", "www.google.com");
selenium.start();
}
#Test
public void Test() throws Exception {
// some tests here
}
#After
public void tearDown() throws Exception {
selenium.stop();
}
I would like to add a user input, so when user types for example "Google Chrome", the test will start with Google Chrome, when he types "Firefox", the test will start with Firefox etc. I have tried to put
Scanner in = new Scanner(System.in);
String web_browser = in.next();
somwhere in my code (in setUp method for example), but when the program starts, I can't type anything in the console. Does anyone know the solution for this?
It's tricky dealing with System.in in the test.
I suggest that you rather read your driver preference as a system property?
String driver = System.getProperty("driver");
if (driver != null) {
//use that driver
}
else {
//use default driver
}
You can the launch your test like
mvn test -Ddriver=chrome
or by setting them in your IDE

How can I load a file relative to a class's package?

I have the file allDepartments.json in a subdirectory called fixtures, to which I want to access from the Fixture.java class.
This is my Fixture.java code:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public final class Fixture {
private static final String FIXTURES_PATH = "";
private final String fixture;
public Fixture(String fixtureName) throws IOException {
fixture = new String(Files.readAllBytes(Paths.get(FIXTURES_PATH + fixtureName)));
}
public final String getFixture() {
return fixture;
}
}
However every time he tries to access the file I get a java.nio.file.NoSuchFileException: allDepartments.json...
I have heard of the getResource() method and tried every combination possible of it, without success.
I need this to store multi-line strings for my JUnit tests.
What can I do?
The NIO.2 API can't be used to read files that are effectively project resources, i.e. files present on the classpath.
In your situation, you have a Maven project and a resource that you want to read during the unit test of the application. First, this implies that this resources should be placed under src/test/resources so that Maven adds it automatically to the classpath during the tests. Second, this implies that you can't use the Files utility to read it.
You will need to resort to using a traditional BufferedReader:
public Fixture(String fixtureName) throws IOException {
try (BufferedReader br = new BufferedReader(new InputStreamReader(Fixture.class.getResourceAsStream(FIXTURES_PATH + fixtureName)))) {
// do your thing with br.readLine();
}
}
Note the path given to getResourceAsStream is either relative to the current class or absolute. If the resources is located in src/test/resources/folder/allDepartments.json then a valid path would be /folder/allDepartments.json.
Add allDepartments.json to the.classpath file of the project and java should be able to pick it up.
Refer this topic if you want to know how to add a file to class path from eclipse
when you run Fixtures.java the relative path would be
../fixtures/allDepartments.json
try using this path.
Thank you all for helping and suggestions.
Thanks to you I was able to put things working, so here is the trick (which I guess only works for Maven projects):
I moved the allDepartments.json file to the default src/test/resources folder as suggested by you guys. I didn't even had to modify the pom.xml. And now everything works!
So this is my project structure now:
And the final Fixture.java code is:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
public final class Fixture {
private final String fixture;
public Fixture(String fixtureName) throws IOException {
fixture = this.readFile(fixtureName);
}
private String readFile(String fileName) throws IOException {
final InputStream in = this.getClass().getClassLoader().getResource("fixtures/" + fileName).openStream();
final BufferedReader buffer = new BufferedReader(new InputStreamReader(in));
try {
return buffer.lines().collect(Collectors.joining("\n"));
} finally {
buffer.close();
}
}
public final String getFixture() {
return fixture;
}
}

How to run Spring Shell scripts in a JUnit test

I have a Spring Shell-based application and a couple of scripts. Is there an easy way to run the scripts in a JUnit test such that a test fails, if some exception/error occurs during the execution of the script?
The purpose of the tests is to make sure that all correct scripts run without errors.
Update 1:
Here's a little helper class for running scripts in JUnit:
import org.apache.commons.io.FileUtils;
import org.springframework.shell.Bootstrap;
import org.springframework.shell.core.CommandResult;
import org.springframework.shell.core.JLineShellComponent;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.fest.assertions.api.Assertions.*;
public class ScriptRunner {
public void runScript(final File file) throws IOException
{
final Bootstrap bootstrap = new Bootstrap();
final JLineShellComponent shell = bootstrap.getJLineShellComponent();
final List<String> lines = FileUtils.readLines(file);
for (final String line : lines) {
execVerify(line, shell);
}
}
private void execVerify(final String command, final JLineShellComponent shell) {
final CommandResult result = shell.executeCommand(command);
assertThat(result.isSuccess()).isTrue();
}
}
You can create an instance of Bootstrap, get the shell out of it and then executeCommand() (including the shell command) on it.
You may be interested in what is done in Spring XD for this: https://github.com/spring-projects/spring-xd/blob/master/spring-xd-shell/src/test/java/org/springframework/xd/shell/AbstractShellIntegrationTest.java (although there are a lot of XD specific details)

How do I programmatically run all the JUnit tests in my Java application?

From Eclipse I can easily run all the JUnit tests in my application.
I would like to be able to run the tests on target systems from the application jar, without Eclipse (or Ant or Maven or any other development tool).
I can see how to run a specific test or suite from the command line.
I could manually create a suite listing all the tests in my application, but that seems error prone - I'm sure at some point I'll create a test and forget to add it to the suite.
The Eclipse JUnit plugin has a wizard to create a test suite, but for some reason it doesn't "see" my test classes. It may be looking for JUnit 3 tests, not JUnit 4 annotated tests.
I could write a tool that would automatically create the suite by scanning the source files.
Or I could write code so the application would scan it's own jar file for tests (either by naming convention or by looking for the #Test annotation).
It seems like there should be an easier way. What am I missing?
According to a recent thread on the JUnit mailing list, ClasspathSuite can collect and run all JUnit tests on the classpath. It is not precisely what you want, since it is a class-level annotation, but the source is available, so you may be able to extend its internal discovery mechanism.
I ran into a minor problem with my last solution. If I ran "all tests" from Eclipse they ran twice because they ran the individual tests AND the suite. I could have worked around that, but then I realized there was a simpler solution:
package suneido;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class RunAllTests {
public static void run(String jarfile) {
String[] tests = findTests(jarfile);
org.junit.runner.JUnitCore.main(tests);
}
private static String[] findTests(String jarfile) {
ArrayList<String> tests = new ArrayList<String>();
try {
JarFile jf = new JarFile(jarfile);
for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements();) {
String name = e.nextElement().getName();
if (name.startsWith("suneido/") && name.endsWith("Test.class")
&& !name.contains("$"))
tests.add(name.replaceAll("/", ".")
.substring(0, name.length() - 6));
}
jf.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return tests.toArray(new String[0]);
}
public static void main(String[] args) {
run("jsuneido.jar");
}
}
Based on http://burtbeckwith.com/blog/?p=52 I came up with the following. It seems to work well.
I can run it from within my code with:
org.junit.runner.JUnitCore.main("suneido.AllTestsSuite");
One weak point is that it relies on a naming convention ("Test" suffix) to identify tests. Another weak point is that the name of the jar file is hard coded.
package suneido;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
/**
* Discovers all JUnit tests in a jar file and runs them in a suite.
*/
#RunWith(AllTestsSuite.AllTestsRunner.class)
public final class AllTestsSuite {
private final static String JARFILE = "jsuneido.jar";
private AllTestsSuite() {
}
public static class AllTestsRunner extends Suite {
public AllTestsRunner(final Class<?> clazz) throws InitializationError {
super(clazz, findClasses());
}
private static Class<?>[] findClasses() {
List<String> classFiles = new ArrayList<String>();
findClasses(classFiles);
List<Class<?>> classes = convertToClasses(classFiles);
return classes.toArray(new Class[classes.size()]);
}
private static void findClasses(final List<String> classFiles) {
JarFile jf;
try {
jf = new JarFile(JARFILE);
for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements();) {
String name = e.nextElement().getName();
if (name.startsWith("suneido/") && name.endsWith("Test.class")
&& !name.contains("$"))
classFiles.add(name.replaceAll("/", ".")
.substring(0, name.length() - 6));
}
jf.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static List<Class<?>> convertToClasses(
final List<String> classFiles) {
List<Class<?>> classes = new ArrayList<Class<?>>();
for (String name : classFiles) {
Class<?> c;
try {
c = Class.forName(name);
}
catch (ClassNotFoundException e) {
throw new AssertionError(e);
}
if (!Modifier.isAbstract(c.getModifiers())) {
classes.add(c);
}
}
return classes;
}
}
}
I have not tried this as of yet, but came across this blog recently: http://burtbeckwith.com/blog/?p=52
The author provides a class that discovers all your junits and runs them, so if you slot this in to your project it may provide the capability required?
Hope this helps.
Get the Java project and pass the project
JUnitLaunchShortcut jUnitLaunchShortcut = new JUnitLaunchShortcut();
jUnitLaunchShortcut.launch("Pass the Java Project containing JUnits Classes", "run");
You also could use ANT which has built-in task.
Write ANT script and run it on target machine.
ANT could create report as result.

Categories

Resources