TestNG Parameters
1. What Are TestNG Parameters?
TestNG parameters let you inject external values (strings, numbers, etc.) into your test or configuration methods, without hard-coding them. You declare parameters in your testng.xml and then annotate your methods with @Parameters, so you can drive things like URLs, browsers, credentials, or any other config at runtime.
// Example of using a parameter in a test method
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParameterExample {
  @Test
  @Parameters("env")      // name of the XML parameter
  public void testEnv(String env) {
    System.out.println("Running tests against environment: " + env);
    // … use `env` to pick base URL, credentials, etc. …
  }
}
2. How to Run TestNG Parameters?
Define your parameters in testng.xml.
Annotate your methods with @Parameters(“name”) (or multiple names).
Point your TestNG runner (Eclipse, CLI, Maven) at that XML—TestNG reads the values and injects them.
Run via CLI:
java -cp "bin:libs/*" org.testng.TestNG testng.xml
With Maven (Surefire):
<build>
  <plugins>
    <plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
        <suiteXmlFiles>
          <suiteXmlFile>testng.xml</suiteXmlFile>
        </suiteXmlFiles>
      </configuration>
    </plugin>
  </plugins>
</build>
mvn test
3. Define TestNG Parameters at the Suite Level
Putting <parameter> directly under <suite> makes it available to all <test> blocks and classes:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="MySuite">
  <!-- Suite-level parameter -->
  <parameter name="env" value="staging"/>
  <parameter name="browser" value="chrome"/>
  <test name="SmokeTests">
    <classes>
      <class name="com.example.tests.ParameterExample"/>
    </classes>
  </test>
  <test name="RegressionTests">
    <classes>
      <class name="com.example.tests.ParameterExample"/>
    </classes>
  </test>
</suite>
All methods annotated with @Parameters(“env”) or @Parameters(“browser”) in any class will receive these values when you run MySuite.
4. Overriding Power in TestNG Parameters
You can override suite-level values by redefining a parameter at the <test> level:
<suite name="OverrideSuite">
  <!-- default values -->
  <parameter name="browser" value="chrome"/>
  <!-- Uses Chrome -->
  <test name="ChromeTests">
    <classes>
      <class name="com.example.tests.ParameterExample"/>
    </classes>
  </test>
  <!-- Overrides to Firefox -->
  <test name="FirefoxTests">
    <parameter name="browser" value="firefox"/>
    <classes>
      <class name="com.example.tests.ParameterExample"/>
    </classes>
  </test>
</suite>
- Suite-level browser=chrome applies by default.
- FirefoxTests explicitly sets browser=firefox, overriding the suite default for that <test> only.
5. Optional Parameters
Sometimes you want a sane default if a parameter isn’t provided in the XML. Use @Optional in your method signature:
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class OptionalParameterExample {
  @Test
  @Parameters("timeout")
  public void timeoutTest(@Optional("30") int timeoutInSeconds) {
    System.out.println("Timeout is set to " + timeoutInSeconds + " seconds");
    // … use timeoutInSeconds …
  }
}
- If <parameter name=”timeout” …/> is present, TestNG converts its value (e.g. “45”) to an int.
If it’s missing, TestNG uses the default 30 defined in @Optional(“30”).
Putting It All Together
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="FullConfigSuite">
  <!-- Suite-level defaults -->
  <parameter name="env"   value="dev"/>
  <parameter name="browser" value="chrome"/>
  <test name="Smoke">
    <!-- inherits env=dev, browser=chrome -->
    <classes>
      <class name="com.example.tests.FullParameterExample"/>
    </classes>
  </test>
  <test name="CrossBrowser">
    <!-- override browser only -->
    <parameter name="browser" value="firefox"/>
    <classes>
      <class name="com.example.tests.FullParameterExample"/>
    </classes>
  </test>
</suite>
package com.example.tests;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class FullParameterExample {
  private String env;
  private String browser;
  private int retries;
  @BeforeClass
  @Parameters({"env","browser","retries"})
  public void setUp(String env,
                    String browser,
                    @Optional("2") int retries) {
    this.env = env;
    this.browser = browser;
    this.retries = retries;
    System.out.printf("Env=%s, Browser=%s, Retries=%d%n", env, browser, retries);
    // … initialize WebDriver based on browser …
  }
  @Test
  public void sampleTest() {
    System.out.println("Running test on " + env + " in " + browser);
    // … test logic …
  }
}
With this pattern you get:
Suite-level defaults for broad configuration.
Test-level overrides for specific runs (e.g. different browsers).
Optional fallbacks so missing parameters don’t break your suite.