Skip to main content

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:

  1. System Property — -Dtestfly.config=/path/to/custom.yml (highest priority)
  2. Classpath Resource — src/test/resources/testfly.yml
  3. 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):

  1. .env file — A .env file in the project root (next to pom.xml). Values here deliberately win over the shell so that a stale exported credential cannot silently override the project's checked-out configuration.
  2. Shell environment variable — System.getenv("VAR_NAME")
  3. System property — -DVAR_NAME=value or System.getProperty("VAR_NAME")
  4. 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
Programmatic access

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
Profile selection

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:

ValueEffect
absent (or null)The module's own settings decide. Omitting the whole features: block reproduces pre-1.0.5 behaviour exactly.
trueThe module's primary enable flag is forced on. Sub-settings (recording.mode, recording.fps, …) are left untouched.
falseThe module is forced off, whatever its own settings say.

Supported keys​

KeyOverridesDefault
aiai.enabled — gates act(), aiAssert(), failure analysis, patch generation and AI locator healingtrue
recordingrecording.enabledfalse
tracingtracing.enabled — generates standalone HTML trace bundle (target/traces/) with step timeline and screenshotsfalse
networknetwork.interceptEnabledfalse
healinglocators.selfHealing and locators.aiHealingfalse
visualno module flag — visual regression is available unless switched offtrue
performanceperformance.captureOnEveryTestfalse
flakinessno module flag — flakiness analysis runs unless switched offtrue
quarantinequarantine.enabledtrue
testManagementtestManagement.testrail.enabled and testManagement.xray.enabledfalse
notificationsno module flag — Slack/Teams adapters register unless switched offtrue
consoleErrorsbrowser.captureConsoleErrorsfalse
loadtestOverrides the parsed loadtest.enabled value; explicit LoadTestRunner.run() calls currently do not consult itfalse

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:

CallWith 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
Unknown keys no longer abort the suite

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.

PropertyTypeDefaultDescription
namestringrequiredTarget browser executable. Valid values: chrome, firefox, edge, safari. May be omitted only when browser.matrix is non-empty.
headlessbooleanfalseRun without a visible GUI window. Automatically forced to true when CI environment variables are detected.
lifecyclestringper-testLifecycle scope for WebDriver instances: per-test (closes browser after each test method) or per-suite (retains browser per thread across tests).
downloadDirstring./target/downloadsPath where downloaded files are saved. Auto-configured in browser options.
captureConsoleErrorsbooleanfalseWhen true, intercepts browser console.error entries during execution.
failOnConsoleErrorsbooleanfalseWhen true, automatically fails the test if any SEVERE browser console errors occurred.
devicestringnullEmulate a specific mobile device viewport and user agent (e.g. "iPhone 14", "Pixel 7").
matrixlist<string>[]Multi-browser matrix execution list (e.g. [chrome, firefox]).
argumentslist<string>[]Extra CLI flags passed directly to the browser binary (e.g. --incognito, --no-sandbox).
capabilitiesmap{}Raw capability key-values merged into WebDriver options (e.g. acceptInsecureCerts, pageLoadStrategy).

Execution​

Governs test execution topology, base URLs, concurrency, and cloud grid providers.

PropertyTypeDefaultDescription
modestringrequiredExecution environment: local, remote, browserstack, or saucelabs.
baseUrlstringnullDefault web URL. When calling open("/home"), TestFly prefixes it with this URL.
gridUrlstringnullHub endpoint for remote Selenium Grid (used when mode: remote). Example: http://localhost:4444.
parallelstringnoneParallel test distribution mode: none, methods, classes, tests, instances. Validated against TestNG ParallelMode.
threadCountint1Concurrency worker count when parallel is enabled.
maxActiveSessionsint5Semaphore limiting concurrent WebDriver sessions. Extra threads queue until a slot is free (see sessionWaitSeconds). Named sessions from MultiSessionManager count against the same limit.
sessionWaitSecondsint300How 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.enabledbooleanfalseDistribute tests across parallel CI worker machines (shards).
sharding.totalint1Total number of parallel CI workers.
sharding.indexint0Zero-based index of this worker (0 to total-1).
sharding.strategystringlptPartitioning strategy: lpt (longest processing time first) or round-robin.
sharding.metricsFilestringtarget/testfly-metrics.jsonPath 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.

PropertyTypeDefaultDescription
explicitintrequired, > 0Timeout in seconds for all WaitEngine, Locator, and assertThat() DOM polling operations.
pageLoadintrequired, > 0Browser document load timeout passed to WebDriver.Timeouts.pageLoadTimeout().

Retry​

Automatic retry configuration for failed test executions.

PropertyTypeDefaultDescription
enabledbooleantrueGlobal switch for automatic test retries.
maxAttemptsint1Maximum attempts for each test. 1 means no retry. 2 means 1 original execution + 1 retry attempt.
Method-Level Override

