Run single test from a JUnit class using command-line - java

I am trying to find an approach that will allow me to run a single test from a JUnit class using only command-line and java.
I can run the whole set of tests from the class using the following:
java -cp .... org.junit.runner.JUnitCore org.package.classname
What I really want to do is something like this:
java -cp .... org.junit.runner.JUnitCore org.package.classname.method
or:
java -cp .... org.junit.runner.JUnitCore org.package.classname#method
I noticed that there might be ways to do this using JUnit annotations, but I would prefer to not modify the source of my test classes by hand (attempting to automate this). I did also see that Maven might have a way to do this, but if possible I would like to avoid depending on Maven.
So I am wondering if there is any way to do this?
Key points I'm looking for:
Ability to run a single test from a JUnit test class
Command Line (using JUnit)
Avoid modifying the test source
Avoid using additional tools

You can make a custom, barebones JUnit runner fairly easily. Here's one that will run a single test method in the form com.package.TestClass#methodName:
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
public class SingleJUnitTestRunner {
public static void main(String... args) throws ClassNotFoundException {
String[] classAndMethod = args[0].split("#");
Request request = Request.method(Class.forName(classAndMethod[0]),
classAndMethod[1]);
Result result = new JUnitCore().run(request);
System.exit(result.wasSuccessful() ? 0 : 1);
}
}
You can invoke it like this:
> java -cp path/to/testclasses:path/to/junit-4.8.2.jar SingleJUnitTestRunner
com.mycompany.product.MyTest#testB
After a quick look in the JUnit source I came to the same conclusion as you that JUnit does not support this natively. This has never been a problem for me since IDEs all have custom JUnit integrations that allow you to run the test method under the cursor, among other actions. I have never run JUnit tests from the command line directly; I have always let either the IDE or build tool (Ant, Maven) take care of it. Especially since the default CLI entry point (JUnitCore) doesn't produce any result output other than a non-zero exit code on test failure(s).
NOTE:
for JUnit version >= 4.9 you need hamcrest library in classpath

I use Maven to build my project, and use SureFire maven plugin to run junit tests.
Provided you have this setup, then you could do:
mvn -Dtest=GreatTestClass#testMethod test
In this example, we just run a test method named "testMethod" within Class "GreatTestClass".
For more details, check out http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html

The following command works fine.
mvn -Dtest=SqsConsumerTest -DfailIfNoTests=false test

We used IntelliJ, and spent quite a bit of time trying to figure it out too.
Basically, it involves 2 steps:
Step 1: Compile the Test Class
% javac -cp .:"/Applications/IntelliJ IDEA 13 CE.app/Contents/lib/*" SetTest.java
Step 2: Run the Test
% java -cp .:"/Applications/IntelliJ IDEA 13 CE.app/Contents/lib/*" org.junit.runner.JUnitCore SetTest

Related

How to run a Gatling simulation from java code without maven and gradle?

I would like to execute my Gatling simulation from within Java code and not with a command maven or gradle. Is it possible to run the tests/scenarios directly from Java code?
Option 1:
If you want to run Gatling from code you can invoke this class:
io.gatling.app.Gatling
Source code:
https://github.com/gatling/gatling/blob/master/gatling-app/src/main/scala/io/gatling/app/Gatling.scala
I probably wouldn't call main directly but rather the start function or custom start function like that. Here is an attempt at that or.
Something like this (copied from the link above):
import io.gatling.app.Gatling
import io.gatling.core.config.GatlingPropertiesBuilder
object Engine extends App {
val props = new GatlingPropertiesBuilder
props.simulationClass("your.simulation.class.goes.here")
props.dataDirectory("path.to.data.directory") //optional
props.resultsDirectory("path.to.results.directory") //optional
props.bodiesDirectory("path.to.template.directory") //optional
props.binariesDirectory("path.to.binaries.directory") //optional
Gatling.fromMap(props.build)
}
Option 2:
(Compilation Phase) Use Maven archetype to generate helper classes (you probably need to compile your Java anyway). Docs. This will generate Engine (code) and other classes which you can run. This is similar to Option 1 but helps to resolve paths if you are working from a maven project. Makes sense if you use maven to build your project.
Option 3:
Invoke gatling.sh or gatling.bat as a process from Java with Runtime.getRuntime().exec() or similar.
Bear in mind:
Gatling tests need to be compiled before they are executed. This is basically what gatling.[sh|bat] is doing:
# Run the compiler
"$JAVA" $COMPILER_OPTS -cp "$COMPILER_CLASSPATH" io.gatling.compiler.ZincCompiler $EXTRA_COMPILER_OPTIONS "$#" 2> /dev/null
# Run Gatling
"$JAVA" $DEFAULT_JAVA_OPTS $JAVA_OPTS -cp "$GATLING_CLASSPATH" io.gatling.app.Gatling "$#"
If you call Scala code from Java there is definitely inter-op available. Make sure Scala is compiled first in your case or can be loaded in Java CP easily. Create Java friendly wrapper if needed on Scala side.
I would start with Option 1 or 2 if you want tight integration and with option 3 if you just want to glue things together and don't mind startup/init time.
Pay attention to Classpath needed for Gatling - this will depend where its classes are located (in your proj or outside) and how you invoke it.
You can definitely pass test names, just see how the arguments are used in those classes. For example simulationClass in props. All available methods (simulationsDirectory, simulationClass, etc).
I'm sure it will take a bit of trial and error but definitely can be done.

