Skip to main content
Java 21 · Selenium 4 · TestNG · JUnit 5 · Cucumber · AI/MCP

Test automation without the noise

AgenticCheckoutTest.java
public class AgenticCheckoutTest extends BaseTest {
@Test
public void autonomousCheckoutFlow() {
open();
// 1. Goal-oriented action compiled & frozen to .testfly/action-cache.json
act("Log in as 'standard_user', add Backpack to cart, proceed to checkout");
// 2. Zero-shot semantic assertion on live DOM (anti-throttle protected)
assertThatPage().satisfiesAi("Checkout overview displays 1 item with valid tax");
assertThatPage().violatesAi("Error banner, stock shortage, or checkout failure");
}
}

A Java test automation SDK for modern teams. TestFly combines browser sessions, API testing, reporting, and optional AI tools. A separate Node.js MCP bridge offers code generation and project scaffolding.

1Single Maven Dependency
1.0.7SDK Source Version
0LLM Calls on Cache Hit
6Separate Bridge Tools
Before / After

Write tests,
not framework plumbing

See how TestFly replaces hundreds of lines of fragile waits, broken locator workarounds, and repetitive setup with clean, self-healing automation.

Explicit waits, stale elements, and JS scroll hacks vs. instant auto-waiting & actionability checks

Plain Selenium14 lines · 2 explicit waits · StaleElement prone
CheckoutTest.java
// Plain Selenium: Flaky explicit wait & JS scroll hack
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement btn = wait.until(
ExpectedConditions.elementToBeClickable(By.id("checkout")));
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView(true);", btn);
btn.click();
// Brittle XPath text match with manual visibility check
WebElement status = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.xpath("//span[contains(@class,'order-badge')]")));
Assert.assertEquals(status.getText().trim(), "Confirmed");
TestFly2 lines · Built-in auto-waiting
CheckoutTest.java
// TestFly: Auto-scroll, actionability check & self-healing
find("#checkout").click();
// Web-first semantic assertion with built-in auto-retry
assertThat(getByRole(Role.STATUS))
.isVisible()
.hasText("Confirmed");
Features

Everything you need,
nothing you don't

One dependency. Zero required config. Full-stack automation power ready the moment you extend BaseTest.

Zero Boilerplate Architecture

Extend BaseTest, write @Test methods, and go. ThreadLocal driver lifecycle, waits, retries, reports, and screenshots are all managed out of the box.

class CheckoutTest extends BaseTest {
@Test
void completeOrder() {
open();
find("#checkout").click();
assertThat(find("[role='alert']"))
.isVisible();
}
}

Agentic Testing & Compile & Freeze

Execute high-level natural language goals via act("..."). The first run compiles concrete Selenium steps into .testfly/action-cache.json; cache hits replay without a new LLM request.

// First run compiles; subsequent runs replay frozen cache
act("Delete the first item in the cart and checkout");
// Dynamic semantic intent locator
byIntent("Proceed to payment").click();

AI Self-Healing & Auto-PR Patches

