@Test Annotation attributes – dependsOnMethods attribute

This post will discuss the dependsOnMethods attribute of the @Test annotation in detail.

What does this attribute do? and what is the use of the dependsOnMethods attribute? dependsOnMethods is used on a test case that depends on the execution of another test case. So, the latter test case will be executed first as its execution is necessary to run the case that depends on it.

Syntax


dependsOnMethod attribute will take a String array like {“test1”, “test2”} and you can also pass like “test1” if a test depends only on one another test. So, it will be something like the below –

@Test(dependsOnMethod = {"test1","test2"})   // if depends on one or more tests
@Test(dependsOnMethod = "test1")   // if your test depends on only one other test

Now, let’s see some code on how to use dependsOnMethods in tests –

import org.testng.Assert;
import org.testng.annotations.Test;

public class CodekruTest {

	@Test // this test will run first
	public void test1() {

		System.out.println("test1 is passed");
		Assert.assertTrue(true);
	}

	@Test(dependsOnMethods = "test1") 
	public void test2() {

		System.out.println("test2 is passed");
		Assert.assertTrue(true);
	}

}

Output –

test1 is passed
test2 is passed
PASSED: test1
PASSED: test2

===============================================
    Default test
    Tests run: 2, Failures: 0, Skips: 0
===============================================

Here you can see that test1() is executed first and then test2(). Now, let’s play with things a little as many burning questions are still unanswered.

What if test1() failed? What will happen to the test2() test as it depends on the test1?

In this scenario, test2() will be skipped and won’t run. Let’s see this in action –

import org.testng.Assert;
import org.testng.annotations.Test;

public class CodekruTest {

	@Test
	public void test1() {

		System.out.println("test1 is passed");
		Assert.assertTrue(false); // failing the condition here
	}

	@Test(dependsOnMethods = "test1") // now this test won't run as test1 failed
	public void test2() {

		System.out.println("test2 is passed");
		Assert.assertTrue(true);
	}

}

Output –

test1 is passed
FAILED: test1
java.lang.AssertionError: expected [true] but found [false]
	at org.testng.Assert.fail(Assert.java:96)
	at org.testng.Assert.failNotEquals(Assert.java:776)
	at org.testng.Assert.assertTrue(Assert.java:44)
	at org.testng.Assert.assertTrue(Assert.java:54)
	at Test.CodekruTest.test1(CodekruTest.java:12)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at org.testng.TestRunner.privateRun(TestRunner.java:648)
	at org.testng.TestRunner.run(TestRunner.java:505)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
	at org.testng.SuiteRunner.run(SuiteRunner.java:364)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
	at org.testng.TestNG.runSuites(TestNG.java:1049)
	at org.testng.TestNG.run(TestNG.java:1017)
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)

SKIPPED: test2
java.lang.Throwable: Method CodekruTest.test2()[pri:0, instance:Test.CodekruTest@27508c5d] depends on not successfully finished methods
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:888)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at org.testng.TestRunner.privateRun(TestRunner.java:648)
	at org.testng.TestRunner.run(TestRunner.java:505)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
	at org.testng.SuiteRunner.run(SuiteRunner.java:364)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
	at org.testng.TestNG.runSuites(TestNG.java:1049)
	at org.testng.TestNG.run(TestNG.java:1017)
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)


===============================================
    Default test
    Tests run: 2, Failures: 1, Skips: 1
===============================================

So, test2() won’t even run if test1() failed, but if we still want to run the test2() test case, then we can use the alwaysRun attribute of the @Test annotation. Please visit this link to know more about the alwaysRun attribute.

What if we don’t use @Test annotation on test1() method but still use @Test(dependsOnMethod = “test1”) on test2() test case?

It will throw an error, and either of the test cases won’t run as shown below –

import org.testng.Assert;
import org.testng.annotations.Test;

public class CodekruTest {

	public void test1() {

		System.out.println("test1 is passed");
		Assert.assertTrue(true);
	}

	@Test(dependsOnMethods = "test1")
	public void test2() {

		System.out.println("test2 is passed");
		Assert.assertTrue(true);
	}

}

Output –

org.testng.TestNGException: 
Test.CodekruTest.test2() is depending on method public void Test.CodekruTest.test1(), which is not annotated with @Test or not included.
	at org.testng.internal.MethodHelper.findDependedUponMethods(MethodHelper.java:123)
	at org.testng.internal.MethodHelper.topologicalSort(MethodHelper.java:266)
	at org.testng.internal.MethodHelper.sortMethods(MethodHelper.java:376)
	at org.testng.internal.MethodHelper.collectAndOrderMethods(MethodHelper.java:65)
	at org.testng.TestRunner.initMethods(TestRunner.java:438)
	at org.testng.TestRunner.init(TestRunner.java:271)
	at org.testng.TestRunner.init(TestRunner.java:241)
	at org.testng.TestRunner.<init>(TestRunner.java:192)
	at org.testng.remote.support.RemoteTestNG6_12$1.newTestRunner(RemoteTestNG6_12.java:33)
	at org.testng.remote.support.RemoteTestNG6_12$DelegatingTestRunnerFactory.newTestRunner(RemoteTestNG6_12.java:66)
	at org.testng.SuiteRunner$ProxyTestRunnerFactory.newTestRunner(SuiteRunner.java:713)
	at org.testng.SuiteRunner.init(SuiteRunner.java:260)
	at org.testng.SuiteRunner.<init>(SuiteRunner.java:198)
	at org.testng.TestNG.createSuiteRunner(TestNG.java:1295)
	at org.testng.TestNG.createSuiteRunners(TestNG.java:1273)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1128)
	at org.testng.TestNG.runSuites(TestNG.java:1049)
	at org.testng.TestNG.run(TestNG.java:1017)
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
What if we passed a list of methods in the dependsOnMethods attribute? Is there any order to their execution?