You can override global retry settings on individual test methods using @Retryable(maxAttempts = 3).


Locators​

Smart locator synthesis and resilience settings.

PropertyTypeDefaultDescription
selfHealingbooleanfalseWhen enabled, locators that time out in waitForVisible are healed using alternate heuristics (id, test-id, text, placeholder) and saved to target/healed-locators.json.
aiHealingbooleanfalseWhen enabled, uses LLM reasoning to synthesize resilient fallback locators when static regex strategies fail.
maxDomTokensint8000Maximum token budget for DOM pruning when sending DOM to LLM.
testIdAttributestringdata-testidThe 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.

PropertyTypeDefaultDescription
enabledbooleantrueMaster 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.
failureAnalysisbooleanfalseWhen true, automatically sends failure stack traces, step logs, and DOM state to the LLM upon test failure.
generatePatchbooleanfalseWhen true, automatically generates a unified git diff .patch file in target/remediations/ on test failure.
actionCachebooleantrueWhen 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.
providerstringclaudeAI backend provider: gemini, claude, or openai-compatible.
apiKeystringnullAPI authorization key for the chosen provider.
modelstringnullTarget model. Defaults automatically to gemini-2.5-flash for Gemini or claude-haiku-4-5-20251001 for Claude if omitted.
baseUrlstringnullCustom API base URL (required for openai-compatible providers like Ollama, LocalAI, vLLM, or DeepSeek).
languagestringenLanguage of the generated analysis report (e.g. en, tr, de, fr).
timeoutSecondsint20Maximum wait time for the AI provider response.

CI / Quality Gates​

Controls CI environment detection and build pass/fail criteria.

PropertyTypeDefaultDescription
failOnPassRateBelowdouble0Minimum test pass rate percentage (e.g. 90.0). If actual pass rate is lower, build fails. 0 disables this gate.
maxFlakyTestsint-1Maximum allowable number of tests that failed initially but passed on retry. -1 disables this gate.
captureMetadatabooleanAutoExtracts 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.

PropertyTypeDefaultDescription
mergeRunsbooleanfalseWhen 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.
historyRunsint10Maximum number of historical test runs to preserve in target/reports/ and list in the interactive HTML report run switcher dropdown.
Run Archiving & History Switcher

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​