When locators break, DomPruner compresses the DOM to <8K tokens and synthesizes a healed selector. On permanent failure, it generates target/remediations/*.patch ready for git apply.

Semantic AI Assertions

Verify complex visual or logical state using LLM reasoning against the live DOM. Each assertion performs one AI evaluation; provider rate limits still apply.

assertThatPage()
.satisfiesAi("Order confirmation summary shows valid total");
assertThatPage()
.violatesAi("500 server error or session expired");

Reports Stakeholders Actually Read

Tabbed HTML dashboard with pass-rate gauge, Flakiness Radar, retry badges, expandable error stacks, timeline screenshots, video recordings, and dark mode.

Separate MCP Bridge & Codegen

The separate Node.js bridge exposes six MCP tools. Use Playwright MCP for live browser inspection, then generate and review Java from observed actions. Live recording is not shipped.

# From the separate testfly-mcp checkout
node bin/testfly-mcp.js --help
# Configure the script as an MCP server; see the CLI guide.
SDK Source Version · 1.0.7

One Dependency to Power Your Entire Stack

No dependency conflicts or classpath bloat. TestFly bundles Selenium 4, smart waits, native CDP screencast, AI engine, and test runner bridges in a single verified artifact.

Java 21+Release verification pendingZero ConflictsApache 2.0
pom.xml
<dependency>
<groupId>io.github.hakanngul</groupId>
<artifactId>testfly</artifactId>
<version>1.0.7</version>
</dependency>

Inside the Java SDK

16 SDK capabilities. Some require configuration, a supported browser, an optional dependency, or an external service.

🎥

Test Execution Video

CDP on Chromium, screenshot fallback elsewhere; retain failed runs as MP4 or GIF.

Enable in YAML
📊

ReportPortal & Allure Dashboards

Write Allure results or send runs to ReportPortal with its framework agent and server.

Optional agent / service
🗄️

Database Testing (DbClient)

Run parameterized SQL queries and row assertions through JDBC.

JDBC driver + datasource
🎯

TestRail & Jira Xray Sync

Send annotated test statuses and error comments to TestRail or Xray; screenshots are not uploaded.

Service + credentials
♿

Accessibility Auditing (axe-core)

Run explicit axe-core WCAG scans with accessibility().run() at the points your flow requires.

JS-capable browser
📈

Core Web Vitals Performance

Collect LCP, FCP, TTFB, and CLS where the browser exposes them, then assert performance thresholds.

Browser-dependent
📋

Data-Driven Testing (@TestData)

Load an Excel, CSV, JSON, or database row and read it through getTestData() or typed key access.

Apache POI for Excel
🌐

CDP Network Interception

Intercept and mock network requests through Chromium CDP.

Chrome / Edge required
🔁

Flakiness Radar & Quarantine

Score failures across prior runs; skip selected tests with testfly-quarantine.yml.

Run history needed
🔐

@PreCondition Session Cache

Cache and restore cookies/localStorage for subsequent tests on the same thread.

Thread-local cache
📧

Email & OTP Verification

Read OTPs and links from Mailhog, Mailtrap, Outlook Graph, or IMAP mailboxes.

Mailbox; extra IMAP dependency
📸

Visual Regression Testing

Compare screenshots with reviewed baselines and configurable pixel tolerance.

Reviewed baseline needed
🕐

Browser Clock Mocking

Mock the client-side Date clock; persistence across navigation depends on Chromium CDP.

Browser-dependent
🪜

StepLogger Timeline

Log named steps with optional screenshots and show them in the report timeline.

Screenshots optional
☁️

Cloud & Grid Execution

Run through Selenium Grid, BrowserStack, or Sauce Labs drivers.

Grid / cloud access
🔌

Extensible SPI Architecture

Plug in custom driver providers, lifecycle hooks, and report adapters via standard Java SPI.

Custom adapter optional

Companion Tools

3 separate Node/IDE tools; not included in the Java SDK JAR.

🎙️

MCP Bridge & Java Codegen

The separate Node bridge provides six tools for scaffolding and Java from supplied actions; live browsing needs Playwright MCP.

Separate Node project
💻

TestFly CLI Toolkit

The separate Node bridge supports init, --version and --help; record and studio are not available.

Separate Node project
🧩

IDE Plugins (IntelliJ & VS Code)

Separate IntelliJ and VS Code extensions requiring installation, MCP setup, and environment checks.

Separate IDE extensions
Java SDK & Separate MCP Bridge

Record test execution,
generate Java from observed actions

The Java SDK optionally captures execution video. The separate Node.js MCP bridge can turn supplied browser actions into Java test code; browser inspection uses Playwright MCP. A live interaction recorder is not currently shipped.

com/example/pages/InventoryPage.java
package com.example.pages;
import io.testfly.test.BasePage;
import io.testfly.locator.Locator;
import org.openqa.selenium.WebDriver;
public class InventoryPage extends BasePage {
// Illustrative locators: verify these against the actual page before use
private final Locator backpackBtn = getByTestId("add-to-cart-sauce-labs-backpack");
private final Locator cartBadge = getByTestId("shopping-cart-badge");
private final Locator checkoutBtn = getByTestId("checkout");
public InventoryPage(WebDriver driver) {
super(driver);
}
public InventoryPage addBackpackToCart() {
backpackBtn.click();
return this;
}
public InventoryPage proceedToCheckout() {
checkoutBtn.click();
return this;
}
}
🎥
Test Execution VideoCDP on Chromium, screenshot fallback for other drivers; retain-on-failure mode
👁️
Browser InspectionInspect the live page with separate Playwright MCP and verify real selectors
🏗️
Codegen From Supplied ActionsThe bridge emits TestNG Java code; review and compile it before adding it to your project
🤖
Six MCP ToolsSeparate bridge: scaffolding, code generation, action cache, and remediation tools
Declarative Orchestration

One unified config,
complete test orchestration

Stop writing fragile framework plumbing. Configure parallel tests, browser session limits, CDP-preferred MP4 recording, and locator recovery in one YAML file. Allure is enabled; add real credentials and enable the switches for DeepSeek/OpenAI analysis and ReportPortal.

⚡
ThreadLocal Parallel EngineSafe concurrent test execution at method/class level
🎥
Native CDP MP4 ScreencastCaptured during tests, retained only on failure
🧠
DeepSeek & OpenAI AI EngineOptional failure analysis and patch generation with an API key
📊
Unified Enterprise ReportingLocal HTML and Allure on; ReportPortal needs credentials to enable
testfly.yml
browser:
name: chrome # Selects the local Chrome driver
headless: false # Opens a visible browser window
lifecycle: per-test # Closes the browser after each test
arguments:
- --start-maximized # Maximizes the window (sets size in headless mode)
- --disable-notifications # Disables Chrome notifications
- --remote-allow-origins=* # Passed through as a Chrome launch argument
capabilities:
acceptInsecureCerts: true # Accepts invalid TLS certificates
pageLoadStrategy: normal # Waits for full page load
execution:
mode: local # Uses a local browser driver
baseUrl: https://www.saucedemo.com/ # Base URL for relative web navigation
gridUrl: http://localhost:4444/wd/hub # Used only when mode: remote
parallel: methods # Runs TestNG methods in parallel
threadCount: 4 # Number of parallel TestNG threads
maxActiveSessions: 4 # Limit on concurrent browser sessions
locators:
selfHealing: true # Attempts recovery for failed locators
aiHealing: false # AI locator healing off; enable with an API key
ai:
failureAnalysis: false # Disables failure analysis
generatePatch: false # Disables AI patch generation
provider: openai-compatible # OpenAI-compatible provider for DeepSeek
baseUrl: https://api.deepseek.com # Provider URL for AI requests
apiKey: "${AI_API_KEY}" # Resolves the key from an environment variable
model: deepseek-v4-flash # Model name sent with requests
language: en # Failure analysis response language
timeoutSeconds: 20 # AI request timeout in seconds
recording:
enabled: true # Enables recording for browser tests
mode: retain-on-failure # Keeps video only on failure
format: mp4 # Saves MP4 video (GIF fallback on error)
fps: 5 # Target frames captured per second
maxDurationSeconds: 60 # Caps stored frames at fps × duration
cdp: true # Prefers CDP; JUnit 5 ignores this field
reporting:
allureEnabled: true # Enables Allure reporting integration
htmlReport: true # Generates the local HTML test report
reportPortal:
enabled: false # Disables ReportPortal publishing
endpoint: "${REPORTPORTAL_ENDPOINT:-https://reportportal.example.com}" # Server URL; example fallback if unset
apiKey: "${REPORTPORTAL_API_KEY}" # Resolves the access key from the environment
project: demo-web # ReportPortal project name
launch: "Demo Web - Dev" # Report launch name
description: "Automated test execution powered by TestFly" # Launch description
attributes: "env:dev" # Launch attributes
type: auto # Detects API or Web run type
mode: default # Accepted; not applied by the runtime
api:
baseUrl: https://fakeapi.net # Default base URL for the API client
timeoutSeconds: 30 # API request timeout in seconds
logBody: false # Omits response bodies from logs
retry:
enabled: false # Disables retries for failed tests
maxAttempts: 2 # Only used when retries are enabled
timeouts:
explicit: 10 # Element wait timeout in seconds
pageLoad: 30 # Page load timeout in seconds
FAQ

Questions, Answered

Straight answers on setup, running tests, optional AI features, and integrations.

TestFly is a multi-domain test automation SDK for Java 21. Alongside Selenium-based web tests, it offers tools for API, load, and other test domains. The browser driver is an adapter, not the entire framework.

With Java 21 and Maven, add the TestFly dependency and define browser, execution mode, and timeouts in src/test/resources/testfly.yml. Use BaseTest for a web test or BaseApiTest for an API test. Follow the Getting Started guide for a complete example.

The standard bootstrap looks for a configuration file: first the path set with -Dtestfly.config, then testfly.yml on the classpath, then in the working directory. Set testfly.profile to select a profile-specific filename. Missing files cause an error; you do not need to list every optional feature in YAML.

TestFly has adapters for TestNG, JUnit 5, and Cucumber BDD; lifecycle and some features can differ by adapter. Local browsers and remote providers work when their required drivers, configuration, and credentials are available.

For TestNG, execution.parallel and execution.threadCount control parallelism; execution.maxActiveSessions limits concurrent browser sessions. Local HTML reporting is a separate setting, while Allure and ReportPortal are optional integrations. ReportPortal also requires a valid endpoint and credentials.

No. locators.selfHealing enables local locator recovery; locators.aiHealing enables AI-assisted recovery. Failure analysis requires ai.failureAnalysis and a configured provider and API key. Neither recovery nor analysis guarantees a successful result.

No. When ai.generatePatch is enabled, AI access is configured, a source snippet can be found, and a valid diff is returned, TestFly can write a reviewable .patch file under target/remediations/. You decide whether to apply it.

An action plan created with act(...) can be stored in .testfly/action-cache.json. A cache hit for the same goal avoids a new LLM request; browser actions and waits still run. Caching and AI-provider use depend on their configuration.

No. The Node.js MCP bridge is separate from the Java SDK and provides project scaffolding and code-generation tools; live browser inspection uses Playwright MCP. The current Node bridge has no testfly record command: that command belongs to the historical Python recorder. See the CLI guide for details.

Yes. In web tests, getDriver() returns the live WebDriver session, and TestFly Locator objects can be converted to Selenium By with toBy(). CDP features depend on browser and driver support.

Ready to delete your boilerplate?

One dependency. One YAML file. Tests that read like intent.