Annotations, Data Providers & Suite Config
Setup/Teardown Scopes
public class UserServiceTest {
@BeforeSuite void initOnce() { /* whole suite, once */ }
@BeforeClass void setUpClass() { /* once per class */ }
@BeforeMethod void setUp() { /* before every test method */ }
@Test(groups = "smoke")
public void createsUser() {
assertNotNull(userService.create("Ada"));
}
@AfterMethod void tearDown() { }
@AfterClass void tearDownClass() { }
}@BeforeMethod/@AfterMethod run per test; @BeforeClass/@AfterClass once per class; @BeforeSuite/@AfterSuite once for the whole run — choose the right scope for correctness (avoid leaking state) and performance (don't repeat expensive setup).
Data Providers — Built-in Parameterized Tests
@DataProvider(name = "emails")
public Object[][] emailData() {
return new Object[][] {
{ "ada@example.com", true },
{ "not-an-email", false },
};
}
@Test(dataProvider = "emails")
public void validatesEmail(String email, boolean expected) {
assertEquals(validator.isValid(email), expected);
}Groups & testng.xml
<suite name="RegressionSuite" parallel="methods" thread-count="4">
<test name="SmokeTests">
<groups>
<run><include name="smoke"/></run>
</groups>
<classes>
<class name="com.example.UserServiceTest"/>
</classes>
</test>
</suite>groups lets a run include/exclude tagged subsets (fast "smoke" vs. full "regression") without physically reorganizing files. parallel/thread-count configures parallel execution declaratively, no manual threading code.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free