Wrong order of running JUnit's methods in IDEA - java

I have a problem with Idea 14 and JUnit. I can't run #BeforeClass and #AfterClass methods in proper order (before all test and after all test). Every time order is different. I tried to reinstall IDEA, delete all settings but nothing works. Please help. This is example of my test code:
package com.rent.test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import static org.junit.Assert.*;
import org.junit.Test;
public class testnewTest {
static int num;
static int num1;
#BeforeClass
public static void OnceExecutedBeforeAll() {
System.out.println("#BeforeClass: onceExecutedBeforeAll");
num = 15;
num1 = 16;
}
#AfterClass
public static void after() throws Exception {
System.out.println("End");
}
#Test
public void testLogin() throws Exception {
System.out.println("test");
assertEquals(15, num);
}
#Test
public void testGetOrdersDate() throws Exception {
System.out.println("test2");
assertEquals(16, num1);
}
}
This is output:
test2
#BeforeClass: onceExecutedBeforeAll
test
End

What you're likely observing is the fact that the output is not always going to be synchronous in the terminal. The test themselves are running in the correct sequence.
If they weren't, then you would have failures in test2 given that it would have appeared that your #BeforeClass method fired afterwards.

Related

How to exclude the time taken by the #AfterClass method?

I ran the following test class and it reported that the first test took 2 seconds and the second took 4 seconds. I expected JUnit to output the time for each test case without putting into account the time of the #BeforeClass or #AfterClass method.
But obviously it includes the time of the #AfterClass method into only the last test case, which doesn't make sense at all if you ask me.
Is there a way make JUnit output the times only for the time taked for each test case ?
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TimeTest {
#Test
public void test1() throws InterruptedException {
Thread.sleep(2000);
}
#Test
public void test2() throws InterruptedException {
Thread.sleep(2000);
}
#AfterClass
public static void afterClass() throws InterruptedException {
Thread.sleep(2000);
}
}
#BeforeClass & #AfterClass run ones for all tests
what you should do is to use #Before, and After instead, with the help of an instance variable
public class TimeTest {
long timeInMillis=0;
#Before
public void before(){
timeInMillis = System.currentTimeMillis();
}
#Test
public void test1() throws InterruptedException {
Thread.sleep(2000);
}
#Test
public void test2() throws InterruptedException {
Thread.sleep(2000);
}
#After
public static void after() throws InterruptedException {
long diff = System.currentTimeMillis() - timeInMillis;
// log the diff or cast it to seconds
}
}
You are not the first one with such a problem. There are a lot of examples of time logging on the internet.
I suggest you to use JUnit #Rules to solve your problem and avoid a code-duplication. (You don't want to write timeInMillis = System.currentTimeMillis() in each test class, do you?)
There is an example of rule implementation

#Before and #After not working with JUnit 5 on Eclipse 2018-12 JAVA

I just created a test class from File->New->JUnit Test Cases and this is my whole code:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.Test;
class TestingJUnit {
#Before
public void testOpenBrowser() {
System.out.println("Opening Chrome browser");
}
#Test
public void tesingNavigation() {
System.out.println("Opening website");
}
#Test
public void testLoginDetails() {
System.out.println("Enter Login details");
}
#After
public void testClosingBrowser() {
System.out.println("Closing Google Chrome browser");
}
}
But when I run this cas only #Test annotations are running #Before and #After annotations code are not running. Please guide me I think this is JUnit version or eclipse IDE version problem, and also my all Test classes not running in TestSuit I don't know why although Test Classes are running fine individually.
My TestSuit Class is here:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(Suite.class)
#SuiteClasses({TestingJUnit.class, SecondTest.class})
public class TestSuit {
}
Try using #BeforeEach instead of #Before and #AfterEach instead of #After
Try Using This
#BeforeEach
public void before() {
System.out.println("Before");
}
#AfterEach
public void after() {
System.out.println("After");
}
#Test
public void sum_with3numbers() {
System.out.println("Test 1");
}
#Test
public void sum_with1numbers() {
System.out.println("Test 2");
}
Output will be:
Before
Test 1
After
Before
Test 2
After

