TestNG

TestNG beforeSuite Example

In this article, we will show you how to use the TestNG @BeforeSuite annotation.

If you have used JUnit annotations, you will be familiar with @BeforeClass. In TestNG, apart from @BeforeClass, we also have additional annotations like @BeforeTest and @BeforeSuite.

@BeforeSuite will be executed before any tests declared inside a TestNG suite are run.

So how is it different from the @BeforeClass annotation? Well… The differences will get clear in a moment as we go through the examples, but first a bit about the setup details:

  • I am using Eclipse as the IDE, version Luna 4.4.1.
  • I will be running the tests using eclipse TestNG plugin so you need to install the TestNG Eclipse Plugin.

1. Example of @BeforeSuite

In order to know when a @BeforeSuite method gets called, we first need to know what a suite is and how it is defined.

A suite is defined by one or more tests and is represented by one XML file which the TestNG will use to run the tests. The XML file will define the set of tests to be run. It is represented by the <suite>tag and it is the first tag that appears in the XML file.

Lets call this file testng.xml.

Each element of the structure defines an event in TestNG lifecycle and is represented by an annotation. Every time a method is annotated with one of these, it will run in the event that the annotation represents.

The testng.xml contains the following structure:

  1. First element is called suite
  2. A suite contains one or more test elements.
  3. A test element is made up of one or more classes
  4. Finally, a class contains one or more test methods

A @BeforeSuite annotated method represents an event before the suite starts, so all the @BeforeSuite methods will be executed before the first test declared within the test element is invoked.

Let’s understand this through an example. Below is the configuration test file that the example uses. The suite contains two tests Test1 and Test2. Test1 contains test class TestClass1 and Test2 contains test class TestClass2.

testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
	<test name="Test1">
		<classes>
			<class name="com.javacodegeeks.testng.TestClass1" />
		</classes>
	</test>
	<test name="Test2">
		<classes>
			<class name="com.javacodegeeks.testng.TestClass2" />
		</classes>
	</test>
</suite>

In TestClass1, we have one @BeforeSuite method called suiteSetup1 at suite level and there are other @Before and @After annotated methods at test, class and method level. We also have couple of @Test methods.

TestClass1:

package com.javacodegeeks.testng;

import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class TestClass1 {
	@BeforeSuite
	public void suiteSetup1() {
		System.out.println("testClass1.suiteSetup1: before suite");
	}		
	
	@BeforeTest
	public void beforeTest() {
		System.out.println("testClass1: before test");
	}
	
	@Test
	public void unitLevel1() {
		System.out.println("testClass1: Unit level1 testing");
	}
	
	@Test
	public void unitLevel2() {
		System.out.println("testClass1: Unit level2 testing");
	}
	
	@BeforeMethod
	public void beforeMethod() {
		System.out.println("testClass1: before method");
	}
	
	@AfterMethod
	public void afterMethod() {
		System.out.println("testClass1: after method");
	}
	
	@BeforeClass
	public void beforeClass() {
		System.out.println("testClass1: before class");
	}
	
	@AfterClass
	public void afterClass() {
		System.out.println("testClass1: after class");
	}
	
	@AfterSuite
	public void cleanupSuite() {
		System.out.println("testClass1.cleanupSuite: after suite");
	}
}

In TestClass2, we have one @BeforeSuite method called suiteSetup2 at suite level and a @Test method. The rest of the methods are @Before annotated methods at test, class and method level.

TestClass2:

package com.javacodegeeks.testng;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class TestClass2 {

	@BeforeSuite
	public void suiteSetup2() {
		System.out.println("testClass2.suiteSetup2: before suite");
	}
	
	@BeforeTest
	public void beforeTest() {
		System.out.println("testClass2: before test");
	}
	
	@BeforeClass
	public void beforeClass() {
		System.out.println("testClass2: before class");
	}
	
	@BeforeMethod
	public void beforeMethod() {
		System.out.println("testClass2: before method");
	}
	
	@Test
	public void unitLevel() {
		System.out.println("testClass2: Unit level testing");
	}
}

When we run testng.xml, we see the order in which the annotated methods are fired. The very first methods that run are the @BeforeSuite methods. Since each of the test classes have one @BeforeSuite, both are consecutively run and then only other annotated methods are fired starting with @BeforeTest method.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNgBeforeSuite\test\com\javacodegeeks\testng\testng.xml

testClass1.suiteSetup1: before suite
testClass2.suiteSetup2: before suite
testClass1: before test
testClass1: before class
testClass1: before method
testClass1: Unit level1 testing
testClass1: after method
testClass1: before method
testClass1: Unit level2 testing
testClass1: after method
testClass1: after class
testClass2: before tst
testClass2: before class
testClass2: before method
testClass2: Unit level testing
testClass1.cleanupSuite: after suite

===============================================
Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

2. Example of parent and child suites

In this example, we have a parent suite that contains child suites. Each child suite has one test class and each test class has one @BeforeSuite method. The parent suite contains a common parameter called param which the @BeforeSuite methods of the child suites share.

parentSuite.xml

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Parent Suite">
  <parameter name="param" value="SuiteExample"></parameter>
  <suite-files>
  	 <suite-file path="./childSuite1.xml"/>
  	 <suite-file path="./childSuite2.xml"/>
  </suite-files>
</suite>

childSuite1.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Child Suite1">
  <test name="Test">  	
    <classes>
      <class name="com.javacodegeeks.testng.ChildTestClass1"/>
    </classes>
  </test>
</suite>

childSuite2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Child Suite2">
  <test name="Test">  	
    <classes>
      <class name="com.javacodegeeks.testng.ChildTestClass2"/>
    </classes>
  </test>
</suite>

