Think of profiles like preset modes on a camera. Portrait mode, landscape mode, night mode — each changes multiple settings at once. Maven profiles work the same way. Instead of passing 5 different -D flags, you activate one profile that sets everything.
<profiles>
<!-- ===== BROWSER PROFILES ===== -->
<profile>
<id>chrome</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<browser>chrome</browser>
</properties>
</profile>
<profile>
<id>firefox</id>
<properties>
<browser>firefox</browser>
</properties>
</profile>
<profile>
<id>edge</id>
<properties>
<browser>edge</browser>
</properties>
</profile>
<!-- ===== ENVIRONMENT PROFILES ===== -->
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<base.url>https://www.testerrank.com/banking</base.url>
<headless>false</headless>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<base.url>https://staging.testerrank.com/banking</base.url>
<headless>true</headless>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<base.url>https://testerrank.com/banking</base.url>
<headless>true</headless>
</properties>
</profile>
<!-- ===== TEST SUITE PROFILES ===== -->
<profile>
<id>smoke</id>
<properties>
<suiteXmlFile>testng-smoke.xml</suiteXmlFile>
</properties>
</profile>
<profile>
<id>regression</id>
<properties>
<suiteXmlFile>testng-regression.xml</suiteXmlFile>
</properties>
</profile>
</profiles># Activate a single profile
mvn clean test -Pfirefox
# Activate multiple profiles (comma-separated, no spaces)
mvn clean test -Pfirefox,staging,smoke
# Real-world CI examples:
# Nightly regression on Chrome against staging
mvn clean test -Pchrome,staging,regression
# Quick smoke test on Firefox against production
mvn clean test -Pfirefox,production,smoke
# Headless Chrome regression in CI
mvn clean test -Pchrome,staging,regression -Dheadless=true
# Check which profiles are active
mvn help:active-profilesCommand-line -D flags override profile properties. So mvn test -Pchrome -Dheadless=true will use Chrome from the profile but override the headless setting. This gives you maximum flexibility — profiles set the defaults, command line overrides when needed.
| Activation Type | How It Works | Example |
|---|---|---|
| -P flag | Manually activated from command line | mvn test -Pfirefox |
| activeByDefault | Active when no other profile is specified | <activeByDefault>true</activeByDefault> |
| OS-based | Activates based on operating system | <os><name>Windows 10</name></os> |
| Property-based | Activates when a property is set | <property><name>env</name><value>staging</value></property> |
| JDK-based | Activates based on Java version | <jdk>17</jdk> |
For QA automation, you'll mostly use -P flag activation. CI pipelines pass profiles as parameters: Jenkins runs mvn clean test -Pchrome,staging,smoke for morning smoke tests and mvn clean test -Pchrome,firefox,edge,regression for nightly cross-browser regression.
Q: What are Maven profiles and how do you use them in your framework?
A: Maven profiles are named sets of configuration that can be activated on demand. In our framework, we have three categories of profiles: browser profiles (chrome, firefox, edge) that set the browser property, environment profiles (local, staging, production) that set the base URL and headless mode, and suite profiles (smoke, regression) that set which testng.xml file to run. We activate them with the -P flag: mvn clean test -Pfirefox,staging,smoke. In our Jenkins pipeline, different jobs use different profile combinations — smoke tests run on every push, full regression runs nightly.
If you set activeByDefault on a profile, it deactivates as soon as ANY other profile is explicitly activated. So if you run mvn test -Pfirefox, the "chrome" profile with activeByDefault will NOT be active. This catches a lot of people off guard.
Key Point: Profiles let you switch browsers, environments, and test suites with -P flags — no code changes needed. CI pipelines rely on this heavily.