Run specific junit4 categories using gradle

I am running some tests on an Android phone using gradle. However I would like to be able to select which tests to run. For the tests I am using jUnit4 and categories.
This is how the tests are build and executed from jenkins:
call gradle assembleDebug assembleDebugAndroidTest
call gradle connectedDebugAndroidTest
This is how a test looks like:
#Category(IncludeTest.class)
#Test
public void test_Test_06() throws Exception {
TestData.setUpTest("test_Test_06");
Log.d("Test: Test 6 included");
}
#Category(ExcludeTest.class)
#Test
public void test_Test_07() throws Exception {
TestData.setUpTest("test_Test_07");
Log.d("Test: Test 7 excluded");
}
In my gradle.build I have tried the following without success:
test {
useJUnit {
includeCategories 'com.abc.def.IncludeTest'
excludeCategories 'com.abc.def.ExcludeTest'
}
}
My structure is as follows:
/someFolder/gradle.build
/someFolder/app/src/android/java/
In java i have a package named com.abc and in that package there is another package, def where my IncludeTest and ExcludeTest interfaces are.
I have tried different paths to Include/ExludeTest in gradle.build but it just does not work, all test all always executed.
I have also tried putting the includeCategories/excludeCategories in a task and made sure the task was actually started. But still all test were executed. Just seems like includeCategories/excludeCategories does not do anything.
Is there anything basic I am doing wrong? Are there any other ways of selecting categories?
After some more research I found out that the includeCategories/excludeCategories does not work with Android.
I found a different solution when using AndroidJUnitRunner. In Gradle it is possible to filter tests on annotations. To include annotations:
call gradle connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.abc.def.IncludeTest
There is also the possibility to exclude annotations using notAnnotation instead.
And of course there is syntax if you want to use multiple annotations with OR/AND combinations.
The following is also possible if you are not using connectedDebugAndroidTest:
adb shell am instrument -w -e annotation com.android.foo.MyAnnotation com.android.foo/android.support.test.runner.AndroidJUnitRunner
Some documentation: https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html

Jenkins - Selecting tests

I am currently working on a Maven Project, using JUnit for defining tests and Jenkins for CI and am looking into how I can group my tests.
Say I had a test class with 20 tests, but I don't want to run all 20 tests, I want to be able to configure which tests to run. For Example, in another standalone project using TestNG and Selenium you can create a test method with the following annotation:
#Test (groups = { "AllTest" })
public void myTestMethod()
{
.. do something
.. assert something
}
... and then I am able to call which group to run based on an XML configuration.
Is it possible to define such type of groupings using Jenkins? I have researched into this and came across the plugin "Tests Selector Plugin" however can't understand how to get started once I've installed the plugin. There is a Wiki Page for it but I can't understand what to do after installing.
I have copy pasted the example property file, and didn't really understand what I needed to manipulate in it. When building, I simply get that the property file cannot be found or Jenkins doesn't have permission; can't find a way around this either :(
It's possible via maven + maven-surefire-plugin
http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html
You can run a single test, set of tests or tests by regexp.

maven not running all subset of tests I ask it to when using #

I am trying to run a couple of tests from different classes, my command line is:
mvn -Dtest=com.MyComp.Selenium.SelTests.SomeTests1#XTest,com.MyComp.Selenium.SelTests.SomeTests1#YTest,com.MyComp.Selenium.SelTests.SomeTests2#ZTest
When I run this I would expect it to run XTest and YTest from the class SomeTests1 and ZTest from SomeTests2 but instead it just runs XTest and ZTest and skips YTest.
If I just tell it to run YTest or if I tell it to run all tests in SomeTests1 it works. Please can somebody see what I'm doing wrong?
I don't want to run all the tests in each class I just want a subset.
If you are using Junit 4.x and surefire 2.12.1 or greater then you can use the following syntax for running multiple tests in a class
mvn -Dtest=com.MyComp.Selenium.SelTests.SomeTests1#XTest+#YTest...
Note the + symbol. Here is the documentation