PropertyTypeDefaultDescription
enabledbooleanfalseEnable streaming results to ReportPortal.
endpointstringnullReportPortal server URL (e.g. http://reportportal.myorg.com:8080).
apiKeystringnullUser API Access Token.
projectstringsuperadmin_personalReportPortal project name.
launchstringTestFly SuiteName of the test launch created in ReportPortal.
typestringautoLaunch enrichment type: auto (detects Web vs API), web, or api.
modestringdefaultReportPortal TestNG listener mode: default or step.
attributesstring""Semicolon-delimited tags and metadata attached to the launch (e.g. "env:ci;team:core").

allure​

PropertyTypeDefaultDescription
enabledbooleanfalseWhen enabled, generates Allure 2 test results in target/allure-results/.

Notifications​

Webhooks for publishing test summary reports on completion.

PropertyTypeDefaultDescription
slack.webhookUrlstringnullIncoming Slack Webhook URL.
slack.notifyOnFailureOnlybooleanfalseOnly send notification if one or more tests failed.
teams.webhookUrlstringnullMicrosoft Teams Connector Webhook URL.
teams.notifyOnFailureOnlybooleanfalseOnly send notification if one or more tests failed.

API Testing​

Configuration for the built-in fluent REST client (ApiClient & BaseApiTest).

PropertyTypeDefaultDescription
baseUrlstringnullDefault HTTP endpoint for API tests (falls back to execution.baseUrl if unset).
baseUrlsmap<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.
timeoutSecondsint30HTTP request timeout in seconds.
logBodybooleanfalseLog request and response payloads into the step timeline report.
logContextbooleantrueLog headers, query parameters, and HTTP methods.
prettyLogbooleanfalsePretty-print JSON bodies in step logs.
logCurlbooleanfalseGenerate and log equivalent curl commands for troubleshooting.
truncationLimitint300Max characters logged per response body to avoid bloating reports.
maskedHeaderslist<string>["Authorization", "Cookie", "X-Api-Key"]Headers redacted in test logs.

SSL and transport settings​

PropertyTypeDefaultMeaning
api.connectTimeoutSecondsint30Connect timeout of the underlying JDK HttpClient. Must be > 0, otherwise the first request fails with IllegalArgumentException.
api.maxConcurrentRequestsint0Runtime-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.trustAllbooleanfalseTrusts any certificate chain while keeping HTTPS hostname verification; logs a one-time WARN step per scope.
api.ssl.trustStore.pathstring—Path to a custom truststore; replaces the default JDK truststore for this profile. Required whenever the trustStore block is present.
api.ssl.trustStore.typestringPKCS12PKCS12 or JKS; any other value is rejected.
api.ssl.trustStore.passwordstringnullSupply 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().

PropertyTypeDefaultDescription
urlstringnullJDBC connection string for default datasource.
usernamestringnullDatabase user.
passwordstringnullDatabase password.
driverstringnullOptional explicit JDBC driver class name (auto-detected from URL for major DBs).
datasourcesmap{}Named datasources accessed via db("name").

Email Verification​

Mailbox testing integrations (Mailhog, Mailtrap, Outlook Graph, IMAP).

PropertyTypeDefaultDescription
providerstringmailhogActive provider: mailhog, mailtrap, outlook, imap.
timeoutSecondsint30Timeout waiting for email arrival.
pollIntervalMsint1000Interval between inbox polling checks.
autoClearbooleanfalseWipe inbox before each test method starts.

Performance​

Automated capture and validation of Google Core Web Vitals during web tests.

PropertyTypeDefaultDescription
captureOnEveryTestbooleanfalseCollect performance metrics once after each passing browser test. It is not an open()/navigation hook.
lcpWarnMsdouble0Largest Contentful Paint warning threshold (ms). 0 = disabled.
fcpWarnMsdouble0First Contentful Paint warning threshold (ms).
ttfbWarnMsdouble0Time to First Byte warning threshold (ms).
clsWarndouble0Cumulative Layout Shift threshold (e.g. 0.1).

Visual Regression​

Pixel-based screenshot comparison and visual baseline management.

PropertyTypeDefaultDescription
baselineDirstringsrc/test/resources/baselinesDirectory containing approved golden images.
diffDirstringtarget/visual-diffsDirectory where mismatch diff images are written.
defaultTolerancedouble0Percentage pixel mismatch tolerance (e.g. 0.02 for 2%).
updateBaselinesbooleanfalseOverwrite baseline golden images with current run screenshots.
failOnNewBaselinebooleanfalseFail 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.

PropertyTypeDefaultDescription
recording.enabledbooleanfalseMaster toggle to enable Web UI video recording.
recording.modestringretain-on-failureretain-on-failure: Discard on pass, compile on fail.
on: Record all tests.
off: Disable recording.
recording.formatstringmp4Video format: mp4 (pure-Java H.264 video, default) or gif (animated GIF).
recording.fpsint2Captured frames per second (recommended 2–5).
recording.maxDurationSecondsint60Maximum recording duration in seconds before capping.
recording.cdpbooleantrueWhen true, uses CDP screencast on Chrome/Edge without blocking execution.
tracing.enabledbooleanfalseGenerates a self-contained HTML trace file containing step timeline, per-step screenshots, and failure snapshot (target/traces/{ClassName}/{testMethod}-trace.html).
tracing.captureOnPassbooleanfalseAlso capture traces for passing tests.

Quarantine​

Automated handling for flaky or under-repair tests.

PropertyTypeDefaultDescription
enabledbooleantrueWhen active, tests listed in testfly-quarantine.yml or tagged in Cucumber are skipped.
cucumberTagstringquarantineTag marking quarantined Cucumber scenarios (without @).

Flakiness Tracking​

Historical stability scoring and flaky test prevention.

PropertyTypeDefaultDescription
historyRunsint20Number of previous execution metrics examined.
highRiskThresholddouble33.0Flakiness score percentage considered high risk.
failOnHighFlakinessbooleanfalseFails 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 (default false).
  • clock.headerName: Custom header name (default "X-Mock-Date").
  • network.interceptEnabled: Activates Chrome DevTools Protocol network interception and stubbing (default false).
  • 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.

PropertyTypeDefaultDescription
enabledbooleanfalseReserved effective flag (overridable via features.loadtest); the current LoadTestRunner.run() path does not enforce it.
baseUrlstringnullBase 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.
enginestringautoExecution engine: auto (Gatling if present, else JDK), gatling (strictly Gatling), or jdk (native virtual threads).
usersint10Default number of concurrent virtual users if not specified in test code.
rampUpstring10sLinear ramp-up duration to reach peak virtual users (e.g. 10s, 1m).
holdstring30sDuration to sustain peak virtual users (e.g. 30s, 5m).
cooldownstring5sCooldown period after peak load completes (e.g. 5s).
maxUsersint1000Safety ceiling for maximum allowed concurrent users.
resultsDirstringtarget/loadtestOutput directory where load test metrics and reports are saved.
reportEnabledbooleantrueGenerates standalone HTML load test report and correlates native Gatling interactive reports.
requestTimeoutSecondsint30HTTP 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.
  • ConfigurationLoader requires a browser name (or matrix), an execution mode, and positive explicit/page-load timeouts.
  • ExecutionValidator then 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.baseUrl as illustrated previously.