---
title: Set up a Maven project for Selenium | TestingBot
description: 'A Selenium + TestNG project needs surprisingly little: two dependencies,
  a test runner plugin and a folder layout Maven understands. This chapter builds
  that…'
source_url:
  html: https://testingbot.com/resources/courses/selenium-testng/project-setup
  md: https://testingbot.com/resources/courses/selenium-testng/project-setup.md
---

Course

[Selenium Java Tutorial with TestNG](https://testingbot.com/resources/courses/selenium-testng)

Chapter 2 of 11

1. [1 Selenium and TestNG: how they fit together](https://testingbot.com/resources/courses/selenium-testng)
2. [2 Set up a Maven project for Selenium](https://testingbot.com/resources/courses/selenium-testng/project-setup)
3. [3 Your first Selenium test with TestNG](https://testingbot.com/resources/courses/selenium-testng/first-test)
4. [4 TestNG annotations and the driver lifecycle](https://testingbot.com/resources/courses/selenium-testng/annotations)
5. [5 Hard assertions vs SoftAssert](https://testingbot.com/resources/courses/selenium-testng/assertions)
6. [6 Data-driven tests with DataProvider](https://testingbot.com/resources/courses/selenium-testng/data-providers)
7. [7 Suites, groups and parameters in testng.xml](https://testingbot.com/resources/courses/selenium-testng/testng-xml)
8. [8 Run Selenium tests in parallel](https://testingbot.com/resources/courses/selenium-testng/parallel-execution)
9. [9 Listeners, screenshots and reports](https://testingbot.com/resources/courses/selenium-testng/listeners-and-reports)
10. [10 Run the suite on a Selenium grid](https://testingbot.com/resources/courses/selenium-testng/run-on-a-selenium-grid)
11. [11 Knowledge check](https://testingbot.com/resources/courses/selenium-testng/knowledge-check)

[Exit course](https://testingbot.com/resources/courses)

 Chapter 2 of 11 Intermediate 6 min read 2 quick checks Updated Nov 2026 

# Set up a Maven project for Selenium
On this page
1. [Check your tools](https://testingbot.com#check-your-tools)
2. [Folder layout](https://testingbot.com#folder-layout)
3. [The pom.xml](https://testingbot.com#the-pom-xml)
4. [Drivers: there is nothing to download](https://testingbot.com#drivers-there-is-nothing-to-download)
5. [A smoke check](https://testingbot.com#a-smoke-check)
6. [Useful Maven commands](https://testingbot.com#useful-maven-commands)

A Selenium + TestNG project needs surprisingly little: two dependencies, a test runner plugin and a folder layout Maven understands. This chapter builds that skeleton and explains the one version choice that will trip you up in 2026.

## Check your tools[#](https://testingbot.com#check-your-tools)

```bash
java -version # 17 or newer; this course uses 21
mvn -version # 3.9.x
```

Selenium Java 4.52.0 and TestNG 7.12.0 are both compiled for Java 11, but the course code uses a few newer language features (such as `Stream.toList()`, Java 16+), so the project compiles for Java 17. Any JDK from 17 upward works; use a current LTS (21 or 25) if you can choose. Gradle works just as well; the [TestNG guide in our docs](https://testingbot.com/support/web-automate/selenium/java/testng) lists the Gradle coordinates if you prefer it.

## Folder layout[#](https://testingbot.com#folder-layout)

```
selenium-testng-course/
  pom.xml
  testng.xml
  src/
    test/
      java/
        com/example/
          FirstTest.java
```

Everything lives under `src/test/java` because it is test code: Maven compiles it in the `test-compile` phase and runs it in the `test` phase. You do not need anything in `src/main` for a pure UI test suite.

## The pom.xml[#](https://testingbot.com#the-pom-xml)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>selenium-testng-course</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <selenium.version>4.52.0</selenium.version>
    <testng.version>7.12.0</testng.version>
    <!-- default suite; override with -DsuiteXmlFile=other.xml -->
    <suiteXmlFile>testng.xml</suiteXmlFile>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.14.1</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <!-- stay on 3.5.x: 3.6.0+ cannot run TestNG suite XML files -->
        <version>3.5.6</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>${suiteXmlFile}</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
```

A few choices are worth explaining.

**`selenium-java`** is the umbrella artifact. It pulls in the WebDriver API, the support classes (`WebDriverWait`, `ExpectedConditions`), the Chrome, Firefox, Edge and Safari drivers, `RemoteWebDriver` for grids, and Selenium Manager. You rarely need the individual modules.

**`<scope>test</scope>`** keeps both libraries off the main classpath. Since all of our code is in `src/test`, that is exactly right. If you later move page objects or helpers into `src/main`, change Selenium's scope to the default `compile`.

**Versions in properties** make upgrades a one-line change. Selenium releases often; check [the selenium-java page on Maven Central](https://central.sonatype.com/artifact/org.seleniumhq.selenium/selenium-java) and bump regularly, because new browser versions sometimes need a newer Selenium.

### Why Surefire is pinned to 3.5.6[#](https://testingbot.com#why-surefire-is-pinned-to-3-5-6)

Maven runs tests through the Surefire plugin. Starting with **Surefire 3.6.0, every test framework runs through the JUnit Platform** , including TestNG (via a TestNG engine). The JUnit Platform cannot read TestNG suite XML files, so the `suiteXmlFiles` setting is no longer supported. With 3.6.1 and the pom above, `mvn test` stops with:

```
Parameter "suiteXmlFiles" is not supported since 3.6.0: TestNG tests now run on the
JUnit Platform, which can't read TestNG suite XML files. ... or keep using
maven-surefire-plugin 3.5.x.
```

This course relies on `testng.xml` for parallelism, parameters and listeners (chapters 6-8), so we stay on 3.5.6, the last 3.5.x release. If you would rather move to 3.6, you can drop `suiteXmlFiles` and select tests with Surefire's `groups` and `includes` parameters instead, but you lose the suite file as the single source of truth. Check the [Surefire release notes](https://maven.apache.org/surefire/maven-surefire-plugin/) before you upgrade either way.

## Drivers: there is nothing to download[#](https://testingbot.com#drivers-there-is-nothing-to-download)

Older tutorials tell you to download `chromedriver`, put it on your `PATH` or set the `webdriver.chrome.driver` system property. With Selenium 4.6 and later, skip all of that. When you call `new ChromeDriver()`, Selenium Manager (bundled in `selenium-java`):

1. Detects the installed Chrome version.
2. Resolves the matching chromedriver version from the browser vendor's metadata.
3. Downloads it once and caches it in `~/.cache/selenium`.
4. Reuses the cached driver on later runs.

If Chrome itself is missing, Selenium Manager can also download a Chrome for Testing build into the same cache. A driver you place on the `PATH` yourself still takes precedence, which is a common source of "session not created: this version of ChromeDriver only supports Chrome version N" errors: an old driver on the `PATH` shadows the one Selenium Manager would have picked. Remove it.

On CI machines without internet access, Selenium Manager cannot download anything; either pre-install the driver or, more simply, run against a remote grid (chapter 9) where the drivers are already in place.

After Chrome auto-updated, every test fails with `session not created: this version of ChromeDriver only supports Chrome version N`. What is the most likely cause?

 Selenium Manager is broken; pin an older Chrome An old chromedriver on the `PATH` is shadowing the one Selenium Manager would pick; remove it The `selenium-java` scope must be `compile` Surefire needs to be upgraded

A driver you place on the `PATH` yourself takes precedence. Remove it and Selenium Manager resolves a matching driver for the installed Chrome.

## A smoke check[#](https://testingbot.com#a-smoke-check)

Create `testng.xml` in the project root. We will grow it in chapter 6:

```xml
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Course suite">
  <test name="First">
    <classes>
      <class name="com.example.FirstTest"/>
    </classes>
  </test>
</suite>
```

Then a throwaway test to prove the wiring:

```java
package com.example;

import org.testng.Assert;
import org.testng.annotations.Test;

public class FirstTest {
    @Test
    public void wiringWorks() {
        Assert.assertTrue(true);
    }
}
```

```bash
mvn test
```

You should see `Tests run: 1, Failures: 0` and a `target/surefire-reports` folder containing TestNG's `index.html` and `emailable-report.html`. In IntelliJ IDEA, the gutter icon next to the class or the `testng.xml` file runs the same thing without Maven; [this IntelliJ setup guide](https://testingbot.com/resources/articles/getting-started-with-webdriver-in-java-using-intellij) walks through importing a Maven project if you haven't done that before.

## Useful Maven commands[#](https://testingbot.com#useful-maven-commands)

```bash
mvn test # run the suite in testng.xml
mvn test -Dtest=FirstTest # one class (ignores testng.xml)
mvn test -Dtest=FirstTest#wiringWorks # one method
mvn test -DsuiteXmlFile=smoke.xml # a different suite file
mvn -q test # less noise
```

Note that `-Dtest` overrides the suite file completely: listeners and parameters declared only in `testng.xml` will not be applied. That is handy for a quick local run and a trap if you forget about it.

In the next chapter, `FirstTest` gets a real browser.

You run `mvn test -Dtest=FirstTest` and the screenshot listener declared in `testng.xml` never fires. Why?

 Listeners only run in parallel mode The listener needs `alwaysRun = true` `-Dtest` bypasses the suite file, so listeners and parameters declared only there are not applied

`-Dtest` overrides the suite file completely. Handy for a quick run, and a trap when the suite file carries configuration.

[Previous · Chapter 1 Selenium and TestNG: how they fit together](https://testingbot.com/resources/courses/selenium-testng) [Next · Chapter 3 Your first Selenium test with TestNG](https://testingbot.com/resources/courses/selenium-testng/first-test)

On this page

1. [Check your tools](https://testingbot.com#check-your-tools)
2. [Folder layout](https://testingbot.com#folder-layout)
3. [The pom.xml](https://testingbot.com#the-pom-xml)
4. [Drivers: there is nothing to download](https://testingbot.com#drivers-there-is-nothing-to-download)
5. [A smoke check](https://testingbot.com#a-smoke-check)
6. [Useful Maven commands](https://testingbot.com#useful-maven-commands)

Certification

This course has a free, hands-on certificate.

[How it works](https://testingbot.com/resources/courses/selenium-testng/certification)
