is there a way to specify the JVM version in a junit test, when multiple java types are available on an OS ?
I'd like to do something like this:
#JVM=1.5
public void test1(){
run();
}
#JVM=1.7
public void test2(){
run();
}
etc..
No, you'll have to run the JUnit tests multiple times with multiple VMs. You can then use Assume to only run the tests for the correct VM:
public void test1(){
// not compiled or tested
Assume.assumeThat(System.getProperty("java.version"), CoreMatchers.startsWith("1.5"));
run();
}
public void test2(){
Assume.assumeThat(System.getProperty("java.version"), CoreMatchers.startsWith("1.7"));
run();
}
Please note that I haven't compiled this, so there may be errors. Then, in your build tool, run these tests twice in two different VMs.
On JUnit 5, you can use EnabledOnJre and DisabledOnJre annotations.
#EnabledOnJre(JRE.JAVA_8)
void testMyMethodInJava8() {
...
}
#DisabledOnJre(JRE.JAVA_8)
void testMyMethodInOtherVersions() {
...
}
You can also apply these to a whole test class:
#EnabledOnJre(JRE.JAVA_11)
public class MyClassTest {
...
}
You still need to run the test suite separately for each JVM, but this allows you to skip the tests that will not work in one or the other.
JUnit test cases are just a bunch of Java classes, not a standalone program. So they would still be confined within the same JVM. AFAIK there is no simple way to do what you intend to do. What you can do is separate the test cases into test suites for each java version you want to test for. Then change the java version in the project settings and run the appropriate test suites.
Also there is a junit.jvm property, but I am not sure if you can change it mid-execution. Have you taken a look at it?
Related
My team received ownership of a webapp. Tests are written with junit suites and serenity. Good things, there a good test coverage. Problem come when you need to run that single test/scenario that is still failing and you need to wait >30min to run everything.
How can I run a single scenario of this suite using mvn command line?
From code editor, it's hard to start single scenario as both suite and test classes contains important initialization code.
I've also tried argument '-Dtest=T1Test#T1Scenario1' without success.
Code snipplet:
#RunWith(Suite.class)
#Suite.SuiteClasses({
UserConfigASuite.class,
UserConfigBSuite.class,
UserConfigCSuite.class
})
public class AllTestSuite {
}
#RunWith(Suite.class)
#Suite.SuiteClasses({
T1Test.class,
T2Test.class,
//... Lots of other tests
})public class UserConfigASuite {
#BeforeClass
public static void beforeClass() {
//Required init code
}
#AfterClass
public static void afterClass() {
//Cleanup after test suite
}
}
#RunWith(SerenityRunner.class)
public class T1Test {
#Test
#Title("T1: scenario 1")
public void T1Scenario1() {
}
//... Lots of other scenarios
}
Just confirm first that your using supported surefire and junit version. For more details refer https://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html
In case your using maven failsafe plugin then the syntax will vary little bit. Something like this
mvn -Dit.test=ITCircle#test* verify
Refer https://maven.apache.org/surefire/maven-failsafe-plugin/examples/single-test.html for more details.
I'm looking for the ability to nest JUnit tests. I found #RunWith(Enclosed.class), but it only runs one level inclosed and other tests aren't run.
Never mind, I found the answer over here: NitorCreations Nested Runner
This is exactly what I was looking for. It allows JUnit tests to be fully nested.
Because NestedRunner tests did not properly visualize test names in my IntelliJ IDEA I am using HierarchicalContextRunner instead
It provides exactly the same functionality. Just swap them in the #RunWith if you are not happy with how your IDE is showing your tests.
Here is an example of what was wrong:
#RunWith(NestedRunner.class)
public class ATest {
#Test
public void haveARegularTestsInside() {}
public class hasASubClass {
#Test
public void thatHasTests() {}
}
}
looks like this:
Here I expected to have thatHasTests at the last line, but got the whole AClass$hasASubClass.thatHasTests.
change #RunWith to HierarchicalContextRunner and what you get is now this:
Better, isn't it?
When writing code that interacts with external resources (such as using a web service or other network operation), I often structure the classes so that it can also be "stubbed" using a file or some other input method. So then I end up using the stubbed implementation to test other parts of the system and then one or two tests that specifically test calling the web service.
The problem is I don't want to be calling these external services either from Jenkins or when I run all of the tests for my project (e.g. "gradle test"). Some of the services have side effects, or may not be accessible to all developers.
Right now I just uncomment and then re-comment the #Test annotation on these particular test methods to enable and disable them. Enable it, run it manually to check it, then remember to comment it out again.
// Uncomment to test external service manually
//#Test
public void testSomethingExternal() {
Is there is a better way of doing this?
EDIT: For manual unit testing, I use Eclipse and am able to just right-click on the test method and do Run As -> JUnit test. But that doesn't work without the (uncommented) annotation.
I recommend using junit categories. See this blog for details : https://community.oracle.com/blogs/johnsmart/2010/04/25/grouping-tests-using-junit-categories-0.
Basically, you can annotate some tests as being in a special category and then you can set up a two test suites : one that runs the tests of that category and one that ignores tests in that category (but runs everything else)
#Category(IntegrationTests.class)
public class AccountIntegrationTest {
#Test
public void thisTestWillTakeSomeTime() {
...
}
#Test
public void thisTestWillTakeEvenLonger() {
....
}
}
you can even annotate individual tests"
public class AccountTest {
#Test
#Category(IntegrationTests.class)
public void thisTestWillTakeSomeTime() {
...
}
Anytime I see something manually getting turned on or off I cringe.
As far as I can see you use gradle and API for JUnit says that annotation #Ignore disables test. I will add gradle task which will add #Ignore for those tests.
If you're just wanting to disable tests for functionality that hasn't been written yet or otherwise manually disable some tests temporarily, you can use #Ignore; the tests will be skipped but still noted in the report.
If you are wanting something like Spring Profiles, where you can define rulesets for which tests get run when, you should either split up your tests into separate test cases or use a Filter.
You can use #Ignore annotation to prevent them from running automatically during test. If required, you may trigger such Ignored tests manually.
#Test
public void wantedTest() {
return checkMyFunction(10);
}
#Ignore
#Test
public void unwantedTest() {
return checkMyFunction(11);
}
In the above example, unwantedTest will be excluded.
I am trying to setup TestNG so that it gives me new instances of my class variable for each test (basically like JUnit). I need this as I intend to parallelize my tests at the method level. I have been experimenting with both standalone Guice and the built in Guice functionality that TestNG provides to try to accomplish this but I have had no luck. I know that I can use ThreadLocal, but calling .get() for every variable in the test is pretty unappealing. I am weary of using GuiceBerry as it does not really have a lot of updates/activity and it's last release is not even acquirable via Maven. I am pretty set on TestNG as for all the inconvenience this is causing me it still does a lot of great things. I am open to things other tools though to accomplish my goal. Basically I want things setup so the below tests would work consistently. Any help would be greatly appreciated.
// just has a variable thats a class called child with a simple string variable
// with a value of "original
Parent p;
#Test
public void sometest1(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
#Test
public void sometest2(){
Assert.assertTrue(p.child.value.equals("original"));
}
TestNG doesn't create a new instance for each test. If you want such a behavior than I recommend creating separate test classes. e.g.:
public class SomeTest1 {
Parent p;
#Test
public void something(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
}
public class SomeTest2 {
Parent p;
#Test
public void something(){
Assert.assertTrue(p.child.value.equals("original"));
}
}
Note that TestNG can run JUnit 3 and JUnit 4 tests (you might maintain a mixed suite depending on the style you want to use in a given test class).
We have recently upgraded on Java 7, but after that our suite is facing weird issue that it is first executing method with #After annotation and then methods with #Test annotation.
Any help will appreciated.
Thanks in advance
EDIT: This is the code from the comment:
public class TestClasse extends TestCase {
#Test public void testLogin(){ System.out.println("TestCase1"); }
#Test public void testLogout(){ System.out.println("TestCase2"); }
#After public void testGenerateReport(){ System.out.println("testCase3") }
}
This is your code:
public class TestClasse extends TestCase {
#Test public void testLogin(){ System.out.println("TestCase1"); }
#Test public void testLogout(){ System.out.println("TestCase2"); }
#After public void testGenerateReport(){ System.out.println("testCase3") }
}
You are using JUnit 3 (because you're extending TestCase), so JUnit is running all of the methods which begin with 'test'.
The solution: don't extend TestCase, and make sure that your classpath includes JUnit 4 (4.11 is the latest). Also, to avoid confusion, don't name your #After methods testXXX.
Why did it stop working when you upgraded to Java 7?
When you are searching for methods in Java 6 and before, in most cases the JVM returns the methods in the order in which they are declared in the source file (in your case testLogin, testLogout, testGenerateReport). This changed with Java 7, so that the methods are returned in a different unpredictable order (see my answer to Has JUnit4 begun supporting ordering of test? Is it intentional?). So, when you upgraded to Java 7, the order in which the methods were found and executed changed - and your #After was executed first.
For more background to this issue, see Sort test methods for predictability and SortMethodsWith allows the user to choose the order of execution of the methods within a test class.