How can I implement Cucumber cross browser testing with a TestNG runner and parameterized setup?

I’m working with Selenium WebDriver using Cucumber for BDD and recently added TestNG to support cross-browser testing. My standalone TestNG test runs fine in both Chrome and Firefox using parameters defined in testng.xml.

However, when I integrate it with my Cucumber setup using AbstractTestNGCucumberTests, the tests run only in one browser (e.g., Chrome), and Firefox gets ignored. I suspect the issue lies in how I’m initializing the TestNG test with a browser parameter inside the step definition class:

java Copy Edit private final WebTest webTest = new WebTest(“CHROME”); This hardcodes the browser choice, making true Cucumber cross browser testing ineffective.

Is there a way to correctly pass TestNG parameters to Cucumber step definitions so that the tests run across multiple browsers as defined in testng.xml? I’d appreciate suggestions or patterns that have worked for managing parameterized Cucumber + TestNG cross-browser tests.

I’ve spent quite a bit of time refining my setup for cucumber cross browser testing, and what finally clicked for me was managing WebDriver instances with ThreadLocal. I inject the browser type via TestNG’s @BeforeClass, and store it using a shared context or environment manager. Instead of hardcoding the browser in my step definitions, I built a factory pattern that pulls the browser from that shared context. This approach keeps the browser config flexible, and it ensures that the step definitions stay decoupled from the browser logic. Each TestNG instance takes care of the browser selection—smooth, scalable, and clean

Yeah, @madhurima_sil’s approach lines up with what we initially tried. I’ve worked quite a bit with cucumber cross browser testing, and one refinement that really helped us was pushing browser initialization into a custom TestNGCucumberRunner subclass. From there, we grabbed the browser type from testng.xml, initialized WebDriver in a @BeforeClass, and passed it into step definitions via PicoContainer. This gave us even tighter control over browser setup, completely abstracted from the step definitions. It also made it easier to scale our suite: one TestNG class per browser session, and we could run tests in true parallel without worrying about driver conflicts.

I’ve faced similar constraints in cucumber cross browser testing, and while I followed a pattern close to what Toby suggested, I added a slight twist. We mapped each <test> node in testng.xml to a different browser and used the @Parameters annotation to fetch the browser type dynamically in a base test class. Then we initialized the driver there and passed it to the step definitions using a static context holder. It’s not the cleanest solution, but it kept our Gherkin steps untouched and allowed us to run Chrome, Firefox, and even Edge in parallel. If you’re dealing with legacy structure or need to plug into an existing suite fast, this approach gets the job done without a big refactor.