strange things with btrace and java.lang.NoSuchMethodError

the main class:
package com.xxx.yyy;
public class Hello{
public static void main(String[] args){
A a = new A();
while(true){
try {
a.execute(1000);
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
class A:
package com.xxx.yyy;
public class A{
public void execute(int sleepTime) throws Exception {
System.out.println("sleep time is "+sleepTime);
}
}
btrace script:
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.str;
import static com.sun.btrace.BTraceUtils.strcat;
import static com.sun.btrace.BTraceUtils.timeMillis;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.ProbeClassName;
import com.sun.btrace.annotations.ProbeMethodName;
import com.sun.btrace.annotations.TLS;
#BTrace
public class BtraceTest{
#OnMethod(clazz="com.xxx.yyy.A",method="execute",location=#Location(Kind.RETURN))
public static void traceExecute(#ProbeClassName String name,#ProbeMethodName String method,int sleepTime){
println(strcat("the class name=>", name));
println(strcat("the class method=>", method));
println(strcat("the class method params=>", str(sleepTime)));
}
}
everything is right.
BUT: when I move the line Thread.sleep(1000) to class A's execute function, like this:
package com.xxx.yyy;
public class A{
public void execute(int sleepTime) throws Exception {
System.out.println("sleep time is "+sleepTime);
Thread.sleep(1000);
}
}
the NoSuchMethodError is thrown by Hello.
Exception in thread "main" java.lang.NoSuchMethodError: com.xxx.yyy.A.$btrace$BtraceTest$traceExecute(Ljava/lang/String;Ljava/lang/String;I)V
at com.xxx.yyy.A.execute(Unknown Source)
at com.xxx.yyy.Hello.main(Hello.java:8)
my environment is
java version "1.8.0_121"
BTrace v.1.3.9 (20170111)
anyone can explain why?thanks!
I think your class should implements Runnable or extends Thread. Then only you can use start, sleepand such similar methods in your program. Have a look at here to know how to implement thread methods.

why this is not working - Unit testing a synchronous method using parameterized data of Junit?

I am trying to learn the JUnit and wanted to extend it to test in a multi-threaded way.
The class I want to test is PrimeNumberValidator. This just tests if a passed in number is prime or not.
package com;
public class PrimeNumberValidator {
public Boolean validate(final Integer primeNumber) {
System.out.println("Validating .............:" + primeNumber);
for (int i = 2; i < (primeNumber / 2); i++) {
if (primeNumber % i == 0) {
return false;
}
}
return true;
}
}
The PrimeNumberValidatorTest is the test class. The 2 of the test data are wrong and I have done this purposely to test for failure.
The test method testPrimeNumberValidator runs perfectly fine. But, the multi-threaded version testMultiThreadedPrimeNumberValidator always says 'pass' for even wrong data.
Why is this happening like this? How do solve this ?
package com;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
#RunWith(Parameterized.class)
public class PrimeNumberValidatorTest {
private Integer primeNumber;
private Boolean expectedValidation;
private PrimeNumberValidator primeNumberValidator;
#Before
public void initialize() {
primeNumberValidator = new PrimeNumberValidator();
}
// Each parameter should be placed as an argument here
// Every time runner triggers, it will pass the arguments from parameters we defined
public PrimeNumberValidatorTest(Integer primeNumber, Boolean expectedValidation) {
this.primeNumber = primeNumber;
this.expectedValidation = expectedValidation;
}
#Parameterized.Parameters
public static Collection primeNumbers() {
return Arrays.asList(new Object[][] {
{ 2, Boolean.FALSE},// 2 is prime so Test should fail
{ 6, Boolean.FALSE}, //is NOT prime so test should pass
{ 19, Boolean.TRUE},//is prime so test should pass
{ 22, Boolean.TRUE} //is NOT prime so test should fail
});
}
// This test will run 4 times since we have 4 parameters defined
#Test
public void testPrimeNumberValidator() {
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}
#Test
public void testMultiThreadedPrimeNumberValidator() {
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}
}
});
}
}
Referring to http://www.youtube.com/watch?v=wDN_EYUvUq0 as mentioned in one of the posts Weird problem using JUnit in multi-thread environment, tried as below. The exceptions are thrown, but the JUnit does not report failure :(
package com;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
#RunWith(Parameterized.class)
public class PrimeNumberValidatorTest {
volatile Exception exception;
volatile Error error;
private Integer primeNumber;
private Boolean expectedValidation;
private PrimeNumberValidator primeNumberValidator;
#Before
public void initialize() {
primeNumberValidator = new PrimeNumberValidator();
}
// Each parameter should be placed as an argument here
// Every time runner triggers, it will pass the arguments from parameters we defined
public PrimeNumberValidatorTest(Integer primeNumber, Boolean expectedValidation) {
this.primeNumber = primeNumber;
this.expectedValidation = expectedValidation;
}
#Parameterized.Parameters
public static Collection primeNumbers() {
return Arrays.asList(new Object[][] {
{ 2, Boolean.FALSE},// 2 is prime so Test should fail
{ 6, Boolean.FALSE}, //is NOT prime so test should pass
{ 19, Boolean.TRUE},//is prime so test should pass
{ 22, Boolean.TRUE} //is NOT prime so test should fail
});
}
// This test will run 4 times since we have 4 parameters defined
#Test
#Ignore
public void testPrimeNumberValidator() {
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}
#Test
public void testMultiThreadedPrimeNumberValidator() {
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < 1; i++) {
try{
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}catch(Error e){
System.out.println("error thrown :" + e);
error =e;
}catch(Exception e){
exception=e;
System.out.println("exception thrown :" + e);
}
}
}
});
}
#After
public void runAfterEveryTest() throws Exception{
if(null != error){
System.out.println("runAfterEveryTest throwing error...............");
throw error;
}
if(null != exception){
System.out.println("runAfterEveryTest throwing exception...............");
throw exception;
}
}
}
The reason the multi-threaded is always passing is the following:
first, the test method does nothing to wait for the multiple threads to complete therefore the #Test method is exiting before any errors are reported
second, the way that testing works is that the assert method throws an exception. The JUnit framework catches this exception by wrapping the #Test method and fails the test if an unexpected exception is thrown. However, in the multi-threaded test no exception is thrown from the #Test method because they are thrown within the threads and the test method does nothing to check this. One solution for this part would be to use an ErrorCollector
It got resolved with the below code. The addtion of Future related code made it work.
#Test
public void testMultiThreadedPrimeNumberValidator() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(100);
Future future = executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try{
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}catch(Error e){
System.out.println("error thrown :" + e);
//error =e;
System.out.println("error set to :" + e);
}catch(Exception e){
System.out.println("exception thrown :" + e);
//exception=e;
System.out.println("Exception set to :" + e);
}
}
}
});
future.get();
}

