I have an issue that I am facing,
I have a class with multiple test cases and I am using test ng with java and selenium.
Is there a possibility that if a test case failed, testNG will run the entire class again?
not the test.
since there are a priority and navigation between pages.
Is there a way to run the entire class that is failed again? I just saw to rerun the test, and it is useless to me.
regards
If I understood you right this is the solution which you needed
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class Retry implements IRetryAnalyzer {
private int count = 0;
private static int maxTry = 3;
public boolean retry(ITestResult iTestResult) {
if (!iTestResult.isSuccess()) {
if (count < maxTry) {
count++;
iTestResult.setStatus(ITestResult.SUCCESS);
return true;
} else {
iTestResult.setStatus(ITestResult.FAILURE);
}
} else {
iTestResult.setStatus(ITestResult.FAILURE);
}
return false;
}
}
Then your all tests methods should be like this:
#Test(retryAnalyzer=Retry.class)
And you should add the BeforeSuite
#BeforeSuite(alwaysRun = true)
public void beforeSuite(ITestContext context) {
for (ITestNGMethod method : context.getAllTestMethods()) {
method.setRetryAnalyzerClass(Retry.class);
}
}
Related
What is the general approach in unit tests for methods that involve a sleep() call?
Lets say I have the class:
class Foo {
public bool someMethodWithSleep() {
bool failed = false;
for (int i = 0 : 5) {
failed = trySomething(); // mocked to return false
if (failed) {
TimeUnit.SECONDS.sleep(5);
} else { return true; }
}
return false;
}
}
In test cases for failures that call this function (directly or nested), I dont want it to sleep for 25+ seconds and slowing every test file that calls it. What's the best approach to skip the sleep calls in unit tests?
Replace it with a dependency.
class Foo {
private final Sleeper sleeper;
public Foo(final Sleeper sleeper) {
this.sleeper = sleeper;
}
public Foo() {
this(SecondsSleeper.INSTANCE);
}
public bool someMethodWithSleep() {
bool failed = false;
for (int i = 0 : 5) {
failed = trySomething(); // mocked to return false
if (failed) {
sleeper.sleep(5);
} else { return true; }
}
return false;
}
}
interface Sleeper {
void sleep(int duration);
}
enum SecondsSleeper implements Sleeper {
INSTANCE;
void sleep(final int seconds) {
TimeUnit.SECONDS.sleep(seconds);
}
}
enum TestSleeper implements Sleeper {
INSTANCE;
void sleepSeconds(final int duration) {
// do nothing
}
}
Then in your real application, create Foo as new Foo() and in your test as new Foo(TestSleeper.INSTANCE)
Can someone explain how does gradle works with priority parameter in #Test annotation in testng?
For example I have the next code:
public class TestGradle {
#Test (priority = 2)
public void testA() throws Exception {
System.out.println("Test A");
}
#Test (priority = 1)
public void testB() throws Exception {
System.out.println("Test B");
}
#Test (priority = 3)
public void testC() throws Exception {
System.out.println("Test C");
}
}
So if I will run it via gradle test --tests TestGradle I will get the next output:
Test A
Test B
Test C
but I thought, that it should be like this:
Test B
Test A
Test C
I think this is a bug in TestNG. I created an issue.
You can create a workaround to solve this problem.
With an IMethodInterceptor you can change the execution order of your methods.
public class ExecutionOrderInterceptor implements IMethodInterceptor {
#Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
Comparator<IMethodInstance> comparator = new Comparator<IMethodInstance>() {
private int getPriority(IMethodInstance mi) {
int result = 0;
Method method = mi.getMethod().getConstructorOrMethod().getMethod();
Test a1 = method.getAnnotation(Test.class);
if (a1 != null) {
result = a1.priority();
}
return result;
}
public int compare(IMethodInstance m1, IMethodInstance m2) {
return getPriority(m1) - getPriority(m2);
}
};
IMethodInstance[] array = methods.toArray(new IMethodInstance[methods.size()]);
Arrays.sort(array, comparator);
return Arrays.asList(array);
}
}
To use this interceptor you need to add an annotation to your test classes:
#Listeners({ TestReportListener.class })
public class MyTestClass {
...
You can also create an abstract class which your test classes extend:
#Listeners({ TestReportListener.class })
public abstract class BaseTest {
//Add here common code
}
And use it in your test class:
public class MyTestClass extends BaseTest {
...
Note: You can use such an interceptor also to implement a custom execution order.
I have written a code for retrying a failed test case in selenium web driver and java.
How should we enhance the script to hold only one record in the test case output even the same test case as been executed multiple times.
I don't want the test output report to contain any redundant result entries.
Code:
Retry Logic :
package tests;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class Retry implements IRetryAnalyzer {
private int retryCount = 0;
private int maxRetryCount = 2; // retry a failed test 2 additional times
#Override
public boolean retry(ITestResult result) {
if (retryCount <maxRetryCount) {
retryCount++;
return true;
}
return false;
}
}
Implementation in the class
#Test(retryAnalyzer=Retry.class)
public void example() throws CustomException
{
throw new CustomException("Example");
}
Please let me know what changes are needed.
Thanks and Regards
Sushanth.G
I had the same problem before.
We used jenkins to run CI, and need to make sure all test case results were SUCCESS (even after some times of retry) then we can deploy build.
The solution is adding TestListenerAdapter to re-write test result status to SKIP if this test will be run again.
public class MyTestListenerAdapter extends TestListenerAdapter {
#Override
public void onTestFailure(ITestResult result) {
if (result.getMethod().getRetryAnalyzer() != null) {
MyRetryAnalyzer retryAnalyzer = (MyRetryAnalyzer)result.getMethod().getRetryAnalyzer();
if(retryAnalyzer.isRetryAvailable()) {
result.setStatus(ITestResult.SKIP);
} else {
result.setStatus(ITestResult.FAILURE);
}
Reporter.setCurrentTestResult(result);
}
}
}
RetryAnalyzer needs to provide another method (isRetryAvailable() in this example) for TestListenerAdapter.
public class MyRetryAnalyzer implements IRetryAnalyzer {
private static int MAX_RETRY_COUNT = 3;
AtomicInteger count = new AtomicInteger(MAX_RETRY_COUNT);
public boolean isRetryAvailable() {
return (count.intValue() > 0);
}
#Override
public boolean retry(ITestResult result) {
boolean retry = false;
if (isRetryAvailable()) {
System.out.println("Going to retry test case: " + result.getMethod() + ", " + (MAX_RETRY_COUNT - count.intValue() + 1) + " out of " + MAX_RETRY_COUNT);
retry = true;
count.decrementAndGet();
}
return retry;
}
}
Now we can add this TestListenerAdapter to test class.
#Listeners({MyTestListenerAdapter.class})
public class AppTest {
#Test(retryAnalyzer=MyRetryAnalyzer.class)
public void testSum(){
MyClass c = new MyClass();
Assert.assertEquals(c.sum(2, 3), 5);
}
}
Please see full example here: https://github.com/haojiwu/testng-retry-example
I made the following custom BlockJUnit4ClassRunner
public class RepeatEachTest extends BlockJUnit4ClassRunner {
private int repeats;
public RepeatEachTest(Class<?> klass) throws InitializationError {
super(klass);
Repeat r = klass.getAnnotation(Repeat.class);
if (r == null) {
throw new InitializationError("A #Repeat annonation must also be suplied to class, for example #Repeat(5) to repeat 5 times");
}
repeats = r.value();
}
#Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
for (int i = 0; i < repeats; i++) {
super.runChild(method, notifier);
}
}
#Override
public int testCount() {
return repeats * super.testCount();
}
}
and
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Repeat {
int value();
}
to execute each test #Repeat.value() number of times. A test run of
#RunWith(RepeatEachTest.class)
#Repeat(2)
public class RepeatEachTestTest {
#Test
public void first() {
System.out.println("ran first");
}
#Test
public void second() {
System.out.println("ran second");
}
}
looks like
ran first
ran first
ran second
ran second
but now I want to implement a second BlockJUnit4ClassRunner which runs the whole test class #Repeat.value() number of times. A run from that setup would look like
ran first
ran second
ran first
ran second
Any thoughts?
That depends on what you want. If you want the #BeforeClass and #AfterClass methods and class rules to be called multiple times, you can override classBlock():
protected Statement classBlock(final RunNotifier notifier) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
for (int i = 0; i < repeats; i++) {
super.classBlock(notifier).evaluate();
}
}
};
}
If you want the #BeforeClass and #AfterClass methods and class rules to be called once, override childrenInvoker() (the code would be similar).
Note, however, that either of these will result in the listeners being notified multiple times that the test has started and completed. Some listeners may not behave correctly in this situation.
I have problem writing a testcase to this method below: EvenNum(double)
public class OddEven {
/**
* #param args
*/
public boolean evenNum(double num)
{
if(num%2 == 0)
{
System.out.print(true);
return true;
}
else
{
System.out.print(false);
return false;
}
}
This is the testcase I wrote but I think I have an inheritance problem or a logical problem in this test case. Should be a very simple one but can't figure out. Here is the code I wrote:
import static org.junit.Assert.*;
import org.junit.Test;
public class OddEvenTest {
#Test
public void testEvenNum() {
boolean ans = true;
boolean val;
double num= 6;
val = OddEven.EvenNum(num) // cant inherit the method dont know why???
assertEquals(ans,val);
}
}
You have a number of issues:
you are attempting to call a non-static method statically
method names in java are case sensitive and you've mixed up the case.
I corrected some things for you and just verified the code below:
OddEven.java:
public class OddEven {
public boolean evenNum(double num)
{
if(num%2 == 0)
{
System.out.print(true);
return true;
}
else
{
System.out.print(false);
return false;
}
}
}
OddEvenTest.java
import static org.junit.Assert.*;
import org.junit.Test;
public class OddEvenTest {
#Test
public void testEvenNum() {
boolean ans = true;
boolean val;
double num = 6;
OddEven oddEven = new OddEven();
val = oddEven.evenNum(num);
assertEquals(ans,val);
}
}
Assuming the calls to System.out.println() in OddEven are strictly for debugging, the whole thing could be collapsed down to:
OddEven.java
public class OddEven {
public boolean evenNum(double num) {
return num%2 == 0;
}
}
OddEvenTest.java
import static org.junit.Assert.*;
import org.junit.Test;
public class OddEvenTest {
#Test
public void testEvenNum() {
OddEven oddEven = new OddEven();
assertTrue(oddEven.evenNum(6));
assertFalse(oddEven.evenNum(5));
}
}
The code is now shorter and the unit test even covers an odd case for good measure.
Two things :
You are invoking a non-static method statically. The method should be declared static:
public static boolean evenNum(double num) {
}
You didn't type the name of the method correctly. Look closely. Also consider renaming it something more readable like, isEven(...)
This seems like testing gone mad to me, and programming gone mad too. All the method does is evaluate num % 2 == 0. You may as well just code that everywhere required and throw away both the method and its tests. If you must keep the method, it relies on a mathematical identity, you don't need to test those. You may as well test 1+1==2.