Run all tests in Junit 4

I want to be able to run all tests in a project programmatically. I know Eclipse has a "Run as JUnit test" configuration which somehow grabs all the tests in a project and run them. Is there any way for me to also grab the list of tests programmatically and run them? Or is there some good way to construct a test suite containing all the test cases without manually listing out every one (all 700+) of them?
I've tried the "New... -> Test Suite" option in Eclipse, but that seems to work only for JUnit 3, identifying tests by their extending from TestCase
The test classes are JUnit 4, so their only distinguishing characteristic is the annotation, no naming convention, no subclassing from TestCase.
Thanks in advance!
Though it does not really solve your immediate problem, I find it a very useful general practice to create suites and suites of suites, e.g. for a package something like PackageFooSuite etc. and assemble these suites in one or more suites again, like ModuleFooSuite and have one top-level suite, like AllTestsSuite. That way it's easy to run both all tests in one step as well as submodule tests for the package I'm currently working on (and have the tests run quicker than if I would always run all of them):
#RunWith(Suite.class)
#Suite.SuiteClasses({ PackageFooSuite.class, PackageBarSuite.class} )
public final class AllTestsSuite {} // or ModuleFooSuite, and that in AllTests
None of the other answers did it for me. I had 40k tests I needed to run, so manually listing every class was not an option.
I did it with ClasspathSuite. A test suite that runs all Junit4 and Junit3 test cases in the class path is as follows:
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.*;
import org.junit.runner.RunWith;
import org.junit.runner.JUnitCore;
import static org.junit.extensions.cpsuite.SuiteType.*;
#RunWith(ClasspathSuite.class)
#SuiteTypes({ JUNIT38_TEST_CLASSES, TEST_CLASSES })
public class RunAllSuite {
/* main method not needed, but I use it to run the tests */
public static void main(String args[]) {
JUnitCore.runClasses(RunAllSuite.class);
}
}
I needed to run it from command line, so this is what I did:
Downloaded cp-1.2.6.jar
Create the previously mentioned RunAllSuite
Compile the class, javac RunAllSuite.java -cp cpsuite-1.2.6.jar;junit-4.8.1.jar
run it with target tests in the class path, java -cp cpsuite-1.2.6.jar;junit-4.8.1.jar;path/to/runallsuite/folder;target/classes;target/test-classes RunAllSuite
And that's it. With the RunAllSuite above, anywhere in your code you can just do JUnitCore.runClasses(RunAllSuite.class), which runs all tests in class path. There are other config options as well which are explained in the ClasspathSuite home page.
Note also that the class given above does not print anything. If that is needed, you can do
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.*;
import org.junit.runner.RunWith;
import org.junit.runner.JUnitCore;
import org.junit.internal.TextListener;
import static org.junit.extensions.cpsuite.SuiteType.*;
#RunWith(ClasspathSuite.class)
#SuiteTypes({ JUNIT38_TEST_CLASSES, TEST_CLASSES })
public class RunAllSuite {
public static void main(String args[]) {
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(RunAllSuite.class);
}
}
You can do this fairly easily from within maven using the surefire plugin: I usually clean/compile/install my projects from the command line before comparing them for eclipse usage (mvn eclipse:clean eclipse:eclipse) and you can define a test suite in your pom which lists all the tests you want to run en masse every time you run mvn install. You're not calling them programatically, exactly, but you can certainly call them en masse.
In Eclipse (I'm using 4.6.1) - Right click the project folder, select "Run As", choose "JUnit Test"
It will run all tests in that project. Same for a package.
Of the top of my head using Spring:
Implement a TypeFilter that matches classes with methods annotated with #Test (don't forget to consider the superclasses)
Invoke classpath scanning on your top-most test package
Invoke the JUnitRunner with the scan results
More info on classpath scanning and custom type filters here
With Eclipse Indigo (possibly Helios as well) in the Run Configurations dialog box, you now have the ability to Run all tests in a selected project, package or source folder.
Also a good reference from Eclipse is the article Java Unit testing with JUnit 4.x in Eclipse.
I also recommend using the JUnit Suite annotations. Follow the link for more detail.

Categories