Test automation without the noise
public class AgenticCheckoutTest extends BaseTest {@Testpublic void autonomousCheckoutFlow() {open();// 1. Goal-oriented action compiled & frozen to .testfly/action-cache.jsonact("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.
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 Selenium: Flaky explicit wait & JS scroll hackWebDriverWait 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 checkWebElement status = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[contains(@class,'order-badge')]")));Assert.assertEquals(status.getText().trim(), "Confirmed");
// TestFly: Auto-scroll, actionability check & self-healingfind("#checkout").click();// Web-first semantic assertion with built-in auto-retryassertThat(getByRole(Role.STATUS)).isVisible().hasText("Confirmed");
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 {@Testvoid 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 cacheact("Delete the first item in the cart and checkout");// Dynamic semantic intent locatorbyIntent("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 checkoutnode bin/testfly-mcp.js --help# Configure the script as an MCP server; see the CLI guide.
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.
<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 YAMLReportPortal & Allure Dashboards
Write Allure results or send runs to ReportPortal with its framework agent and server.
Optional agent / serviceDatabase Testing (DbClient)
Run parameterized SQL queries and row assertions through JDBC.
JDBC driver + datasourceTestRail & Jira Xray Sync
Send annotated test statuses and error comments to TestRail or Xray; screenshots are not uploaded.
Service + credentialsAccessibility Auditing (axe-core)
Run explicit axe-core WCAG scans with accessibility().run() at the points your flow requires.
JS-capable browserCore Web Vitals Performance
Collect LCP, FCP, TTFB, and CLS where the browser exposes them, then assert performance thresholds.
Browser-dependentData-Driven Testing (@TestData)
Load an Excel, CSV, JSON, or database row and read it through getTestData() or typed key access.
Apache POI for ExcelCDP Network Interception
Intercept and mock network requests through Chromium CDP.
Chrome / Edge requiredFlakiness 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 cacheEmail & OTP Verification
Read OTPs and links from Mailhog, Mailtrap, Outlook Graph, or IMAP mailboxes.
Mailbox; extra IMAP dependencyVisual Regression Testing
Compare screenshots with reviewed baselines and configurable pixel tolerance.
Reviewed baseline neededBrowser Clock Mocking
Mock the client-side Date clock; persistence across navigation depends on Chromium CDP.
Browser-dependentStepLogger Timeline
Log named steps with optional screenshots and show them in the report timeline.
Screenshots optionalCloud & Grid Execution
Run through Selenium Grid, BrowserStack, or Sauce Labs drivers.
Grid / cloud accessExtensible SPI Architecture
Plug in custom driver providers, lifecycle hooks, and report adapters via standard Java SPI.
Custom adapter optionalCompanion 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 projectTestFly CLI Toolkit
The separate Node bridge supports init, --version and --help; record and studio are not available.
Separate Node projectIDE Plugins (IntelliJ & VS Code)
Separate IntelliJ and VS Code extensions requiring installation, MCP setup, and environment checks.
Separate IDE extensionsRecord 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.
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 useprivate 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;}}
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.
browser:name: chrome # Selects the local Chrome driverheadless: false # Opens a visible browser windowlifecycle: per-test # Closes the browser after each testarguments:- --start-maximized # Maximizes the window (sets size in headless mode)- --disable-notifications # Disables Chrome notifications- --remote-allow-origins=* # Passed through as a Chrome launch argumentcapabilities:acceptInsecureCerts: true # Accepts invalid TLS certificatespageLoadStrategy: normal # Waits for full page loadexecution:mode: local # Uses a local browser driverbaseUrl: https://www.saucedemo.com/ # Base URL for relative web navigationgridUrl: http://localhost:4444/wd/hub # Used only when mode: remoteparallel: methods # Runs TestNG methods in parallelthreadCount: 4 # Number of parallel TestNG threadsmaxActiveSessions: 4 # Limit on concurrent browser sessionslocators:selfHealing: true # Attempts recovery for failed locatorsaiHealing: false # AI locator healing off; enable with an API keyai:failureAnalysis: false # Disables failure analysisgeneratePatch: false # Disables AI patch generationprovider: openai-compatible # OpenAI-compatible provider for DeepSeekbaseUrl: https://api.deepseek.com # Provider URL for AI requestsapiKey: "${AI_API_KEY}" # Resolves the key from an environment variablemodel: deepseek-v4-flash # Model name sent with requestslanguage: en # Failure analysis response languagetimeoutSeconds: 20 # AI request timeout in secondsrecording:enabled: true # Enables recording for browser testsmode: retain-on-failure # Keeps video only on failureformat: mp4 # Saves MP4 video (GIF fallback on error)fps: 5 # Target frames captured per secondmaxDurationSeconds: 60 # Caps stored frames at fps × durationcdp: true # Prefers CDP; JUnit 5 ignores this fieldreporting:allureEnabled: true # Enables Allure reporting integrationhtmlReport: true # Generates the local HTML test reportreportPortal:enabled: false # Disables ReportPortal publishingendpoint: "${REPORTPORTAL_ENDPOINT:-https://reportportal.example.com}" # Server URL; example fallback if unsetapiKey: "${REPORTPORTAL_API_KEY}" # Resolves the access key from the environmentproject: demo-web # ReportPortal project namelaunch: "Demo Web - Dev" # Report launch namedescription: "Automated test execution powered by TestFly" # Launch descriptionattributes: "env:dev" # Launch attributestype: auto # Detects API or Web run typemode: default # Accepted; not applied by the runtimeapi:baseUrl: https://fakeapi.net # Default base URL for the API clienttimeoutSeconds: 30 # API request timeout in secondslogBody: false # Omits response bodies from logsretry:enabled: false # Disables retries for failed testsmaxAttempts: 2 # Only used when retries are enabledtimeouts:explicit: 10 # Element wait timeout in secondspageLoad: 30 # Page load timeout in seconds
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.