No, there is no order of execution of tests, so, If we pass a list of tests like @Test(dependsOnMethods = {“test1″,”test2”}). TestNG can execute either test1 or test2 first, but it is guaranteed that they will run before the test method that uses the dependsOnMethods attribute.

How to use dependsOnMethods on test cases belonging to different classes?

We can do that by giving the full path up to the method name within the dependsOnMethods attribute. Let’s make two different classes, CodekruTestFirst and CodekruTestSecond, each having a test case of its own. And the test case of CodekruTestFirst depends on the test case of CodekruTestSecond.

dependsOnMethods project structure

CodekruTestFirst.java

import org.testng.Assert;
import org.testng.annotations.Test;

public class CodekruTestFirst {

	@Test()
	public void testFirst() {
		System.out.println("Excecuting test method in CodekruTestFirst class");
		Assert.assertTrue(true);
	}

}

CodekruTestSecond.java

import org.testng.Assert;
import org.testng.annotations.Test;

public class CodekruTestSecond {

	@Test(dependsOnMethods = "Demo.CodekruTestFirst.testFirst")
	public void testSecond() {
		System.out.println("Excecuting test method in CodekruTestSecond class");
		Assert.assertTrue(true);
	}

} 

We will now run the CodekruTestSecond class and the test case inside CodekruTestFirst will also be executed as the testSecond() method depends on it.

Output –

Excecuting test method in CodekruTestFirst class
Excecuting test method in CodekruTestSecond class

===============================================
codekru
Total tests run: 2, Passes: 2, Failures: 0, Skips: 0

Note: The dependent method and the depending method must have different names. Otherwise, you will run into an error.

public class CodekruTestFirst {

	@Test
	public void test() {
		System.out.println("Excecuting test method in CodekruTestFirst class");
		Assert.assertTrue(true);
	}

}
public class CodekruTestSecond {

	@Test(dependsOnMethods = "Demo.CodekruTestFirst.test")
	public void test() {
		System.out.println("Excecuting test method in CodekruTestSecond class");
		Assert.assertTrue(true);
	}

}

Now, when we run the CodekruTestSecond class, then we will get the below error.


org.testng.TestNGException: 
The following methods have cyclic dependencies:
CodekruTestSecond.test()[pri:0, instance:Demo.CodekruTestSecond@236e3f4e]

	at org.testng.internal.Graph.topologicalSort(Graph.java:128)
	at org.testng.internal.MethodHelper.topologicalSort(MethodHelper.java:299)
	at org.testng.internal.MethodHelper.sortMethods(MethodHelper.java:382)
	at org.testng.internal.MethodHelper.collectAndOrderMethods(MethodHelper.java:71)
	at org.testng.TestRunner.initMethods(TestRunner.java:517)
	at org.testng.TestRunner.init(TestRunner.java:336)
	at org.testng.TestRunner.init(TestRunner.java:289)
	at org.testng.TestRunner.<init>(TestRunner.java:220)
	at org.testng.remote.support.RemoteTestNG6_12$1.newTestRunner(RemoteTestNG6_12.java:33)
	at org.testng.remote.support.RemoteTestNG6_12$DelegatingTestRunnerFactory.newTestRunner(RemoteTestNG6_12.java:66)
	at org.testng.ITestRunnerFactory.newTestRunner(ITestRunnerFactory.java:55)
	at org.testng.SuiteRunner$ProxyTestRunnerFactory.newTestRunner(SuiteRunner.java:676)
	at org.testng.SuiteRunner.init(SuiteRunner.java:178)
	at org.testng.SuiteRunner.<init>(SuiteRunner.java:112)
	at org.testng.TestNG.createSuiteRunner(TestNG.java:1306)
	at org.testng.TestNG.createSuiteRunners(TestNG.java:1282)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1131)
	at org.testng.TestNG.runSuites(TestNG.java:1069)
	at org.testng.TestNG.run(TestNG.java:1037)
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)

We hope that you have liked the article. If you have any doubts or concerns, please feel free to write us in the comments or mail us at admin@codekru.com.

Other @Test attributes

Liked the article? Share this on

Leave a Comment

Your email address will not be published. Required fields are marked *