ChildTestClass1 and ChildTestClass2 each has a @BeforeSuite method that takes in a parameter whose value is set in the parent suite.

ChildTestClass1:

package com.javacodegeeks.testng;

import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Parameters;

public class ChildTestClass1 {
	@BeforeSuite
	@Parameters("param")
	public void beforeSuite(String p) {
		System.out.println("ChildTestClass1: before suite " + p);
	}
}

In each @BeforeSuite method, we print the parameter value.

ChildTestClass2:

package com.javacodegeeks.testng;

import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Parameters;

public class ChildTestClass2 {
	@BeforeSuite
	@Parameters("param")
	public void beforeSuite(String p) {
		System.out.println("ChildTestClass2: before suite " + p);
	}
}

When you run the parent suite, you can see that the parameter value set at parent suite is received by both the child suites.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNgBeforeSuite\test\com\javacodegeeks\testng\childSuite1.xml

ChildTestClass1: before suite SuiteExample

===============================================
Child Suite1
Total tests run: 0, Failures: 0, Skips: 0
===============================================

[TestNG] Running:
  C:\javacodegeeks_ws\testNgBeforeSuite\test\com\javacodegeeks\testng\childSuite2.xml

ChildTestClass2: before suite SuiteExample

===============================================
Child Suite2
Total tests run: 0, Failures: 0, Skips: 0
===============================================

[TestNG] Running:
  C:\javacodegeeks_ws\testNgBeforeSuite\test\com\javacodegeeks\testng\parentSuite.xml


===============================================
Parent Suite
Total tests run: 0, Failures: 0, Skips: 0
===============================================

3. @BeforeSuite with ITestContext parameter

A @BeforeSuite method can be declared with a parameter of type ITestContext. In the below example, class ContextBeforeSuite has one such @BeforeSuite method.

contextSuite.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Context Suite">
	<test name="Test">
		<classes>
			<class name="com.javacodegeeks.testng.ContextBeforeSuite" />
		</classes>
	</test>
</suite>

ContextBeforeSuite:

Using the context, we print the suite name.

package com.javacodegeeks.testng;

import org.testng.ITestContext;
import org.testng.annotations.BeforeSuite;

public class ContextBeforeSuite {
	@BeforeSuite
	public void beforeSuite(ITestContext context) {
		System.out.println("ContextBeforeSuite: before suite " + context.getSuite().getName());
	}
}

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNgBeforeSuite\test\com\javacodegeeks\testng\contextSuite.xml

ContextBeforeSuite: before suite Context Suite

===============================================
Context Suite
Total tests run: 0, Failures: 0, Skips: 0
Configuration Failures: 1, Skips: 0
===============================================

4. @BeforeSuite behavior when used in Factory

@BeforeSuite methods shouldn’t run more than once even when used in Factory.

TestClassFactory below defines a factory method createTestClass. This factory method returns an array of two objects of TestClass class.

TestClassFactory:

package com.javacodegeeks.testng;

import org.testng.annotations.Factory;

public class TestClassFactory {
	@Factory
	public Object[] createTestClass() {
		return new Object[]{new TestClass("1"), new TestClass("2")};
	}
}

TestClass contains a dummy test which prints the param passed in while creating TestClass object. It has a @BeforeSuite method which we are expecting will be invoked only once even if the test is driven by the factory.

TestClass:

package com.javacodegeeks.testng;

import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class TestClass {
	private String param;

	public TestClass(String param) {
		this.param = param;
	}
	
	@BeforeSuite
	public void beforeSuite() {
		System.out.println("before suite");
	}	
	
	@Test
	public void dummyTest() {
		System.out.println("dummy test " + param);
	}
}

Select the factory class in eclipse and run it as TestNG test. Note that the @BeforeSuite method fires only once.

Output:

[TestNG] Running:
  C:\Users\mokkara\AppData\Local\Temp\testng-eclipse-50136982\testng-customsuite.xml

before suite
dummy test 2
dummy test 1
PASSED: dummyTest
PASSED: dummyTest

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


===============================================
Default suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

5. @BeforeSuite with dependency method

When a test suite has multiple @BeforeSuite methods and we want them to be invoked in a particular order, then we use the dependsOnMethods attribute to add the dependent methods.

beforeSuiteWithDependency.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite">
	<test name="Test Before Suite Dependency">
		<classes>
			<class name="com.javacodegeeks.testng.BeforeSuiteDependency" />
		</classes>
	</test>
</suite>

The @BeforeSuite method secondBeforeSuite depends on firstBeforeSuite and beforeSuite methods so it is called only after the dependent methods are called.

BeforeSuiteDependency:

package com.javacodegeeks.testng;

import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class BeforeSuiteDependency {	
	
	@BeforeSuite(dependsOnMethods={"firstBeforeSuite","beforeSuite"})
	public void secondBeforeSuite() {
	    System.out.println("Second Before suite");
	}
	
	@BeforeSuite
	public void firstBeforeSuite() {
	    System.out.println("First before suite");
	}
	
	@BeforeSuite
	public void beforeSuite() {
	    System.out.println("before suite");
	}
	
	@Test
	public void unitTest() {
		System.out.println("Unit test");
	}
}

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNgBeforeSuite\test\com\javacodegeeks\testng\beforeSuiteWithDependency.xml

before suite
First before suite
Second Before suite
Unit test

===============================================
Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

Download the Eclipse Project

In this article we have provided several examples of the TestNG @BeforeSuite.

Download
You can download the full source code of this example here: testNgBeforeSuite.zip

Ram Mokkapaty

Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
dongmei
dongmei
6 years ago

In 2. Example of parent and child suites, is it possible to call BeforeSuite only once?

Ravi
Ravi
2 years ago

Thank you for the solution😊

Back to top button