Configuration Reference
All TestFly behaviour is controlled by testfly.yml. This document is the exhaustive reference for every top-level section, nested configuration property, default value, environment variable resolution, and profile override supported by the framework.
File Resolution Order
When TestFly bootstraps at suite execution start, it searches for the configuration file using the following priority order:
- System Property —
-Dtestfly.config=/path/to/custom.yml(highest priority) - Classpath Resource —
src/test/resources/testfly.yml - Working Directory —
./testfly.yml(fallback)
If no file is found at any of these locations, suite initialization fails immediately with a descriptive IllegalStateException.
Environment Variable Substitution & Dynamic Overrides
Placeholder Syntax
Any string value in testfly.yml (including string list items and map values) can reference environment variables or Java system properties using ${VAR_NAME} syntax:
execution:
baseUrl: ${BASE_URL}
browserstack:
username: ${BS_USER}
accessKey: ${BS_KEY}
api:
auth:
admin:
type: bearer
token: ${API_TOKEN}
TestFly resolves ${VAR_NAME} placeholders using the following priority (highest → lowest):
.envfile — A.envfile in the project root (next topom.xml). Values here deliberately win over the shell so that a stale exported credential cannot silently override the project's checked-out configuration.- Shell environment variable —
System.getenv("VAR_NAME") - System property —
-DVAR_NAME=valueorSystem.getProperty("VAR_NAME") - Default fallback —
${VAR_NAME:-default}syntax provides a fallback when no source defines the variable.
Placeholders are resolved after YAML parsing, so boolean and numeric fields (for example browser.headless, execution.threadCount) cannot use them — headless: ${HEADLESS:-true} fails at startup with a ConstructorException. Use a profile file (-Dtestfly.profile=ci) for those values.
Supported .env syntax:
# comment
API_KEY=sk-abc123
SECRET="quoted value"
TOKEN='single quoted'
URL=https://example.com # inline comment
Use DotEnvLoader.fromDotEnv("API_KEY") to read a value exclusively from the .env file, bypassing the shell and system properties.
Environment Profiles (-Dtestfly.profile)
You can create environment-specific override files by naming them testfly-<profile>.yml:
testfly.yml # Base configuration (shared defaults)
testfly-staging.yml # Complete staging configuration
testfly-prod.yml # Complete production configuration
testfly-ci.yml # Complete CI configuration
Activate a profile via Maven or Gradle:
mvn test -Dtestfly.profile=staging
Each profile file is a complete configuration. TestFly loads the selected file without merging it with testfly.yml. Omitted optional properties use framework defaults; required settings must be present in the profile.
Master testfly.yml Template
The following commented template demonstrates every supported configuration block with recommended defaults:
# ── Feature Switchboard ──────────────────────────────────────────────────────
# Master on/off panel that sits ABOVE each module's own settings.
# Omit a key to let that module's own config decide; set true/false to override it.
# Values below form a runnable recommended profile; they are not all field defaults.
features:
ai: true # every AI/agentic surface: act(), aiAssert(), failure analysis, AI healing
recording: false # MP4/GIF video capture of browser execution
tracing: false # step screenshots + execution timeline (target/traces/)
network: false # CDP interception, route mocking, URL blocklists
healing: false # locator self-healing, including the AI fallback
visual: true # visual regression comparison
performance: false # Core Web Vitals collection
flakiness: true # flakiness history scoring
quarantine: true # automatic skipping of quarantined tests
testManagement: false # TestRail / Xray result push
notifications: true # Slack / Teams run notifications
consoleErrors: false # browser console (JS) error collection
loadtest: false # parsed into loadtest.enabled; explicit runs are not currently gated
# ── Browser ──────────────────────────────────────────────────────────────────
browser:
name: chrome # chrome | firefox | edge | safari
headless: false # auto-forced to true when CI environment is detected
lifecycle: per-test # per-test (clean isolation) | per-suite (reuse session per thread)
downloadDir: ./target/downloads # target directory for browser file downloads
captureConsoleErrors: false # collect browser console (JS) error logs
failOnConsoleErrors: false # fail test if severe console errors are detected
device: # optional mobile emulation profile (e.g. "iPhone 14")
matrix: [] # multi-browser matrix execution (e.g. [chrome, firefox])
arguments: # extra command-line flags passed to browser executable
- --start-maximized
- --disable-notifications
- --remote-allow-origins=*
capabilities: # raw WebDriver capability overrides
acceptInsecureCerts: true
pageLoadStrategy: eager
# ── Execution ────────────────────────────────────────────────────────────────
execution:
mode: local # local | remote | browserstack | saucelabs
baseUrl: https://example.com # default base URL used by open("/")
gridUrl: http://localhost:4444 # Selenium Grid hub URL (mode: remote)
parallel: none # none | methods | classes | tests | instances
threadCount: 1 # worker thread count when parallel is active
maxActiveSessions: 5 # concurrency semaphore limiting active browsers
sessionWaitSeconds: 300 # seconds a test waits for a free browser slot (0 = fail fast)
# ── CI Sharding
sharding:
enabled: false # distribute test methods across CI workers
total: 1 # total worker count
index: 0 # zero-based index of this worker
strategy: lpt # lpt (longest processing time first) | round-robin
metricsFile: target/testfly-metrics.json
# ── BrowserStack (mode: browserstack)
browserstack:
username: ${BS_USER}
accessKey: ${BS_KEY}
os: Windows # Windows | OS X
osVersion: "11"
browser: chrome # chrome | firefox | edge | safari
browserVersion: latest
device: # real mobile device name (e.g. "iPhone 14")
realMobile: true
capabilities: # extra bstack:options overrides
debug: false
# ── Sauce Labs (mode: saucelabs)
saucelabs:
username: ${SAUCE_USER}
accessKey: ${SAUCE_KEY}
region: us-west-1 # us-west-1 | eu-central | apac-southeast
platformName: "Windows 11"
browser: chrome
browserVersion: latest
capabilities: # extra sauce:options overrides
recordVideo: true
# ── Timeouts ──────────────────────────────────────── ─────────────────────────
timeouts:
explicit: 10 # seconds — WaitEngine & Locator explicit wait timeout
pageLoad: 30 # seconds — WebDriver page load timeout
# ── Retry ────────────────────────────────────────────────────────────────────
retry:
enabled: true # global automatic test retry toggle
maxAttempts: 2 # total attempts per test (1 = no retry, 2 = 1 initial + 1 retry)
# ── Locators ─────────────────────────────────────────────────────────────────
locators:
selfHealing: false # auto-heal broken locators using fallback strategies
aiHealing: false # fallback to LLM when static heuristics fail
maxDomTokens: 8000 # token limit for DOM pruning
testIdAttribute: data-testid # attribute queried by getByTestId()
# ── AI Failure Analysis & Agentic Testing ─────────────────────────────────────
ai:
enabled: true # master switch for EVERY AI surface (also settable via features.ai)
failureAnalysis: false # generate AI root-cause analysis on test failure
generatePatch: false # generate unified git diff .patch files for test failures
actionCache: true # cache compiled action plans for act() in .testfly/action-cache.json
provider: gemini # gemini | claude | openai-compatible
apiKey: ${AI_API_KEY} # provider API key
model: # optional — defaults: gemini-2.5-flash or claude-haiku-4-5-20251001
language: en # analysis language: en, tr, de, fr, es, etc.
timeoutSeconds: 20 # HTTP timeout for AI response generation
baseUrl: # optional — custom endpoint (required for openai-compatible)
# ── CI / Build Quality Gates ─────────────────────────────────────────────────
ci:
failOnPassRateBelow: 0 # 0 = disabled. Example: 85 (fails build if pass rate < 85%)
maxFlakyTests: -1 # -1 = disabled. Fails build if retried tests exceed threshold
captureMetadata: true # auto-captures provider, branch, commit, build URL in reports
# ── Notifications ────────────────────────────────────────────────────────────
notifications:
slack:
webhookUrl: ${SLACK_WEBHOOK}
notifyOnFailureOnly: false
teams:
webhookUrl: ${TEAMS_WEBHOOK}
notifyOnFailureOnly: false
# ── Reporting ────────────────────────────────────────────────────────────────
reporting:
mergeRuns: false # retain and merge sequential test runs into cumulative report (-Dtestfly.merge=true)
historyRuns: 10 # number of historical test runs to preserve in report run switcher
allure:
enabled: false # export Allure 2 test results to target/allure-results/
reportportal:
enabled: false
endpoint: http://localhost:8080
apiKey: ${RP_API_KEY}
project: testfly_project
launch: "Regression Suite"
description: "Nightly automated test run"
attributes: "env:staging;team:qa"
type: auto # auto (auto-detect Web vs API) | web | api
mode: default # default | step
# ── Screen Recording ─────────────────────────────────────────────────────────
recording:
enabled: false # record MP4 video of browser execution
mode: retain-on-failure # retain-on-failure | on | off
format: mp4 # mp4 (default, pure-Java H.264) | gif
fps: 5 # frame rate (1-10 recommended)
maxDurationSeconds: 60 # maximum video length per test
cdp: true # use Chrome DevTools Protocol screencast on Chromium
# ── Execution Tracing ────────────────────────────────────────────────────────
tracing:
enabled: false # generate standalone HTML trace bundle with step timeline and screenshots
captureOnPass: false # include passing tests in trace bundle
# ── Visual Regression ────────────────────────────────────────────────────────
visual:
baselineDir: src/test/resources/baselines # golden image directory
diffDir: target/visual-diffs # visual mismatch image output directory
defaultTolerance: 0.01 # allowable pixel difference ratio (0.0 to 1.0)
updateBaselines: false # update baselines from current run if true
# ── Multi-Session Isolation ──────────────────────────────────────────────────
sessions:
maxPerTest: 2 # max isolated browser sessions per test (e.g. multi-user chat)
# ── Performance (Core Web Vitals) ───────────────────────────── ───────────────
performance:
captureOnEveryTest: false # collect metrics after each passing browser test
lcpWarnMs: 2500 # Largest Contentful Paint threshold (ms, 0 = disabled)
fcpWarnMs: 1800 # First Contentful Paint threshold (ms)
ttfbWarnMs: 800 # Time to First Byte threshold (ms)
clsWarn: 0.1 # Cumulative Layout Shift score threshold
# ── Quarantine ───────────────────────────────────────────────────────────────
quarantine:
enabled: true # skip quarantined tests automatically
cucumberTag: quarantine # Cucumber tag marking quarantined scenarios
# ── Flakiness Tracking ───────────────────────────────────────────────────────
flakiness:
historyRuns: 20 # previous execution runs analyzed for stability score
highRiskThreshold: 33.0 # percentage flaky failure rate triggering high risk warning
failOnHighFlakiness: false # fail build if any high-risk flaky tests are detected
# ── Clock Mocking ────────────────────────────────────────────────────────────
clock:
injectHeader: false # send mock date header on HTTP requests
headerName: X-Mock-Date # custom header name for backend clock synchronization
# ── Network Interception ─────────────────────────────────────────────────────
network:
interceptEnabled: false # enable CDP network interception and route mocking
blockUrls: # URL patterns to abort globally (trackers, ads, etc.)
- "*google-analytics.com*"
- "*doubleclick.net*"
# ── Email Verification ───────────────────────────────────────────────────────
email:
provider: mailhog # mailhog | mailtrap | outlook | imap
timeoutSeconds: 30 # max wait duration for expected emails
pollIntervalMs: 1000 # inbox polling interval
autoClear: false # wipe inbox before each test method runs
mailhog:
host: localhost
port: 8025
mailtrap:
apiToken: ${MAILTRAP_TOKEN}
accountId: ${MAILTRAP_ACCOUNT}
inboxId: ${MAILTRAP_INBOX}
outlook:
tenantId: ${AZURE_TENANT_ID}
clientId: ${AZURE_CLIENT_ID}
clientSecret: ${AZURE_CLIENT_SECRET}
mailbox: test@example.com
imap:
host: imap.example.com
port: 993
ssl: true
username: ${EMAIL_USER}
password: ${EMAIL_PASS}
folder: INBOX
# ── Database Assertions ──────────────────────────────────────────────────────
database:
url: jdbc:postgresql://localhost:5432/maindb
username: ${DB_USER}
password: ${DB_PASS}
driver: org.postgresql.Driver
datasources:
analytics:
url: jdbc:postgresql://localhost:5432/analytics
username: ${ANALYTICS_USER}
password: ${ANALYTICS_PASS}
# ── API Testing ──────────────────────────────────────────────────────────────
api:
baseUrl: https://api.example.com # default base URL for ApiClient
timeoutSeconds: 30 # per-request timeout (seconds)
connectTimeoutSeconds: 30 # TCP/TLS connect timeout; must be > 0
maxConcurrentRequests: 0 # global cap on in-flight real HTTP sends; 0 = unlimited
ssl:
trustAll: false # trust any certificate chain (hostname still verified)
# trustStore: # custom truststore — mutually exclusive with trustAll
# path: certs/truststore.p12 # required once the trustStore block is present
# type: PKCS12 # PKCS12 (default) or JKS
# password: ${TESTFLY_TRUSTSTORE_PASSWORD}
logBody: false # attach request/response bodies to HTML step log
logContext: true # log query parameters and headers
prettyLog: false # format JSON bodies with indentation
logCurl: false # print equivalent curl command for failed requests
truncationLimit: 300 # maximum characters logged for response bodies
maskedHeaders: # headers redacted in execution logs
- Authorization
- Cookie
- X-Api-Key
retry:
enabled: false # retry failed HTTP requests automatically
maxAttempts: 3
backoffMs: 500
retryOnStatus: [502, 503, 504]
retryOnException: true
auth:
adminBearer:
type: bearer
token: ${ADMIN_TOKEN}
basicAuth:
type: basic
username: apiuser
password: ${API_PASS}
oauthClient:
type: oauth2
tokenUrl: https://auth.example.com/oauth/token
clientId: ${CLIENT_ID}
clientSecret: ${CLIENT_SECRET}
# ── Test Management ──────────────────────────────────────────────────────────
testmanagement:
testrail:
enabled: false
url: https://myorg.testrail.io
username: ${TR_USER}
apiKey: ${TR_KEY}
projectId: 1
suiteId: 10
runName: "Automated Suite"
autoCreateRun: true
xray:
enabled: false
mode: cloud # cloud | server
clientId: ${XRAY_ID}
clientSecret: ${XRAY_SECRET}
projectKey: PROJ
testPlanKey: PROJ-100
# ── Load Testing ─────────────────────────────────────────────────────────────
loadtest:
enabled: false # reserved flag; explicit LoadTestRunner.run() calls are not gated
baseUrl: https://api.example.com # target base URL for load tests
engine: auto # auto (prefers Gatling if present, else JDK) | gatling | jdk
users: 10 # default concurrent virtual users
rampUp: 10s # linear ramp-up duration (e.g. 10s, 1m)
hold: 30s # peak load sustain duration (e.g. 30s, 5m)
cooldown: 5s # cooldown period after test run (e.g. 5s)
maxUsers: 1000 # safety ceiling on concurrent users
resultsDir: target/loadtest # target directory for metrics and reports
reportEnabled: true # generate standalone HTML load test report
requestTimeoutSeconds: 30 # HTTP connection and request read timeout in seconds
Detailed Section Guide
Feature Switchboard
A single on/off panel for every optional framework module. It sits above each module's own settings, so you can disable a subsystem without hunting down which key controls it — and without deleting the module's detailed configuration.
features:
ai: false # no AI calls anywhere in the run
recording: true # force video on, even though recording.enabled is false
healing: false # no locator self-healing
Resolution
Each key is tri-state:
| Value | Effect |
|---|---|
absent (or null) | The module's own settings decide. Omitting the whole features: block reproduces pre-1.0.5 behaviour exactly. |
true | The module's primary enable flag is forced on. Sub-settings (recording.mode, recording.fps, …) are left untouched. |
false | The module is forced off, whatever its own settings say. |
Supported keys
| Key | Overrides | Default |
|---|---|---|
ai | ai.enabled — gates act(), aiAssert(), failure analysis, patch generation and AI locator healing | true |
recording | recording.enabled | false |
tracing | tracing.enabled — generates standalone HTML trace bundle (target/traces/) with step timeline and screenshots | false |
network | network.interceptEnabled | false |
healing | locators.selfHealing and locators.aiHealing | false |
visual | no module flag — visual regression is available unless switched off | true |
performance | performance.captureOnEveryTest | false |
flakiness | no module flag — flakiness analysis runs unless switched off | true |
quarantine | quarantine.enabled | true |
testManagement | testManagement.testrail.enabled and testManagement.xray.enabled | false |
notifications | no module flag — Slack/Teams adapters register unless switched off | true |
consoleErrors | browser.captureConsoleErrors | false |
loadtest | Overrides the parsed loadtest.enabled value; explicit LoadTestRunner.run() calls currently do not consult it | false |
What "off" means when a test asks for the feature
Background behaviour (recording, tracing, performance capture, flakiness analysis, notifications, TestRail/Xray push) simply does not run.
Features a test invokes explicitly never fail silently, because a silently skipped check is a false green:
| Call | With the feature off |
|---|---|
act("...") | IllegalStateException: AI features are disabled via ai.enabled=false or features.ai=false in testfly.yml |
aiAssert(...) | assertion fails with reason AI features are disabled via ai.enabled=false or features.ai=false |
VisualAssert.assertScreenshot(...) | TestNG SkipException — the test is reported as skipped, not passed |
Diagnostics
FrameworkBootstrap prints the active overrides at suite start:
[TestFly] features: ai=OFF, recording=ON, healing=OFF
Plugins may gate their own behaviour with a private feature name. Unrecognised names are accepted (a plugin might own them) but reported once, so a typo is visible rather than silently ignored:
[TestFly] Unknown feature name in testfly.yml: 'features.recordng' — ignored. Known features: [...]
Programmatic access is available through io.testfly.config.FeatureGate:
FeatureGate.enabled(FeatureGate.AI); // umbrella only, defaults to on
FeatureGate.enabled(FeatureGate.RECORDING, rec.isEnabled()); // umbrella over a module flag
FeatureGate.override(FeatureGate.VISUAL); // raw tri-state, null when not configured
testfly.yml is parsed tolerantly: a key with no matching configuration property is skipped and reported on stderr ([TestFly] Unknown config key 'headles' on Browser — ignored) instead of failing the run with a ConstructorException.
Browser
Controls WebDriver browser provisioning, execution mode, capabilities, and process arguments.
| Property | Type | Default | Description |
|---|---|---|---|
name | string | required | Target browser executable. Valid values: chrome, firefox, edge, safari. May be omitted only when browser.matrix is non-empty. |
headless | boolean | false | Run without a visible GUI window. Automatically forced to true when CI environment variables are detected. |
lifecycle | string | per-test | Lifecycle scope for WebDriver instances: per-test (closes browser after each test method) or per-suite (retains browser per thread across tests). |
downloadDir | string | ./target/downloads | Path where downloaded files are saved. Auto-configured in browser options. |
captureConsoleErrors | boolean | false | When true, intercepts browser console.error entries during execution. |
failOnConsoleErrors | boolean | false | When true, automatically fails the test if any SEVERE browser console errors occurred. |
device | string | null | Emulate a specific mobile device viewport and user agent (e.g. "iPhone 14", "Pixel 7"). |
matrix | list<string> | [] | Multi-browser matrix execution list (e.g. [chrome, firefox]). |
arguments | list<string> | [] | Extra CLI flags passed directly to the browser binary (e.g. --incognito, --no-sandbox). |
capabilities | map | {} | Raw capability key-values merged into WebDriver options (e.g. acceptInsecureCerts, pageLoadStrategy). |
Execution
Governs test execution topology, base URLs, concurrency, and cloud grid providers.
| Property | Type | Default | Description |
|---|---|---|---|
mode | string | required | Execution environment: local, remote, browserstack, or saucelabs. |
baseUrl | string | null | Default web URL. When calling open("/home"), TestFly prefixes it with this URL. |
gridUrl | string | null | Hub endpoint for remote Selenium Grid (used when mode: remote). Example: http://localhost:4444. |
parallel | string | none | Parallel test distribution mode: none, methods, classes, tests, instances. Validated against TestNG ParallelMode. |
threadCount | int | 1 | Concurrency worker count when parallel is enabled. |
maxActiveSessions | int | 5 | Semaphore limiting concurrent WebDriver sessions. Extra threads queue until a slot is free (see sessionWaitSeconds). Named sessions from MultiSessionManager count against the same limit. |
sessionWaitSeconds | int | 300 | How long a thread waits for a free session slot before failing with a timeout error. 0 fails immediately when no slot is free. Must be >= 0. Earlier versions used a fixed 30 seconds. |
sharding.enabled | boolean | false | Distribute tests across parallel CI worker machines (shards). |
sharding.total | int | 1 | Total number of parallel CI workers. |
sharding.index | int | 0 | Zero-based index of this worker (0 to total-1). |
sharding.strategy | string | lpt | Partitioning strategy: lpt (longest processing time first) or round-robin. |
sharding.metricsFile | string | target/testfly-metrics.json | Path to execution duration metrics used by LPT partitioning. |
Sizing rule: set maxActiveSessions to at least threadCount (plus one slot per additional named session a test opens at the same time). When parallel is not none and threadCount is greater than maxActiveSessions, TestFly logs a warning at startup: the surplus threads queue for a slot and fail with a timeout if it does not free up within sessionWaitSeconds. The run is not rejected.
Cloud Sub-Blocks: browserstack & saucelabs
execution:
mode: browserstack
browserstack:
username: ${BS_USER}
accessKey: ${BS_KEY}
os: Windows
osVersion: "11"
browser: chrome
browserVersion: latest
capabilities:
projectName: "E-Commerce"
buildName: "Build #104"
Timeouts
Centralized explicit and implicit wait durations in seconds.
| Property | Type | Default | Description |
|---|---|---|---|
explicit | int | required, > 0 | Timeout in seconds for all WaitEngine, Locator, and assertThat() DOM polling operations. |
pageLoad | int | required, > 0 | Browser document load timeout passed to WebDriver.Timeouts.pageLoadTimeout(). |
Retry
Automatic retry configuration for failed test executions.
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Global switch for automatic test retries. |
maxAttempts | int | 1 | Maximum attempts for each test. 1 means no retry. 2 means 1 original execution + 1 retry attempt. |
You can override global retry settings on individual test methods using @Retryable(maxAttempts = 3).
Locators
Smart locator synthesis and resilience settings.
| Property | Type | Default | Description |
|---|---|---|---|
selfHealing | boolean | false | When enabled, locators that time out in waitForVisible are healed using alternate heuristics (id, test-id, text, placeholder) and saved to target/healed-locators.json. |
aiHealing | boolean | false | When enabled, uses LLM reasoning to synthesize resilient fallback locators when static regex strategies fail. |
maxDomTokens | int | 8000 | Maximum token budget for DOM pruning when sending DOM to LLM. |
testIdAttribute | string | data-testid | The HTML attribute targeted by getByTestId("submit-btn"). Can be configured to data-qa, data-test, etc. |
AI Failure Analysis & Agentic Testing
AI-driven test triage, automated root-cause suggestion, and agentic execution engine.
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Master switch for every AI surface: act(), aiAssert(), failure analysis, patch generation and AI locator healing. The granular flags below choose which surfaces run; none of them can run while this is false. Also settable from the umbrella via features.ai. |
failureAnalysis | boolean | false | When true, automatically sends failure stack traces, step logs, and DOM state to the LLM upon test failure. |
generatePatch | boolean | false | When true, automatically generates a unified git diff .patch file in target/remediations/ on test failure. |
actionCache | boolean | true | When true, stores compiled act() plans in .testfly/action-cache.json; a cache hit avoids a new LLM request, while normal cache lookup and browser execution time remain. |
provider | string | claude | AI backend provider: gemini, claude, or openai-compatible. |
apiKey | string | null | API authorization key for the chosen provider. |
model | string | null | Target model. Defaults automatically to gemini-2.5-flash for Gemini or claude-haiku-4-5-20251001 for Claude if omitted. |
baseUrl | string | null | Custom API base URL (required for openai-compatible providers like Ollama, LocalAI, vLLM, or DeepSeek). |
language | string | en | Language of the generated analysis report (e.g. en, tr, de, fr). |
timeoutSeconds | int | 20 | Maximum wait time for the AI provider response. |
CI / Quality Gates
Controls CI environment detection and build pass/fail criteria.
| Property | Type | Default | Description |
|---|---|---|---|
failOnPassRateBelow | double | 0 | Minimum test pass rate percentage (e.g. 90.0). If actual pass rate is lower, build fails. 0 disables this gate. |
maxFlakyTests | int | -1 | Maximum allowable number of tests that failed initially but passed on retry. -1 disables this gate. |
captureMetadata | boolean | Auto | Extracts CI environment details (Git branch, commit SHA, PR number, build URL) into reports. |
Reporting
Settings for the built-in HTML dashboard report, run history archiving, and third-party test portals.
| Property | Type | Default | Description |
|---|---|---|---|
mergeRuns | boolean | false | When true, sequential test executions merge their test results into a cumulative report instead of overwriting previous tests. Can also be toggled via CLI: -Dtestfly.merge=true. |
historyRuns | int | 10 | Maximum number of historical test runs to preserve in target/reports/ and list in the interactive HTML report run switcher dropdown. |
TestFly automatically archives every test execution to target/reports/testfly-report-YYYYMMDD-HHmmss.html alongside the primary target/testfly-report.html. The top header includes an interactive run switcher dropdown and a dedicated Run History tab to navigate past runs, timelines, and pass rates.
reportportal
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable streaming results to ReportPortal. |
endpoint | string | null | ReportPortal server URL (e.g. http://reportportal.myorg.com:8080). |
apiKey | string | null | User API Access Token. |
project | string | superadmin_personal | ReportPortal project name. |
launch | string | TestFly Suite | Name of the test launch created in ReportPortal. |
type | string | auto | Launch enrichment type: auto (detects Web vs API), web, or api. |
mode | string | default | ReportPortal TestNG listener mode: default or step. |
attributes | string | "" | Semicolon-delimited tags and metadata attached to the launch (e.g. "env:ci;team:core"). |
allure
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | When enabled, generates Allure 2 test results in target/allure-results/. |
Notifications
Webhooks for publishing test summary reports on completion.
| Property | Type | Default | Description |
|---|---|---|---|
slack.webhookUrl | string | null | Incoming Slack Webhook URL. |
slack.notifyOnFailureOnly | boolean | false | Only send notification if one or more tests failed. |
teams.webhookUrl | string | null | Microsoft Teams Connector Webhook URL. |
teams.notifyOnFailureOnly | boolean | false | Only send notification if one or more tests failed. |
API Testing
Configuration for the built-in fluent REST client (ApiClient & BaseApiTest).
| Property | Type | Default | Description |
|---|---|---|---|
baseUrl | string | null | Default HTTP endpoint for API tests (falls back to execution.baseUrl if unset). |
baseUrls | map<string,string> | {} | Named service endpoints used by ApiClient.toService(name) / apiToService(name). A missing service falls back to api.baseUrl; if neither is set, the call fails. |
timeoutSeconds | int | 30 | HTTP request timeout in seconds. |
logBody | boolean | false | Log request and response payloads into the step timeline report. |
logContext | boolean | true | Log headers, query parameters, and HTTP methods. |
prettyLog | boolean | false | Pretty-print JSON bodies in step logs. |
logCurl | boolean | false | Generate and log equivalent curl commands for troubleshooting. |
truncationLimit | int | 300 | Max characters logged per response body to avoid bloating reports. |
maskedHeaders | list<string> | ["Authorization", "Cookie", "X-Api-Key"] | Headers redacted in test logs. |
SSL and transport settings
| Property | Type | Default | Meaning |
|---|---|---|---|
api.connectTimeoutSeconds | int | 30 | Connect timeout of the underlying JDK HttpClient. Must be > 0, otherwise the first request fails with IllegalArgumentException. |
api.maxConcurrentRequests | int | 0 | Runtime-wide cap on in-flight real HTTP sends (fair semaphore); 0 is unlimited, negative values are rejected. Mocked responses consume no permit. The value cannot change while test scopes are active. |
api.ssl.trustAll | boolean | false | Trusts any certificate chain while keeping HTTPS hostname verification; logs a one-time WARN step per scope. |
api.ssl.trustStore.path | string | — | Path to a custom truststore; replaces the default JDK truststore for this profile. Required whenever the trustStore block is present. |
api.ssl.trustStore.type | string | PKCS12 | PKCS12 or JKS; any other value is rejected. |
api.ssl.trustStore.password | string | null | Supply via ${TESTFLY_TRUSTSTORE_PASSWORD}; never commit it. |
Setting trustAll: true together with a trustStore block fails with Conflicting SSL selection. Request-level .trustStore(...) or .trustAllCerts() replaces the entire YAML SSL selection for that request. .requestTimeout(Duration) and the existing .timeout(int) set the per-request timeout; the last call wins. This is not a socket read-idle timeout. The batch limit controls logical calls; the global transport limit controls real sends.
See SSL Configuration and Timeouts & Performance.
api.retry
HTTP-level retry policy for transient server errors (e.g. 502, 503, 504).
api:
retry:
enabled: true
maxAttempts: 3
backoffMs: 500
retryOnStatus: [502, 503, 504]
retryOnException: true
api.auth
Named authentication profiles referenced in tests via @UseAuth("name") or apiClient().withAuth("name"):
api:
auth:
adminBearer:
type: bearer
token: ${SECRET_TOKEN}
gatewayUser:
type: basic
username: testuser
password: ${USER_PASS}
keyAuth:
type: apiKey
headerName: X-API-Token
apiKey: ${API_KEY}
oauth2Service:
type: oauth2
tokenUrl: https://auth.myorg.com/oauth/token
clientId: ${CLIENT_ID}
clientSecret: ${CLIENT_SECRET}
Database
Database connectivity for state assertions and test data seeding via db().
| Property | Type | Default | Description |
|---|---|---|---|
url | string | null | JDBC connection string for default datasource. |
username | string | null | Database user. |
password | string | null | Database password. |
driver | string | null | Optional explicit JDBC driver class name (auto-detected from URL for major DBs). |
datasources | map | {} | Named datasources accessed via db("name"). |
Email Verification
Mailbox testing integrations (Mailhog, Mailtrap, Outlook Graph, IMAP).
| Property | Type | Default | Description |
|---|---|---|---|
provider | string | mailhog | Active provider: mailhog, mailtrap, outlook, imap. |
timeoutSeconds | int | 30 | Timeout waiting for email arrival. |
pollIntervalMs | int | 1000 | Interval between inbox polling checks. |
autoClear | boolean | false | Wipe inbox before each test method starts. |
Performance
Automated capture and validation of Google Core Web Vitals during web tests.
| Property | Type | Default | Description |
|---|---|---|---|
captureOnEveryTest | boolean | false | Collect performance metrics once after each passing browser test. It is not an open()/navigation hook. |
lcpWarnMs | double | 0 | Largest Contentful Paint warning threshold (ms). 0 = disabled. |
fcpWarnMs | double | 0 | First Contentful Paint warning threshold (ms). |
ttfbWarnMs | double | 0 | Time to First Byte warning threshold (ms). |
clsWarn | double | 0 | Cumulative Layout Shift threshold (e.g. 0.1). |
Visual Regression
Pixel-based screenshot comparison and visual baseline management.
| Property | Type | Default | Description |
|---|---|---|---|
baselineDir | string | src/test/resources/baselines | Directory containing approved golden images. |
diffDir | string | target/visual-diffs | Directory where mismatch diff images are written. |
defaultTolerance | double | 0 | Percentage pixel mismatch tolerance (e.g. 0.02 for 2%). |
updateBaselines | boolean | false | Overwrite baseline golden images with current run screenshots. |
failOnNewBaseline | boolean | false | Fail when no baseline exists instead of creating a new baseline. |
Screen Recording & Tracing
Session capture for debugging, failure analysis, and audit compliance. See the full Video Recording Guide for details.
| Property | Type | Default | Description |
|---|---|---|---|
recording.enabled | boolean | false | Master toggle to enable Web UI video recording. |
recording.mode | string | retain-on-failure | retain-on-failure: Discard on pass, compile on fail.on: Record all tests.off: Disable recording. |
recording.format | string | mp4 | Video format: mp4 (pure-Java H.264 video, default) or gif (animated GIF). |
recording.fps | int | 2 | Captured frames per second (recommended 2–5). |
recording.maxDurationSeconds | int | 60 | Maximum recording duration in seconds before capping. |
recording.cdp | boolean | true | When true, uses CDP screencast on Chrome/Edge without blocking execution. |
tracing.enabled | boolean | false | Generates a self-contained HTML trace file containing step timeline, per-step screenshots, and failure snapshot (target/traces/{ClassName}/{testMethod}-trace.html). |
tracing.captureOnPass | boolean | false | Also capture traces for passing tests. |
Quarantine
Automated handling for flaky or under-repair tests.
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | When active, tests listed in testfly-quarantine.yml or tagged in Cucumber are skipped. |
cucumberTag | string | quarantine | Tag marking quarantined Cucumber scenarios (without @). |
Flakiness Tracking
Historical stability scoring and flaky test prevention.
| Property | Type | Default | Description |
|---|---|---|---|
historyRuns | int | 20 | Number of previous execution metrics examined. |
highRiskThreshold | double | 33.0 | Flakiness score percentage considered high risk. |
failOnHighFlakiness | boolean | false | Fails build if any test exceeds the high risk threshold. |
Test Management
Push execution outcomes and run links to Jira and TestRail.
testmanagement:
testrail:
enabled: true
url: https://yourorg.testrail.io
username: ${TR_USER}
apiKey: ${TR_KEY}
projectId: 1
suiteId: 2
autoCreateRun: true
xray:
enabled: true
mode: cloud # cloud | server
clientId: ${XRAY_ID}
clientSecret: ${XRAY_SECRET}
projectKey: PROJ
testPlanKey: PROJ-12
Clock & Network
clock.injectHeader: Injects mock date HTTP header into browser requests (defaultfalse).clock.headerName: Custom header name (default"X-Mock-Date").network.interceptEnabled: Activates Chrome DevTools Protocol network interception and stubbing (defaultfalse).network.blockUrls: Glob URL patterns to abort network requests globally (e.g. trackers, ads) (default:[]).
Load Testing
Configuration for concurrent load testing powered by Gatling or Java Virtual Threads. See the Load Testing Getting Started Guide and Load Testing Configuration for in-depth examples.
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Reserved effective flag (overridable via features.loadtest); the current LoadTestRunner.run() path does not enforce it. |
baseUrl | string | null | Base URL used for load HTTP calls after scenario/annotation overrides. Gatling falls back to execution.baseUrl; the JDK engine requires an explicit load/scenario/annotation URL. |
engine | string | auto | Execution engine: auto (Gatling if present, else JDK), gatling (strictly Gatling), or jdk (native virtual threads). |
users | int | 10 | Default number of concurrent virtual users if not specified in test code. |
rampUp | string | 10s | Linear ramp-up duration to reach peak virtual users (e.g. 10s, 1m). |
hold | string | 30s | Duration to sustain peak virtual users (e.g. 30s, 5m). |
cooldown | string | 5s | Cooldown period after peak load completes (e.g. 5s). |
maxUsers | int | 1000 | Safety ceiling for maximum allowed concurrent users. |
resultsDir | string | target/loadtest | Output directory where load test metrics and reports are saved. |
reportEnabled | boolean | true | Generates standalone HTML load test report and correlates native Gatling interactive reports. |
requestTimeoutSeconds | int | 30 | HTTP connection and request read timeout in seconds. |
Validation & Startup Diagnostics
Configuration validation is staged and fail-fast rather than aggregated:
- SnakeYAML keys without a matching property are reported on stderr and ignored.
ConfigurationLoaderrequires a browser name (or matrix), an execution mode, and positive explicit/page-load timeouts.ExecutionValidatorthen validates parallel mode, thread/session limits, and related execution constraints.- Provider-specific requirements, such as cloud credentials, are checked when that provider is created. The loader does not aggregate these failures or validate
execution.baseUrlas illustrated previously.