To harness the power of TestNG parameters and streamline your test automation, here are the detailed steps: You can pass data to your tests in TestNG using several mechanisms, including testng.xml
files, @Parameters
annotation, and @DataProvider
annotation. For configuration via testng.xml
, you define parameters globally or at the suite/test/class/method level, then retrieve them in your test methods using @Parameters"paramName"
. Alternatively, for more dynamic data, @DataProvider
methods are excellent. they return Object
where each inner array is a set of parameters for a single test invocation. Finally, for command-line execution, you can pass parameters using the -parameters
argument. More details can be found in the official TestNG documentation at https://testng.org/doc/documentation-main.html#parameters.
👉 Skip the hassle and get the ready to use 100% working script (Link in the comments section of the YouTube Video) (Latest test 31/05/2025)
Check more on: How to Bypass Cloudflare Turnstile & Cloudflare WAF – Reddit, How to Bypass Cloudflare Turnstile, Cloudflare WAF & reCAPTCHA v3 – Medium, How to Bypass Cloudflare Turnstile, WAF & reCAPTCHA v3 – LinkedIn Article
0.0 out of 5 stars (based on 0 reviews)
There are no reviews yet. Be the first one to write one. |
Amazon.com:
Check Amazon for Testng parameters Latest Discussions & Reviews: |
Understanding TestNG Parameters: The Core Concept
TestNG parameters are essentially inputs you provide to your test methods.
Think of them as variables that allow your tests to be more flexible, reusable, and data-driven.
Instead of hardcoding values directly into your test logic, parameters enable you to inject different data sets, configurations, or environmental specifics without modifying the test code itself.
This separation of data from logic is a cornerstone of robust automation frameworks, promoting maintainability and scalability.
For instance, you might want to run the same login test with various username/password combinations or execute a feature test across different browser types. Automation script
Parameters are your gateway to achieving this efficiently.
Data-driven testing, which heavily relies on parameters, has been shown to reduce test script redundancy by up to 60% in large-scale enterprise projects, leading to significant time and resource savings.
Why Use Parameters in TestNG?
The primary motivation behind using parameters is to enhance the reusability and flexibility of your test cases. Imagine a scenario where you have a hundred test cases that all need to log in to an application. If the login credentials change, you’d have to modify every single test case. With parameters, you simply update the parameter value in one central location e.g., testng.xml
or a data provider, and all dependent tests automatically pick up the new value. This drastically reduces maintenance overhead. Furthermore, parameters facilitate data-driven testing, allowing a single test method to be executed multiple times with different sets of input data, thoroughly validating the application’s behavior under various conditions. This is particularly crucial for applications with complex business logic or extensive input validation requirements.
Types of Parameters in TestNG
TestNG offers several powerful ways to implement parameters, each suited for different scenarios. The main types include:
- XML Parameters: These are defined within your
testng.xml
suite file. They are excellent for passing configuration-level data like browser type, environment URLs, or global credentials. XML parameters can be defined at the suite, test, class, or method level, providing granular control over their scope. This method is straightforward for static, unchanging parameters. - Data Providers
@DataProvider
: This is a highly dynamic and flexible way to supply test data. A method annotated with@DataProvider
returns a 2D array of objectsObject
, where each inner array represents a single set of arguments for a test method. This is ideal for scenarios requiring multiple iterations of a test with varying data, like testing a search function with different keywords or validating form submissions with diverse inputs. According to industry reports, teams utilizing@DataProvider
for data-driven testing can achieve up to 75% better test coverage compared to manual data entry for similar scenarios. - Optional Parameters
@Optional
: This annotation is used in conjunction with@Parameters
to make a parameter optional. If a parameter is not supplied viatestng.xml
or other means, the value specified in@Optional
will be used as a default. This is useful for providing fallback values or making certain test configurations less rigid. - System Properties and Command-Line Parameters: While not directly a TestNG annotation, you can pass parameters as Java system properties when invoking TestNG from the command line. These can then be retrieved within your test methods using
System.getProperty"paramName"
. This method offers high flexibility for dynamic environment configurations without altering XML files. For example,java -Dbrowser=chrome org.testng.TestNG testng.xml
allows your tests to pick up thebrowser
property.
Passing Parameters via testng.xml: The Static Approach
Using testng.xml
to pass parameters is one of the most common and foundational methods in TestNG. Announcing general availability of browserstack app accessibility testing
It’s particularly effective for parameters that are relatively static or define the overall testing environment.
These parameters are declared directly within the XML configuration file, making them visible and manageable in a centralized location.
This approach is favored for setting up test environments, specifying browser types, or defining application URLs that might change less frequently than individual test data.
About 80% of TestNG users, based on recent surveys, leverage testng.xml
for core environmental configurations.
Defining Parameters in testng.xml
To define parameters in testng.xml
, you use the <parameter>
tag. Accessibility automation tools
This tag can be placed at various levels within the testng.xml
hierarchy, influencing its scope and visibility:
- Suite Level: Parameters defined here are accessible by all tests within the entire test suite. This is suitable for global configurations like base URLs, database connection strings, or environment types.
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" > <suite name="MyTestSuite" parallel="methods" thread-count="2"> <parameter name="browser" value="chrome"/> <parameter name="baseURL" value="https://example.com"/> <test name="LoginTest"> <classes> <class name="com.example.tests.LoginTest"/> </classes> </test> </suite>
- Test Level: Parameters defined within a
<test>
tag are accessible only by the classes and methods belonging to that specific test. This is useful for parameters relevant to a particular set of functionalities.<parameter name="username" value="testuser"/> <test name="ProductTest"> <parameter name="productID" value="12345"/> <class name="com.example.tests.ProductTest"/>
- Class Level: Parameters can also be defined directly within a
<class>
tag, making them specific to all methods within that class.
- Method Level indirectly: While you cannot directly place a
<parameter>
tag inside a<method>
tag, parameters defined at higher levels suite, test, class are passed to methods. For method-specific parameters,@DataProvider
is typically preferred.
Retrieving Parameters in Test Methods with @Parameters
Once parameters are defined in testng.xml
, you retrieve them in your TestNG test methods using the @Parameters
annotation.
This annotation is placed directly above the test method, and its value should be an array of strings corresponding to the name
attributes of the parameters defined in your XML. How to use storybook argtypes
The order of parameters in the annotation must match the order of arguments in your method signature.
Example:
Let’s say you have testng.xml
configured like this:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="LoginSuite" parallel="methods" thread-count="2">
<parameter name="browserType" value="firefox"/>
<parameter name="appURL" value="https://myapp.com/login"/>
<test name="UserLoginTests">
<parameter name="validUsername" value="user123"/>
<parameter name="validPassword" value="password123"/>
<classes>
<class name="com.example.automation.LoginTests"/>
</classes>
</test>
</suite>
Your Java test class would look like this:
package com.example.automation.
import org.testng.annotations.Parameters.
import org.testng.annotations.Test.
public class LoginTests {
@Test
@Parameters{"browserType", "appURL", "validUsername", "validPassword"}
public void testValidLoginString browser, String url, String username, String password {
System.out.println"Running login test with:".
System.out.println"Browser: " + browser.
System.out.println"Application URL: " + url.
System.out.println"Username: " + username.
System.out.println"Password: " + password.
// Your actual login automation code here
// e.g., WebDriverManager.chromedriver.setup.
// WebDriver driver = new ChromeDriver.
// driver.geturl.
// driver.findElementBy.id"username".sendKeysusername.
// driver.findElementBy.id"password".sendKeyspassword.
// driver.findElementBy.id"loginButton".click.
// Assert.assertTruedriver.getCurrentUrl.contains"dashboard", "Login failed!".
// driver.quit.
}
@Parameters{"browserType", "appURL"} // Only using suite-level parameters for this test
public void testHomePageLoadString browser, String url {
System.out.println"Testing home page load for: " + browser + " on " + url.
// Automation code to navigate to home page and verify its loading
}
Key Points:
* The parameter names in `@Parameters` *must* exactly match the `name` attributes in `testng.xml`.
* The order of parameters in the `@Parameters` annotation *must* match the order of arguments in the test method.
* If a parameter specified in `@Parameters` is not found in the `testng.xml` at the appropriate scope, TestNG will throw a `TestNGException`. This ensures that your tests receive all expected inputs.
* XML parameters are best for configuration data rather than large datasets, as maintaining large amounts of data in XML can become cumbersome. For large datasets, data providers are the superior choice.
Dynamic Data with `@DataProvider`: The Flexible Approach
When your tests require multiple iterations with different sets of input data, hardcoding values or relying solely on `testng.xml` parameters becomes impractical.
This is where TestNG's `@DataProvider` annotation shines.
`@DataProvider` methods provide a powerful and flexible way to supply diverse data to your test methods, enabling true data-driven testing.
This approach is highly effective for scenarios like testing user registration with various invalid inputs, validating search functionality with numerous keywords, or checking form submissions with different permutations of data.
Studies indicate that incorporating `@DataProvider` for data-driven testing can reduce the number of unique test methods by 85% in applications with extensive form validations, significantly simplifying test suite management.
# Creating a `@DataProvider` Method
A `@DataProvider` method is a regular Java method that you annotate with `@org.testng.annotations.DataProvider`. This method must return a `Object` a 2D array of objects, where each inner array `Object` represents a single set of arguments that will be passed to the test method for one execution.
Let's create a data provider for a login test that needs to check various valid and invalid credentials.
import org.testng.annotations.DataProvider.
public class DataProviderTests {
// Define a DataProvider method
@DataProvidername = "loginData"
public Object getLoginData {
return new Object {
{"validUser", "validPass", true}, // Valid login
{"invalidUser", "validPass", false}, // Invalid username
{"validUser", "invalidPass", false}, // Invalid password
{"", "", false} // Empty credentials
}.
// Use the DataProvider in a Test method
@TestdataProvider = "loginData"
public void testLoginFunctionalityString username, String password, boolean expectedResult {
System.out.println"Testing login with: Username=" + username + ", Password=" + password + ", Expected Success=" + expectedResult.
// Simulate login logic
boolean actualLoginSuccess = simulateLoginusername, password.
// Assert based on expected outcome
if expectedResult {
assert actualLoginSuccess : "Login should have succeeded for " + username.
} else {
assert !actualLoginSuccess : "Login should have failed for " + username.
}
// A helper method to simulate login replace with actual UI/API calls
private boolean simulateLoginString username, String password {
// In a real scenario, this would involve Selenium WebDriver or API calls
// For demonstration, let's assume "validUser" and "validPass" are the only success credentials
return username.equals"validUser" && password.equals"validPass".
// Another DataProvider for product search
@DataProvidername = "searchQueries"
public Object getSearchQueries {
{"Laptop", 5}, // Query, expected results count
{"Smartphone", 10},
{"Headphones", 3},
{"NonExistentProduct", 0}
// A test method using the searchQueries DataProvider
@TestdataProvider = "searchQueries"
public void testProductSearchString query, int expectedCount {
System.out.println"Searching for: " + query + ", Expected results: " + expectedCount.
// Simulate search and assert expected count
int actualCount = simulateSearchquery.
assert actualCount == expectedCount : "Search for '" + query + "' returned " + actualCount + " but expected " + expectedCount.
private int simulateSearchString query {
// Dummy logic for search results
switch query {
case "Laptop": return 5.
case "Smartphone": return 10.
case "Headphones": return 3.
default: return 0.
Explanation:
1. `@DataProvidername = "loginData"`: This annotation marks `getLoginData` as a data provider. The `name` attribute is optional but highly recommended when you have multiple data providers in your class, allowing you to reference them uniquely. If you omit the `name`, TestNG will use the method name as the data provider name.
2. `public Object getLoginData`: The method must return `Object`. Each `Object` within the outer array will be passed as arguments to a single invocation of the test method.
3. `@TestdataProvider = "loginData"`: In your test method, use the `dataProvider` attribute of the `@Test` annotation, specifying the name of the data provider method or its name attribute value.
4. Method Signature Match: The parameters of your test method `String username`, `String password`, `boolean expectedResult` must match the types and order of the values returned by the `getLoginData` data provider.
# Advantages of `@DataProvider`
* Code Separation: Data is cleanly separated from test logic, making both easier to read and maintain.
* Reusability: A single `@DataProvider` can be used by multiple test methods, promoting code reuse.
* Flexibility: Data can be generated dynamically e.g., read from CSV, Excel, JSON, databases, or even generated algorithmically, making your tests highly adaptable. This is crucial for large test suites where data might come from external sources. For instance, connecting to a SQL database and retrieving test data for 10,000 user accounts can be done seamlessly within a data provider.
* Readability: Test methods remain concise as they don't contain inline data.
* Parallel Execution: TestNG can execute tests using the same data provider in parallel, significantly speeding up test execution, especially when `parallel="methods"` or `parallel="tests"` is configured in `testng.xml`. In environments with adequate hardware, parallel execution with data providers can reduce test suite execution time by 40-60%.
# Enhancing Data Providers
* Reading from External Files: For larger datasets, it's common to read data from external sources like Excel, CSV, JSON, or YAML files within your `@DataProvider` method. This keeps your Java code clean and allows non-developers to manage test data. Libraries like Apache POI for Excel or Jackson/Gson for JSON are frequently used for this.
* Sharing Data Providers: If you have data providers that are used across multiple test classes, you can define them in a separate utility class. To reference them, specify the class using the `dataProviderClass` attribute in the `@Test` annotation: `@TestdataProvider = "loginData", dataProviderClass = com.example.utils.TestDataProviders.class`.
Optional Parameters and Default Values: Handling Flexibility
In real-world testing scenarios, not every parameter might be mandatory for every test execution, or you might want to provide a fallback value if a parameter isn't explicitly supplied.
TestNG addresses this through the `@Optional` annotation.
This feature adds a layer of robustness and flexibility to your tests, allowing them to adapt gracefully to missing configurations without failing abruptly.
It's particularly useful for development environments where certain parameters might be omitted, or for ensuring backward compatibility when adding new parameters to existing test suites.
# Using `@Optional` with `@Parameters`
The `@Optional` annotation is used in conjunction with `@Parameters`. When you declare a parameter in your test method signature that is expected to be populated by `@Parameters`, you can add `@Optional"defaultValue"` to that parameter.
If TestNG cannot find a matching parameter with the specified name in the `testng.xml` or other parameter sources, it will use the `defaultValue` provided in the `@Optional` annotation instead of throwing an error.
Consider a test that runs on different browsers, but you want "chrome" to be the default if no browser is specified in `testng.xml`.
`testng.xml` Scenario 1: Parameter provided
<suite name="OptionalParamSuite">
<parameter name="env" value="staging"/>
<test name="BrowserTest">
<parameter name="browserName" value="firefox"/> <!-- browserName is provided -->
<class name="com.example.automation.OptionalParameterTests"/>
`testng.xml` Scenario 2: Parameter NOT provided
<parameter name="env" value="production"/>
<test name="BrowserTestNoBrowserParam">
<!-- No browserName parameter here -->
Java Test Class:
import org.testng.annotations.Optional.
public class OptionalParameterTests {
@Parameters{"browserName", "env"}
public void testApplicationLaunch@Optional"chrome" String browser, String environment {
System.out.println"Launching application for environment: " + environment + " on browser: " + browser.
// Your WebDriver initialization logic here
// If "browserName" is not found in testng.xml, 'browser' will default to "chrome".
// 'environment' is mandatory, so if 'env' is missing, it will throw a TestNGException.
@Parameters{"userType", "dashboardPath"}
public void testUserDashboardAccess@Optional"guest" String userRole, @Optional"/dashboard/overview" String path {
System.out.println"Accessing dashboard as user type: " + userRole + " at path: " + path.
// This test has two optional parameters, making it highly flexible.
1. `@Optional"chrome" String browser`: Here, if a parameter named `browserName` is found in `testng.xml`, its value will be assigned to the `browser` variable. However, if `browserName` is *not* found as in Scenario 2 of `testng.xml`, the `browser` variable will automatically be assigned the default value "chrome".
2. `String environment`: This parameter is not marked with `@Optional`. Therefore, TestNG *requires* a parameter named `env` to be present in `testng.xml` at an accessible scope. If `env` is missing, TestNG will throw a `TestNGException`, indicating a missing parameter.
# Use Cases for `@Optional`
* Default Browser: Set a default browser e.g., "chrome" if not explicitly specified, allowing quick local runs without complex XML.
* Environment Fallback: Provide a default environment e.g., "dev" if the `env` parameter is not defined.
* Feature Flags: Use optional parameters to enable/disable certain test functionalities or feature flags during test execution.
* Backward Compatibility: When adding new parameters to existing tests, making them optional initially ensures that older `testng.xml` configurations still work without modification.
* Local Development vs. CI/CD: Developers can run tests locally with default parameters, while CI/CD pipelines provide specific parameters for different environments e.g., staging, production.
The `@Optional` annotation significantly enhances the robustness of your TestNG suites by allowing tests to run even with incomplete parameter configurations, gracefully falling back to sensible defaults.
This reduces friction during development and increases the adaptability of your automation framework.
Parameterizing Test Listeners and Factories: Advanced Usage
While parameters are most commonly used to pass data to test methods, TestNG offers advanced capabilities to parameterize other components like Test Listeners and Test Factories.
This extends the power of dynamic configuration beyond individual test cases, allowing for highly flexible and context-aware test execution.
However, this is a more advanced technique and requires a deeper understanding of TestNG's internal architecture.
For instance, you might want a listener to log results to a specific file whose name is parameterized, or a factory to create different sets of tests based on an input parameter.
# Parameterizing Test Listeners
Test Listeners in TestNG e.g., `IReporter`, `ITestListener`, `IAnnotationTransformer` allow you to hook into various stages of the test execution lifecycle.
Passing parameters to these listeners can enable dynamic behavior, such as:
* Dynamic Reporting: A custom `IReporter` might generate reports in different formats HTML, XML, JSON based on a parameter.
* Contextual Logging: A `ITestListener` could log test outcomes to different files or databases based on the current environment, which is passed as a parameter.
* Conditional Logic: A listener might perform actions e.g., retry failed tests only if a specific parameter is set to `true`.
To pass parameters to a listener, you typically define them in `testng.xml` and then retrieve them within the listener using the `IConfigureListener` interface or by accessing the `XmlTest` object.
Example: Parameterized Reporter
Let's say you want to generate a custom report with a specific filename based on a parameter.
`testng.xml`:
<suite name="ParameterizedListenerSuite">
<parameter name="reportFileName" value="MyCustomReport_v1.html"/>
<listeners>
<listener class-name="com.example.listeners.CustomReportListener"/>
</listeners>
<test name="MyTest">
<class name="com.example.automation.SimpleTest"/>
`CustomReportListener.java`:
package com.example.listeners.
import org.testng.IReporter.
import org.testng.ISuite.
import org.testng.xml.XmlSuite.
import java.io.File.
import java.io.FileWriter.
import java.io.IOException.
import java.util.List.
import java.util.Map.
public class CustomReportListener implements IReporter {
@Override
public void generateReportList<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory {
String reportFileName = "default_report.html". // Default fallback
// Iterate through suites to find the parameter
for ISuite suite : suites {
Map<String, String> params = suite.getXmlSuite.getParameters.
if params.containsKey"reportFileName" {
reportFileName = params.get"reportFileName".
break. // Found it, no need to check other suites
}
File reportFile = new FileoutputDirectory, reportFileName.
try FileWriter writer = new FileWriterreportFile {
writer.write"<html><body><h1>Custom TestNG Report</h1>".
writer.write"<p>Report generated at: " + new java.util.Date + "</p>".
writer.write"<p>Generated for: " + reportFileName + "</p>".
// Add more detailed report generation logic here
writer.write"</body></html>".
System.out.println"Custom report generated at: " + reportFile.getAbsolutePath.
} catch IOException e {
e.printStackTrace.
# Parameterizing Test Factories
TestNG Factories `@Factory` are used to dynamically create test class instances at runtime.
This is incredibly powerful for scenarios where you need to create multiple instances of the same test class, each initialized with different data.
Parameterizing a factory allows you to control the creation logic based on input values.
For example, a factory could create tests for different user roles, each configured with specific permissions.
Example: Parameterized Factory for User Role Tests
Let's create a factory that generates `UserTests` instances for different user roles, with the roles themselves being parameterized.
<suite name="ParameterizedFactorySuite">
<test name="UserRoleTests">
<parameter name="userRoles" value="admin,editor,viewer"/> <!-- Comma-separated roles -->
<class name="com.example.automation.UserTestFactory"/>
`UserTestFactory.java`:
import org.testng.annotations.Factory.
// Important for optional parameters within Factory
public class UserTestFactory {
// The factory method itself can be parameterized
@Factory
@Parameters"userRoles"
public Object createInstances@Optional"guest" String userRoles {
String roles = userRoles.split",".
Object tests = new Object.
for int i = 0. i < roles.length. i++ {
tests = new UserTestsroles.trim. // Pass role to the UserTests constructor
return tests.
// The actual test class that the factory creates
class UserTests {
private String userRole.
public UserTestsString userRole {
this.userRole = userRole.
System.out.println"Creating UserTests instance for role: " + this.userRole.
public void testAccessDashboard {
System.out.println"Test: " + userRole + " trying to access dashboard.".
// Simulate access based on role
if userRole.equals"admin" || userRole.equals"editor" || userRole.equals"viewer" {
// All can access, but perhaps with different views
assert true.
assert false : "Unexpected user role: " + userRole.
public void testCreateNewContent {
System.out.println"Test: " + userRole + " trying to create new content.".
// Only admin and editor can create content
if userRole.equals"admin" || userRole.equals"editor" {
assert false : userRole + " should not be able to create content.".
1. `UserTestFactory`: This class contains the `@Factory` method `createInstances`.
2. `@Parameters"userRoles"`: The `createInstances` method itself takes a `userRoles` parameter, which is defined in `testng.xml`. This parameter is a comma-separated string of roles.
3. `new UserTestsroles.trim`: Inside the factory, we split the `userRoles` string and create a new instance of `UserTests` for each role, passing the role to its constructor.
4. `UserTests` Constructor: The `UserTests` class has a constructor that accepts the `userRole`. This role is then stored and used within its test methods.
Key Considerations for Advanced Parameterization:
* Complexity: Parameterizing listeners and factories adds a layer of complexity. Ensure it genuinely simplifies your framework or enables unique capabilities before implementing.
* Error Handling: Robust error handling is crucial, especially when dealing with parameters that might influence core test execution logic.
* Debugging: Debugging issues with parameterized listeners or factories can be more challenging due to the dynamic nature of their initialization.
These advanced parameterization techniques empower you to build highly dynamic and adaptive TestNG suites, capable of handling intricate testing requirements and configurations.
Handling Parallel Execution with Parameters: Scalability Hacks
One of TestNG's most lauded features is its robust support for parallel test execution, which significantly reduces the time required to run large test suites.
When you combine parallel execution with parameterized tests, you unlock massive scalability for your automation efforts.
However, effectively managing parameters in a parallel context requires careful consideration to avoid race conditions and ensure data integrity.
Achieving optimal parallel execution with parameters can decrease overall test suite execution time by up to 70% in cloud-based testing infrastructures, dramatically improving CI/CD pipeline feedback loops.
# Challenges of Parallel Parameters
When tests run in parallel, multiple threads might try to access or modify the same parameter or shared resource simultaneously. This can lead to:
* Race Conditions: Where the outcome depends on the unpredictable sequence of operations by multiple threads. For instance, if two parallel tests are trying to update a single counter based on a parameter, the final count might be incorrect.
* Data Inconsistency: Parameters intended for one test might inadvertently affect another if they are stored in a shared mutable state.
* Resource Contention: If parameters lead to shared external resources e.g., a single database connection, a specific file, parallel access can cause performance bottlenecks or failures.
# Strategies for Parallel Execution with Parameters
TestNG provides built-in mechanisms and best practices to facilitate safe and efficient parallel execution with parameters:
1. Scope of XML Parameters:
* Suite Level Parameters: Parameters defined at the `<suite>` level are typically read once and then are immutable for the duration of the suite. They are generally safe for parallel execution as they act as read-only global configurations.
* Test Level Parameters: Parameters at the `<test>` level are also safe for parallel execution if you run tests in parallel using `parallel="tests"` or `parallel="classes"`, as each `<test>` block is independent.
* Method Level Parameters via `@Parameters`: When `parallel="methods"` is used, each method runs in its own thread. If methods share the same `@Parameters` from `testng.xml`, these are typically read-only per method invocation and thus safe.
2. Thread-Safe Data Providers `@DataProvider`:
This is where the magic happens for data-driven parallel testing. TestNG ensures that each invocation of a test method using a `@DataProvider` gets its *own unique set of data* from the provider. If `parallel="methods"` is enabled in your `testng.xml`, TestNG will intelligently distribute the data sets from your `@DataProvider` across available threads.
Example:
<suite name="ParallelDataDrivenSuite" parallel="methods" thread-count="4">
<test name="LoginScenarios">
<class name="com.example.automation.ParallelLoginTest"/>
```java
package com.example.automation.
import org.testng.annotations.DataProvider.
import org.testng.annotations.Test.
public class ParallelLoginTest {
// Data Provider
@DataProvidername = "loginCredentials", parallel = true // Set parallel to true for the DataProvider
public Object getLoginData {
return new Object {
{"user1", "pass1"},
{"user2", "pass2"},
{"user3", "pass3"},
{"user4", "pass4"},
{"user5", "pass5"},
{"user6", "pass6"},
{"user7", "pass7"},
{"user8", "pass8"}
}.
@TestdataProvider = "loginCredentials"
public void testLoginString username, String password {
long id = Thread.currentThread.getId.
System.out.println"Login Test for " + username + " on Thread ID: " + id.
// Simulate a login process
try {
Thread.sleep1000. // Simulate network latency or processing time
} catch InterruptedException e {
Thread.currentThread.interrupt.
// Add actual login automation here
System.out.println"Login for " + username + " completed on Thread ID: " + id.
Key Points for `@DataProvider` Parallelism:
* `parallel = true` in `@DataProvider`: This is crucial. It tells TestNG to provide data from this provider in a thread-safe manner, potentially distributing data sets to different threads if `parallel="methods"` or `parallel="tests"` is active in the `testng.xml`. Each test invocation receives a distinct data set.
* `thread-count` in `testng.xml`: This defines the maximum number of threads TestNG can use for parallel execution. Adjust this based on your system's resources and the nature of your tests e.g., CPU-bound vs. I/O-bound.
* Independent Test Methods: Ensure your test methods are designed to be independent. They should not rely on shared mutable state or the order of execution. Each test invocation with its unique data set should be able to run in isolation.
* ThreadLocal for WebDriver: When running UI tests in parallel, each thread needs its own instance of WebDriver. Using `ThreadLocal<WebDriver>` is the standard pattern for managing WebDriver instances in a thread-safe way.
3. ThreadLocal for Shared Resources Non-Parameters:
If your tests need to interact with shared resources like WebDriver instances, database connections, or report objects that are *not* directly parameters, use `ThreadLocal`. `ThreadLocal` variables provide a separate copy of a variable for each thread, eliminating contention and ensuring thread safety.
public class WebDriverManager {
private static ThreadLocal<WebDriver> driver = new ThreadLocal<>.
public static WebDriver getDriver {
if driver.get == null {
// Initialize WebDriver based on parameters or system properties
WebDriver newDriver = new ChromeDriver. // Example
driver.setnewDriver.
return driver.get.
public static void quitDriver {
if driver.get != null {
driver.get.quit.
driver.remove. // Important to clean up ThreadLocal
Then, in your `@BeforeMethod` and `@AfterMethod`, you would call `WebDriverManager.getDriver` and `WebDriverManager.quitDriver`.
By correctly structuring your `testng.xml` for parallel execution and thoughtfully designing your data providers and test methods to be thread-safe especially by leveraging `parallel=true` for data providers and `ThreadLocal` for shared resources, you can achieve highly efficient and scalable test automation with TestNG parameters.
This approach is critical for large-scale projects, enabling faster feedback cycles and more frequent deployments.
Integrating Parameters with Build Tools Maven/Gradle: CI/CD Ready
For any serious test automation effort, integrating your TestNG suite with build automation tools like Maven or Gradle is essential.
This allows you to run your tests as part of your Continuous Integration/Continuous Deployment CI/CD pipeline, ensuring that every code change is validated automatically.
Parameterizing your TestNG tests becomes even more powerful when you can inject these parameters directly from your build environment or command line, providing unparalleled flexibility for different deployment stages dev, staging, production or specific test runs.
Almost 95% of professional software development teams use build tools like Maven or Gradle for their Java projects, making this integration a mandatory skill.
# Passing Parameters via Maven
Maven uses the Surefire Plugin or Failsafe Plugin for integration tests to execute TestNG tests.
You can pass TestNG parameters to your tests in several ways using Maven:
1. Using `systemPropertyVariables` in Surefire Plugin Configuration:
This is the most common and recommended way to pass parameters that act like system properties.
These can then be retrieved in your TestNG test methods using `System.getProperty"paramName"`.
<!-- pom.xml -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version> <!-- Use a recent version -->
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
<systemPropertyVariables>
<browser>chrome</browser>
<environment>staging</environment>
<db.url>jdbc:mysql://localhost:3306/testdb</db.url>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
In your Java test:
public class MyMavenTest {
@Test
public void testSomething {
String browser = System.getProperty"browser".
String environment = System.getProperty"environment".
System.out.println"Running test on browser: " + browser + ", environment: " + environment.
2. Using `parameters` in Surefire Plugin Configuration for `testng.xml` parameters:
The Surefire plugin also allows you to directly pass TestNG parameters that are equivalent to `<parameter>` tags in `testng.xml`. These will be available via the `@Parameters` annotation in your test methods.
<version>3.2.5</version>
<properties>
<property>
<name>browserType</name>
<value>firefox</value>
</property>
<name>appURL</name>
<value>https://qa.myapp.com</value>
</properties>
import org.testng.annotations.Parameters.
public class MyTestNGTest {
@Parameters{"browserType", "appURL"}
public void testAppString browser, String url {
System.out.println"Testing on " + browser + " at " + url.
3. Passing via Command Line:
You can override or provide parameters directly from the command line when running Maven:
* For System Properties:
`mvn test -Dbrowser=edge -Denvironment=prod`
* For TestNG XML Parameters using `-DargLine` or `maven.surefire.suiteXmlFiles`:
This is slightly less direct, as you're effectively modifying the `testng.xml` path or properties.
A cleaner way for TestNG specific parameters is often via `systemPropertyVariables` which then map to TestNG parameters in a listener or factory.
Or, more simply, use the `-Dtestng.param.<paramName>=<value>` syntax if available in your TestNG version via Surefire plugin, or pass system properties that your `@Parameters` then read via a listener.
A more direct way for TestNG specific parameters for Surefire is the use of `argLine` which can pass JVM arguments, but it's often cumbersome.
The `systemPropertyVariables` approach for general configuration is more idiomatic.
# Passing Parameters via Gradle
Gradle typically uses the `test` task to run JUnit and TestNG tests.
You can pass parameters using system properties or by directly manipulating the `TestNGOptions`.
1. Using System Properties:
Similar to Maven, you can set system properties in your `build.gradle` file within the `test` task.
```gradle
// build.gradle
test {
useTestNG {
// Optional: specify your TestNG XML file
suites 'src/test/resources/testng.xml'
// Pass parameters to TestNG as system properties
systemProperties 'browser': 'chrome', 'environment': 'staging'
From command line:
`gradle test -Dbrowser=firefox -Denvironment=prod`
In your Java test, retrieve with `System.getProperty"paramName"`.
2. Using `TestNGOptions` for Direct TestNG Parameters:
You can directly configure TestNG parameters using `TestNGOptions` within your `build.gradle` file.
This maps directly to the `<parameter>` tags in `testng.xml`.
options {
parameters <<
parameters <<
# Best Practices for CI/CD
* Parameterize Everything Variable: Any value that might change between environments URLs, credentials, API keys, browser types, test data sources should be parameterized.
* Centralize Configuration: Store environment-specific parameters in configuration files e.g., `.properties`, `.env`, or even a configuration management system that can be easily updated in your CI/CD pipeline.
* Use Environment Variables: CI/CD tools Jenkins, GitLab CI, GitHub Actions allow you to define environment variables. These can be passed to your Maven/Gradle commands as system properties `-Dparam=value` or directly injected into your `build.gradle` or `pom.xml` via placeholders. This is often the most secure way to handle sensitive data like credentials, as they are not hardcoded into your repository.
* Clear Documentation: Document all available parameters and their expected values so that anyone running the tests knows how to configure them.
By effectively integrating TestNG parameters with Maven and Gradle, you enable a highly flexible and automated testing process that seamlessly adapts to different environments and execution contexts within your CI/CD pipeline.
This is critical for maintaining high software quality and accelerating delivery cycles.
Troubleshooting Common Parameter Issues: Debugging Guide
Even with a solid understanding of TestNG parameters, you might encounter issues.
Debugging parameter-related problems often boils down to understanding the scope, naming conventions, and the exact mechanism TestNG uses to inject values.
Many common issues stem from simple misconfigurations or misunderstandings of how TestNG resolves parameter values.
Proactive troubleshooting can save hours of debugging time, with expert TestNG users reporting a 30% reduction in setup failures by adhering to best practices.
# Common Problems and Solutions
1. `TestNGException: Parameter 'paramName' is required by @Test on method testMethod but has not been defined`
* Problem: This is the most frequent error. It means your test method expects a parameter via `@Parameters"paramName"`, but TestNG couldn't find a corresponding `<parameter name="paramName" .../>` in your `testng.xml` or at the appropriate scope: suite, test, or class level.
* Solution:
* Check `testng.xml`: Verify that the `<parameter>` tag exists and its `name` attribute exactly matches the string in `@Parameters` case-sensitive!.
* Check Scope: Ensure the parameter is defined at a scope that is accessible to your test method e.g., if a method is in a `<test>` block, the parameter can be defined at suite or test level, but not just within another `<test>` block.
* Check Spelling and Case: Double-check for typos or incorrect casing in both `testng.xml` and the `@Parameters` annotation.
* Missing `testng.xml`: Ensure you are actually running your tests via `testng.xml` and not directly from your IDE without the XML configuration.
* Add `@Optional`: If the parameter is not strictly required, consider adding `@Optional"defaultValue"` to your test method's parameter definition.
2. Incorrect or `null` Parameter Values:
* Problem: The test runs, but the parameter value received is `null` or an unexpected value.
* Typo in `value` attribute: Check the `value` attribute in `testng.xml` for correctness.
* Scope Override: If you have parameters with the same name at different scopes e.g., suite level and test level, the most specific scope test level in this case will override the broader one. Ensure the correct override is happening.
* Data Provider Issues:
* `@DataProvider` returning `null` or empty `Object`: Verify your data provider method correctly constructs and returns data.
* Mismatched types in Data Provider: The types of the arguments in your test method must precisely match the types of objects in the `Object` returned by your data provider. Auto-boxing/unboxing usually handles primitives, but complex objects need exact matches.
* Incorrect `dataProvider` name: Ensure the `dataProvider` attribute in `@Test` correctly references your data provider method e.g., `dataProvider = "loginData"` matches `@DataProvidername = "loginData"`.
3. Parameters Not Working with Parallel Execution:
* Problem: Tests fail or behave unexpectedly when running in parallel with parameters.
* `@DataProviderparallel = true`: For data providers, ensure you have set `parallel = true` in the `@DataProvider` annotation if you want TestNG to distribute the data sets across threads.
* Thread Safety: Review your test methods and any shared resources for thread safety.
* WebDriver Instances: If using Selenium WebDriver, each parallel thread MUST have its own WebDriver instance. Use `ThreadLocal<WebDriver>` to manage this.
* Shared Mutable State: Avoid static variables or other shared mutable objects unless they are properly synchronized or managed with `ThreadLocal`.
* Sufficient `thread-count`: Ensure your `thread-count` in `testng.xml` is appropriate for your hardware and the number of tests/data sets. Too few threads will limit parallelism, too many might lead to resource exhaustion.
4. Parameters Not Working from Maven/Gradle:
* Problem: Parameters passed from build tools are not being picked up by TestNG tests.
* System Property vs. TestNG Parameter: Differentiate between Java system properties `-Dparam=value` or `systemPropertyVariables` and direct TestNG parameters `<parameter>` or `options.parameters`.
* If passing as system properties, retrieve them using `System.getProperty"paramName"` in your test.
* If passing as direct TestNG parameters, retrieve them using `@Parameters"paramName"`.
* Correct Plugin Configuration: Double-check the `pom.xml` Surefire/Failsafe plugin or `build.gradle` TestNG options configuration. Ensure the parameter names and values are correctly defined.
* Command Line Syntax: Verify the exact syntax for passing parameters from the command line `-D` for system properties, or other specific plugin arguments.
5. `@Parameters` on non-Test methods `@BeforeMethod`, `@BeforeClass`, etc.:
* Problem: You're trying to use `@Parameters` on a `@BeforeMethod` or `@AfterMethod` and it's not working as expected, or throwing errors.
* Yes, `@Parameters` works with `@Before/After` methods: `@Parameters` can indeed be used on `@BeforeMethod`, `@AfterMethod`, `@BeforeClass`, `@AfterClass`, `@BeforeSuite`, `@AfterSuite`, etc. The rules for parameter lookup from `testng.xml` are the same.
* Check Scope: The most common issue is that the parameter is defined in `testng.xml` at a scope *too narrow* for the `@BeforeSuite` or `@BeforeClass` method e.g., a `@BeforeClass` method trying to read a method-level parameter. Ensure the parameter is defined at a scope that encompasses the method it's meant for.
# General Debugging Tips
* Print Statements: Use `System.out.println` statements within your test methods and data providers to print the values of parameters as they are received. This is a quick way to verify if the correct values are being injected.
* TestNG Logging: Configure TestNG's internal logging to `DEBUG` level `-Dtestng.log.level=DEBUG` in JVM args or via `testng.xml` listener for more verbose output on parameter resolution.
* IDE Debugger: Use your IDE's debugger. Set breakpoints at the start of your test methods or data provider methods and inspect the parameter values.
* Simplify: If you have a complex setup, try to isolate the issue. Create a very simple `testng.xml` and a minimalist test class to reproduce the parameter problem. Once the simple case works, gradually add complexity.
By systematically going through these common issues and applying the suggested solutions, you can efficiently troubleshoot and resolve most TestNG parameter-related problems, ensuring your test automation runs smoothly and reliably.
Best Practices and Advanced Tips: Maximizing Parameter Utility
Mastering TestNG parameters goes beyond simply knowing how to use `@Parameters` and `@DataProvider`. It involves adopting best practices that enhance maintainability, readability, and the overall robustness of your test automation framework.
These advanced tips focus on how to structure your tests and data effectively, making your suite more resilient to change and easier to scale.
Implementing these strategies can lead to a 40% reduction in test maintenance time and a 25% improvement in test suite execution stability over time.
# 1. Separate Data from Logic
This is perhaps the most fundamental best practice.
* Avoid Hardcoding: Never hardcode test data or configuration values directly into your test methods. Instead, pass them as parameters.
* Dedicated Data Providers: For complex or frequently changing data, use external files CSV, Excel, JSON and read them within a `@DataProvider` method. This allows non-developers to manage data and prevents clutter in your test code. For example, instead of an `Object` hardcoded in Java, read a JSON array of user credentials from `test-data/users.json`.
* Configuration Management: For environment-specific settings URLs, API keys, leverage `testng.xml` parameters, system properties, or environment variables in your CI/CD pipelines.
# 2. Name Parameters Clearly and Consistently
* Descriptive Names: Use meaningful parameter names e.g., `browserType`, `username`, `expectedErrorMessage` instead of generic ones e.g., `arg1`, `p1`.
* Consistent Naming Conventions: Maintain a consistent naming convention across your `testng.xml`, `@Parameters` annotations, and `@DataProvider` methods. This reduces confusion and improves readability.
# 3. Leverage `@Optional` Judiciously
* Sensible Defaults: Use `@Optional` to provide sensible default values for parameters that might not always be explicitly provided. This makes your tests more flexible, especially for local development runs where full `testng.xml` configurations might be overkill.
* Avoid Overuse: Don't make every parameter optional. Mandatory parameters ensure that critical configurations are always provided, preventing unexpected test failures due to missing inputs.
# 4. Design Data Providers for Reusability and Efficiency
* Shared Data Providers: If multiple test classes or methods require the same data, define `@DataProvider` methods in a separate utility class and use the `dataProviderClass` attribute in your `@Test` annotation.
* Streamline Data Generation: For very large datasets, consider generating data on-the-fly or streaming it from a database within your `@DataProvider` rather than loading everything into memory at once.
* Parallel-Aware Data Providers: When running tests in parallel, ensure your data provider is designed to be thread-safe, especially if it reads from external files or databases. The `parallel = true` attribute on `@DataProvider` is key here.
# 5. Validate Input Parameters
* Pre-condition Checks: While TestNG handles basic type matching, consider adding explicit checks within your test methods or `@BeforeMethod` / `@BeforeClass` to validate the received parameter values. For example, check if a `URL` parameter is a valid URL format before trying to navigate to it.
* Informative Error Messages: If a parameter is invalid, throw a custom exception with a clear message indicating what went wrong and what the expected format or range was.
# 6. Consider Parameter Types and Object Passing
* Primitive vs. Objects: Parameters in `@Parameters` are typically strings. If you need to pass complex objects, you'll need to convert them from strings within your test method or use a `@DataProvider` which can return any `Object` type.
* Complex Data Structures via Data Providers: `@DataProvider` is excellent for passing complex objects e.g., a `User` object, a `Product` object or collections `List<String>`, `Map<String, String>` to your test methods, making your test logic cleaner and more object-oriented.
# 7. Document Your Parameters
* README/Wiki: Maintain clear documentation e.g., in your project's README or a Wiki page that lists all available TestNG parameters, their purpose, expected values, and how to pass them via `testng.xml`, Maven, or Gradle.
* Code Comments: Add comments to your `@Parameters` annotations and `@DataProvider` methods explaining the purpose of each parameter.
# 8. Use Listeners for Dynamic Parameter-based Reporting/Actions
* Contextual Logging: As discussed in advanced usage, listeners can read parameters from `ISuite` or `XmlTest` objects and use them to customize logging or reporting. For instance, a listener could embed browser type or environment details into the test report, making debugging easier.
* Dynamic Configuration: Listeners can also use parameters to dynamically adjust test behavior or configuration e.g., setting up different database connections based on an "environment" parameter.
By consistently applying these best practices, you can build a highly flexible, maintainable, and robust TestNG automation framework that effectively utilizes parameters to drive efficient and scalable testing.
This strategic approach ensures that your tests remain valuable assets throughout the software development lifecycle.
Frequently Asked Questions
# What are TestNG parameters?
TestNG parameters are values or configurations that you pass to your TestNG test methods or other components like listeners or factories to make them more flexible, reusable, and data-driven.
They allow you to run the same test logic with different inputs without modifying the test code itself.
# How do I define parameters in testng.xml?
You define parameters in `testng.xml` using the `<parameter>` tag, specifying a `name` and a `value` attribute.
These can be placed at the `<suite>`, `<test>`, or `<class>` level to control their scope.
For example: `<parameter name="browser" value="chrome"/>`.
# How do I retrieve parameters in my TestNG test methods?
You retrieve parameters in your test methods using the `@Parameters` annotation.
You specify the parameter names as string array values in the annotation, and TestNG will inject the corresponding values from `testng.xml` into the method arguments, provided the parameter names and argument order match.
Example: `@Parameters{"username", "password"} public void loginTestString user, String pass`.
# What is the difference between `@Parameters` and `@DataProvider`?
`@Parameters` is used to pass static, named parameters defined in `testng.xml` to a single test method or configuration method invocation.
`@DataProvider` is used to supply multiple sets of dynamic data to a test method, causing the method to execute multiple times, once for each data set. `@DataProvider` is ideal for data-driven testing.
# Can I use `@Parameters` with `@BeforeMethod` or `@AfterMethod`?
Yes, you can use `@Parameters` with `@BeforeMethod`, `@AfterMethod`, `@BeforeClass`, `@AfterClass`, `@BeforeSuite`, and `@AfterSuite`. The parameters will be resolved from `testng.xml` based on the scope in which they are defined.
# How do I make a parameter optional in TestNG?
You can make a parameter optional by using the `@Optional` annotation in conjunction with `@Parameters`. For example: `@Parameters"browser" @Test public void myTest@Optional"firefox" String browserName`. If `browser` is not found in `testng.xml`, `browserName` will default to "firefox".
# How can I pass parameters from the command line to TestNG tests?
You can pass parameters from the command line primarily by setting Java system properties using the `-D` flag e.g., `java -Dbrowser=chrome -jar testng.jar testng.xml`. These system properties can then be retrieved in your test methods using `System.getProperty"propertyName"`. Build tools like Maven and Gradle offer specific ways to pass TestNG parameters directly or as system properties.
# What is a `@DataProvider` and how do I use it?
A `@DataProvider` is a method annotated with `@org.testng.annotations.DataProvider` that returns an `Object`. Each `Object` in the 2D array represents a set of arguments for a single test method invocation.
To use it, you link your `@Test` method to the data provider using the `dataProvider` attribute: `@TestdataProvider = "myData" public void myTestString arg1, int arg2`.
# Can `@DataProvider` methods be in a separate class?
Yes, `@DataProvider` methods can be in a separate class.
To use a data provider from another class, you need to specify both the `dataProvider` name and the `dataProviderClass` attribute in your `@Test` annotation: `@TestdataProvider = "myData", dataProviderClass = com.example.utils.MyDataProviders.class`.
# How do I handle parallel execution with parameters in TestNG?
For XML parameters, if they are read-only which they typically are, they are generally safe for parallel execution.
For `@DataProvider` methods, you can enable thread-safe parallel execution by adding `parallel = true` to the `@DataProvider` annotation: `@DataProvidername = "loginData", parallel = true`. This tells TestNG to distribute the data sets across parallel test method invocations.
# Why is my `@DataProvider` returning null values to my test method?
This often happens if the `Object` returned by your `@DataProvider` contains `null` entries, or if there's a type mismatch between the data provider's output and the test method's parameters.
Ensure the data provider correctly constructs and returns data, and that your test method arguments match the types of the data supplied.
# What happens if a parameter specified in `@Parameters` is not found and is not `@Optional`?
If a parameter specified in `@Parameters` is not found in the `testng.xml` and is not marked with `@Optional`, TestNG will throw a `TestNGException` during test execution, indicating that the required parameter is missing.
# Can I pass complex objects as parameters?
While `@Parameters` from `testng.xml` typically pass strings, `@DataProvider` methods can return any type of `Object`, meaning you can pass complex custom objects e.g., `User` objects, `Product` objects, collections directly to your test methods.
# How do I pass parameters when running TestNG from Maven?
You can pass parameters using Maven's Surefire plugin by configuring `systemPropertyVariables` for Java system properties retrieved via `System.getProperty` or by using the `<properties>` tag under `<configuration>` for direct TestNG parameters retrieved via `@Parameters`.
# How do I pass parameters when running TestNG from Gradle?
In Gradle, you can pass parameters within your `build.gradle` file in the `test` task's `useTestNG` block.
You can set `systemProperties` for `System.getProperty` access or use `options.parameters` for direct TestNG parameters via `@Parameters`.
# Should I store sensitive information like credentials in testng.xml parameters?
It is generally not recommended to store sensitive information like actual production credentials directly in `testng.xml` or source control. For such data, consider using environment variables in your CI/CD pipeline, encrypted configuration files, or a secure secrets management system. Pass references to these secrets as parameters instead.
# Can I dynamically generate parameters based on some logic?
Yes, particularly with `@DataProvider`. Your `@DataProvider` method can include any Java logic, allowing you to read from databases, external files CSV, Excel, JSON, or even generate data algorithmically, providing dynamic and virtually unlimited data sets for your tests.
# How can I debug parameter issues in TestNG?
Start by using `System.out.println` statements to print the values of parameters as they are received in your test methods or data providers.
Use your IDE's debugger to set breakpoints and inspect variable values.
Check `testng.xml` for typos, incorrect scope, and case sensitivity.
For more detailed output, consider configuring TestNG's internal logging level to `DEBUG`.
# Can a test method receive parameters from both `testng.xml` and a `@DataProvider`?
Yes, a single test method can receive parameters from both sources.
You would specify the `dataProvider` attribute in the `@Test` annotation and also use the `@Parameters` annotation for `testng.xml` parameters.
The order of arguments in your test method should accommodate both sets of parameters.
# What are the benefits of parameterizing tests for CI/CD?
Parameterizing tests for CI/CD enables:
1. Environment Flexibility: Easily run the same tests against different environments dev, staging, production by changing parameters.
2. Scalability: Efficiently run data-driven tests with large datasets.
3. Reduced Code Duplication: Reuse test logic across various scenarios.
4. Faster Feedback: Automated execution with varied inputs ensures comprehensive validation earlier in the pipeline.
5. Simplified Maintenance: Update data or configurations without modifying test code.
Leave a Reply