Re-run failed test using Junit

I'm trying to improve an existing system of automated Selenium test.
My goal is to repeat the tests that fails because of connections problem.
I've found and tried to follow this thread How to Re-run failed JUnit tests immediately? that revealed itself quite useful.
In my case the suite is composed by classes, so I've tried to substitute #Rule with #ClassRule, in order to repeat for each try also the #Before and #After parts.
I'm sorry for my ignorance, but where am I supposed to place this rule? In my Suite class? Or in the Classes representing the test?
I am the original answerer of How to Re-run failed JUnit tests immediately?
If I understand correctly, the problem that you are having is due to the #Before being executed before the code in the RetryRule, and the #After being executed afterwards.
So your current behaviour is something like:
#Before
#Retry
test code
#Retry
#After
But you can implement your #Before and #After as a rule - there is a rule ExternalResource which does exactly that. You would implement #Before and #After as a rule:
#Rule public ExternalResource beforeAfter = new ExternalResource() {
public void before() {
// code that was in #Before
}
public void after() {
// code that was in #After
}
}
Then you don't need the #Before and #After. You can then chain these rules using RuleChain. This forces an order of execution to your rules:
#Rule public RuleChain chain= RuleChain
.outerRule(new LoggingRule("outer rule")
.around(new LoggingRule("middle rule")
.around(new LoggingRule("inner rule");
so your final solution would be something like:
private ExternalResource beforeAfter = ...
private RetryRule retry = ...
#Rule public RuleChain chain = RuleChain
.outerRule(retry)
.around(beforeAfter);
Note that if you are using RuleChain, you no longer need the #Rule annotation on the ExternalResource and RetryRule, but you do on the RuleChain.
Here is my solution based on the one mentionned in the question.
It's a combinaison of a #Rule, FailedRule and a #ClassRule, RetryRule
public class RetryTest
{
public static class FailedRule implements TestRule
{
#Override
public Statement apply(final Statement base, final Description description)
{
return new Statement()
{
#Override
public void evaluate() throws Throwable
{
try
{
base.evaluate();
}
catch (Throwable t)
{
System.out.println(description.getDisplayName() + " failed");
retry.setNotGood();
if (retry.isLastTry())
{
System.out.println("No more retry !");
throw t;
}
else
{
System.out.println("Retrying.");
}
}
}
};
}
}
public static class RetryRule implements TestRule
{
private int retryCount, currentTry;
private boolean allGood = false;
public RetryRule(int retryCount)
{
this.retryCount = retryCount;
this.currentTry = 1;
}
public boolean isLastTry()
{
return currentTry == retryCount;
}
public void setNotGood()
{
allGood = false;
}
public Statement apply(final Statement base, final Description description)
{
return new Statement()
{
#Override
public void evaluate() throws Throwable
{
// implement retry logic here
for (; currentTry <= retryCount && !allGood; currentTry++)
{
allGood = true;
System.out.println("Try #" + currentTry);
base.evaluate();
}
}
};
}
}
#ClassRule
public static RetryRule retry = new RetryRule(3);
#Rule
public FailedRule onFailed = new FailedRule();
#BeforeClass
public static void before()
{
System.out.println("Before...");
}
#AfterClass
public static void after()
{
System.out.println("...After\n");
}
#Test
public void test1()
{
System.out.println("> test1 running");
}
#Test
public void test2()
{
System.out.println("> test2 running");
Object o = null;
o.equals("foo");
}
}
It gives :
Try #1
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After
Try #2
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After
Try #3
Before...
> test1 running
> test2 running
test2(RetryTest) failed
No more retry !
...After
If I am commenting the o.equals("foo"); in test2, everything runs fine in the firt try :
Try #1
Before...
> test1 running
> test2 running
...After
You decorate the test name itself with the #After or #Afterclass attributes:
#After
#Test
#Category(SmokeTests.class)
public void testProductPageOnly() throws TimeoutException {
//Some tests here.
}
#Afterclass
public static void SomeTest {
//Some test here.
}
Something to note, #Afterclass will always run; even if you are using a #Beforeclass that throws an exception.
May this can solve problem:
1) Test class should be inherited from junit.framework.TestCase
2) Run your tests with something like this
YourTestClass testClass = new YourTestClass();
TestResult result = testClass.run();
Enumeration<TestFailure> failures = result.failures();
if (result.failureCount() != 0)
{
TestFailure fail = failes.nextElement();
junit.framework.Test test = fail.failedTest();
test.run( result );
}
At the end result will contains last results of test running, so after analyzing what test was failed you can run it again.

Categories