Robot Framework Java GUI Library
Automate Java desktop apps โ Swing, SWT, and Eclipse RCP โ straight from Robot Framework. A Rust + PyO3 core does the heavy lifting so you write plain, readable test cases with inline assertions. Real widgets, real clicks, real screenshots. No brittle pixel-matching, no vendor lock-in.
The Swiss Army knife for Java GUI testing: one library, three toolkits, human-readable tests.
๐ Keyword Documentation โ every keyword, with a runnable example: Swing ยท SWT ยท Eclipse RCP
Features
- High Performance: Core library written in Rust with PyO3 bindings for Python
- Multi-Toolkit Support: Java Swing, SWT, and Eclipse RCP โ see the maturity table below for the support level of each
- Inline Assertions: Browser Library-style assertions with automatic retry (via
robotframework-assertion-engine) - CSS-like Selectors: Intuitive element locators similar to web testing
- XPath Support: XPath-style locator syntax for complex queries
- Comprehensive Component Support: Buttons, text fields, tables, trees, lists, menus, and more
- Java Agent: Non-invasive instrumentation via Java agent
- Cross-Platform: Designed for Windows, macOS, and Linux
Toolkit Support & Maturity
The three toolkits are not at the same level of maturity. Support level reflects how thoroughly each is verified against real applications:
| Toolkit | Import | Keywords | Maturity | Notes |
|---|---|---|---|---|
| Swing | JavaGui.Swing |
~108 | Stable | Fully implemented and exercised end-to-end against real Swing apps. Recommended for production use. |
| SWT | JavaGui.Swt |
~71 | Stable | Fully implemented and exercised end-to-end against a real SWT app (widgets, shells, tables, trees, text, selection). |
| Eclipse RCP | JavaGui.Rcp |
~75 | Beta โ validated on real Eclipse & DBeaver | Introspection (workbench, perspectives, views, editors) plus actions (show/close view, open perspective, execute command) run against a live Eclipse workbench โ and are proven headless against DBeaver Community Edition, a real public RCP product, in the Docker harness under tests/docker/rcp. State-changing actions run on the SWT UI thread; generic widget keywords (Find Widget, Input Text, Check Button, type: locators) reach the workbench window. Needs a running Eclipse RCP app; not usable against non-Eclipse targets. |
Note: Keyword counts include deprecated aliases retained for backward compatibility. RCP targets applications built on the Eclipse Rich Client Platform โ validate against your specific app before production. Want proof it works on a real product? Run
docker build -t rcp-dbeaver-harness tests/docker/rcp && docker run --rm -v "$PWD":/work rcp-dbeaver-harnessand read the embedded screenshots inresults/dbeaver/log.html.
Table of Contents
- ๐ Keyword Documentation (GitHub Pages)
- ๐ Spy Tool โ javagui-spy
- Installation
- Quick Start
- Attach to a Running Application
- Libraries
- Locator Syntax
- Assertion Engine
- Keywords Reference
- Examples
- Architecture
- Development
- Troubleshooting
- License
Installation
Prerequisites
- Python 3.8 or higher
- Java 11 or higher (for running Java applications)
- Rust toolchain (for building from source)
- Maven (for building the Java agent)
Install from PyPI
# Install the library with pip
pip install robotframework-javagui
# Or install with uv (recommended)
uv pip install robotframework-javagui
Install from Source
# Clone the repository
git clone https://github.com/manykarim/robotframework-javaui.git
cd robotframework-javaui
# Install with uv (recommended)
uv pip install -e .
# Or install with pip
pip install -e .
Dependencies
The library automatically installs these dependencies:
| Package | Version | Purpose |
|---|---|---|
robotframework |
>=4.0 | Test automation framework |
robotframework-assertion-engine |
>=3.0.0 | Inline assertions with retry |
docutils |
>=0.20.1 | Documentation generation |
Build the Java Agent
The Java agent is required for instrumenting Java applications:
cd agent
mvn package
This creates agent/target/javagui-agent.jar.
Build the Demo Application (Optional)
A demo Swing application is included for testing:
cd demo
mvn package
Quick Start
1. Start Your Java Application with the Agent
# For Swing applications
java -javaagent:path/to/javagui-agent.jar=port=5678 -jar your-swing-app.jar
# For SWT applications
java -javaagent:path/to/javagui-agent.jar=port=5678 -jar your-swt-app.jar
# For Eclipse RCP applications
eclipse -vmargs -javaagent:path/to/javagui-agent.jar=port=5678
2. Create a Robot Framework Test
*** Settings ***
Library JavaGui.Swing # For Swing applications
# Library JavaGui.Swt # For SWT applications
# Library JavaGui.Rcp # For Eclipse RCP applications
*** Test Cases ***
Example Login Test
Connect To Application main_class=com.example.MyApp host=localhost port=5678
Input Text [name='username'] admin
Input Text [name='password'] secret
Click JButton[text='Login']
# Using inline assertion with retry
Get Text JLabel[name='status'] == Welcome
[Teardown] Disconnect
3. Run the Test
robot my_test.robot
Attach to a Running Application
Connect To Application needs the target started with -javaagent:javagui-agent.jar=port=โฆ. Sometimes you cannot do that โ the app is already running, someone else launched it, or it comes up through a launcher (Java Web Start) that will not let you add JVM args. Attach To Application handles those cases: it finds the target JVM, loads the agent at runtime through the JDK Attach API, and connects โ no -javaagent on the command line.
*** Settings ***
Library JavaGui.Swing
*** Test Cases ***
Automate An Already-Running Swing App
Attach To Application main_class=testapp.SwingTestApp
Click JButton[text='OK']
[Teardown] Disconnect
You point it at exactly one JVM. Selection is unambiguous or it errors โ if 0 or >1 processes match, the keyword raises with the candidate list instead of guessing.
| Argument | Selects by |
|---|---|
pid |
Process ID โ the most explicit. |
main_class |
Regex matched against the target's main class / entry jar / command line. |
title |
Window-title pattern (* wildcards; needs wmctrl). |
Not sure what is running? List Applications returns the discovered JVMs so you can pick one:
${apps}= List Applications
Log ${apps}
Attach To Application pid=${apps}[0][pid]
Each entry is a dict with pid, main_class, command_line, display_name, is_launcher, and markers. Launchers (javaws, an IDE bootstrap, etc.) are filtered out by default; pass include_launchers=True to see them too.
SWT and Eclipse RCP work the same way โ the toolkit just defaults differently:
*** Settings ***
Library JavaGui.Swt
*** Test Cases ***
Attach To A Running SWT App
Attach To Application main_class=MySwtApp toolkit=auto
Click Button[text='Save']
[Teardown] Disconnect
toolkit=auto detects Swing vs SWT from the classes loaded in the target, so it is a safe default when you are not sure. List Applications and Attach To Application are available on JavaGui.Swing, JavaGui.Swt, and JavaGui.Rcp (SWT/RCP default toolkit=swt; Swing defaults toolkit=swing).
When to use it vs Connect To Application
| Use | When |
|---|---|
Connect To Application |
You launch the app yourself and can add -javaagent:โฆ. Lowest overhead, works on any JVM. |
Attach To Application |
The app is already running, you cannot relaunch it, or it starts via Java Web Start. |
Requirements
- A JDK on the machine running the tests. Runtime attach uses the JDK Attach API (
jdk.attach). A plain JRE has no attach support โ install a JDK, or provide ajattachbinary (setJAVAGUI_JATTACH, or put it onPATH). - Same-user access to the target. The OS only lets you attach to JVMs owned by your user.
- JDK 21+ prints a one-line "dynamic agent loading" warning on the target โ harmless. JDK 24+ additionally requires the target to be launched with
-XX:+EnableDynamicAgentLoading; that flag is set at the target's launch, not by the test.
Java Web Start (JNLP)
Web Start apps are started by javaws (OpenWebStart, IcedTea-Web), which builds the JVM command line itself. You cannot add -javaagent at launch โ it is not on the JNLP secure vm-args whitelist, so the launcher strips it. Runtime attach is the way in. Launch Web Start Application starts the .jnlp, finds the application JVM (whether it runs in-process in the launcher or in a forked child), attaches the agent, and connects:
*** Settings ***
Library JavaGui.Swing
*** Test Cases ***
Automate A Web Start App
Launch Web Start Application https://example.com/app.jnlp toolkit=auto
Click JButton[text='Start']
[Teardown] Disconnect
Point launcher= at a specific javaws binary or an IcedTea-Web image directory (or set JAVAGUI_JAVAWS); omit it to use javaws on PATH. settle (default 8s) controls how long to wait for the app JVM to appear before attaching.
What works, and what does not:
| Target | Runtime attach |
|---|---|
Plain running app (java -jar app.jar, no -javaagent) |
โ Works |
| JNLP under modern OpenWebStart / JDK 24+ | โ Works |
JNLP under IcedTea-Web (legacy SecurityManager) |
โ Blocked |
The IcedTea-Web block is structural, not a permissions setting: ITW installs a JNLPSecurityManager that cannot classify the foreign code an attach-loaded agent brings in, so it denies the agent's initialization. This is independent of the app's permission level โ an all-permissions, signed JNLP is blocked exactly the same way. When this happens, Launch Web Start Application raises a clear AttachError naming the SecurityManager, rather than hanging. Use a launcher without the legacy SecurityManager (OpenWebStart, or a JDK 24+ javaws) for Web Start automation.
See docs/runtime-attach.md for the injection model, the full JDK/launcher matrix, troubleshooting, and the javagui-spy --attach-pid flags.
Spy Tool โ javagui-spy
Point it at a running Swing/SWT/RCP app and it hands you unique, verified Robot Framework locators โ no guessing, no sleep-and-hope. Every candidate is checked through the same matcher your tests run, so a suggested locator cannot fail to parse in a suite. A UI is coming; the agentic CLI is here today.
It ships in the wheel: pip install robotframework-javagui gives you the javagui-spy command. Attach to a live app on its agent port, or --launch app.jar to start one under the bundled agent.
The five-call workflow:
javagui-spy dump-tree --visible-only # 1. orient
javagui-spy find "text:Save" # 2. shortlist
javagui-spy suggest --node-id 7 # 3. ranked verified locators
javagui-spy validate "JButton[name='save']" # 4. exit 0 = unique, done
javagui-spy screenshot -o proof.png # 5. visual confirmation
suggest returns ranked candidates plus ready-to-paste rf_snippets (Click JButton[name='toolbarNewButton']). Deep, nameless widgets get nearest-stable-ancestor >> chains; --strip-names simulates off-the-shelf apps with no names. Connection flags (--host, --port, --toolkit, --timeout) sit on every verb.
Also: a web inspector (javagui-spy ui โ click a widget on a live screenshot, get ranked verified locators with a live match-count bar), click-to-pick (pick --at X,Y, in-JVM hit-test), highlight, and an MCP server (javagui-spy mcp) exposing the same verbs as tools.
Libraries
This package provides three libraries for different Java GUI frameworks:
| Library | Import | Use Case |
|---|---|---|
| Swing | Library JavaGui.Swing |
Java Swing applications (JButton, JTable, etc.) |
| Swt | Library JavaGui.Swt |
SWT applications (Eclipse widgets) |
| Rcp | Library JavaGui.Rcp |
Eclipse RCP applications (views, editors, perspectives) |
Full keyword reference (GitHub Pages): every keyword, with a runnable example โ
Swing ยท
SWT ยท
Eclipse RCP.
Hosted from docs/keywords/ โ regenerate with uv run invoke docs.
Library Import Options
*** Settings ***
# Basic import
Library JavaGui.Swing
# With options
Library JavaGui.Swing timeout=30 screenshot_dir=screenshots
# Multiple libraries (if needed)
Library JavaGui.Swing WITH NAME Swing
Library JavaGui.Rcp WITH NAME Rcp
Locator Syntax
The library supports multiple locator strategies for finding UI elements.
CSS-like Selectors
| Selector | Description | Example |
|---|---|---|
Type |
Match by component type | JButton |
[attr='value'] |
Exact attribute match | [name='loginBtn'] |
[attr*='value'] |
Attribute contains | [text*='Submit'] |
[attr^='value'] |
Attribute starts with | [name^='btn_'] |
[attr$='value'] |
Attribute ends with | [text$='...'] |
Type[attr='value'] |
Type with attribute | JButton[name='ok'] |
Parent > Child |
Direct child | JPanel > JButton |
Ancestor Descendant |
Descendant | JFrame JButton |
:enabled |
Enabled elements | JButton:enabled |
:visible |
Visible elements | JLabel:visible |
:first-child |
First child | JButton:first-child |
:nth-child(n) |
Nth child | JButton:nth-child(2) |
XPath-style Selectors
| Selector | Description | Example |
|---|---|---|
//Type |
Any descendant | //JButton |
//Type[@attr='value'] |
With attribute | //JButton[@name='ok'] |
//Type[n] |
By index (1-based) | //JButton[1] |
Combined Selectors
# Multiple attributes
JButton[name='submit'][text='OK']:enabled
# Nested with pseudo-selectors
JPanel[name='form'] JTextField:visible
# XPath with multiple predicates
//JTable[@name='data']//JButton[@text='Edit']
Assertion Engine
This library integrates robotframework-assertion-engine (v3.0.0+) to provide inline assertions with automatic retry, following the Browser Library pattern. This enables more concise and readable tests.
Basic Usage
Get keywords can optionally perform assertions with automatic retry:
*** Test Cases ***
Example With Assertions
# Without assertion - returns value
${text}= Get Text JLabel[name='status']
# With assertion - asserts with automatic retry (5s default)
Get Text JLabel[name='status'] == Ready
# With custom timeout
Get Text JLabel[name='status'] == Ready timeout=10
# With custom message
Get Text JLabel[name='status'] == Ready message=Status not ready
Assertion Operators
| Operator | Aliases | Description | Example |
|---|---|---|---|
== |
equal, equals, should be |
Exact equality | Get Text loc == Hello |
!= |
inequal, should not be |
Not equal | Get Text loc != Error |
< |
less than |
Less than (numeric) | Get Element Count JButton < 10 |
> |
greater than |
Greater than (numeric) | Get Table Row Count loc > 0 |
<= |
Less or equal | Get Element Count loc <= 5 |
|
>= |
Greater or equal | Get Table Row Count loc >= 1 |
|
*= |
contains |
Contains substring/item | Get Text loc contains success |
^= |
starts |
Starts with | Get Text loc starts Hello |
$= |
ends |
Ends with | Get Text loc ends world |
matches |
Regex match | Get Text loc matches \\d{3}-\\d{4} |
|
validate |
Custom expression | Get Text loc validate len(value) > 5 |
|
then |
Return value only (no assert) | ${v}= Get Text loc then |
Formatters
Apply text transformations before assertion:
*** Test Cases ***
Using Formatters
# Normalize spaces and strip whitespace
Get Text JLabel[name='title'] == Hello World formatters=['normalize_spaces', 'strip']
# Case-insensitive comparison
Get Text JLabel[name='status'] == ready formatters=['lowercase']
| Formatter | Description |
|---|---|
normalize_spaces |
Collapse multiple whitespace to single space |
strip |
Remove leading/trailing whitespace |
lowercase |
Convert to lowercase |
uppercase |
Convert to uppercase |
Element States
The Get Element States keyword returns element states that can be asserted:
*** Test Cases ***
Assert Element States
# Check element is visible and enabled
Get Element States JButton[name='submit'] contains enabled
Get Element States JButton[name='submit'] contains visible
# Check multiple states
${states}= Get Element States JButton[name='submit']
Should Contain ${states} enabled
Should Contain ${states} visible
Available States: visible, hidden, enabled, disabled, focused, unfocused, selected, unselected, checked, unchecked, editable, readonly, expanded, collapsed, attached, detached
Configuration
Configure assertion behavior globally or per-keyword:
*** Test Cases ***
Configure Assertions
# Set default timeout for all assertions
Set Assertion Timeout 10
# Set retry interval
Set Assertion Interval 0.2
# Override per keyword call
Get Text JLabel[name='status'] == Ready timeout=30
Validate Operator (Custom Expressions)
The validate operator allows custom Python expressions:
*** Test Cases ***
Custom Validation
# Validate with custom expression (value is the retrieved value)
Get Text JLabel[name='count'] validate int(value) > 10
Get Text JLabel[name='email'] validate '@' in value and '.' in value
Get Element Count JButton validate value % 2 == 0 # Even number
Security Note: The validate operator uses a secure expression evaluator that blocks dangerous operations like eval, exec, file access, and attribute manipulation.
Keywords Reference
Swing Keywords
Assertion-Enabled Get Keywords
These keywords support inline assertions with automatic retry:
| Keyword | Arguments | Description |
|---|---|---|
Get Text |
locator, assertion_operator=, expected=, message=, timeout=, formatters= |
Get element text with optional assertion |
Get Value |
locator, assertion_operator=, expected=, message=, timeout= |
Get input field value with optional assertion |
Get Element Count |
locator, assertion_operator=, expected=, message=, timeout= |
Count matching elements with optional numeric assertion |
Get Element States |
locator, assertion_operator=, expected=, message=, timeout= |
Get element states (visible, enabled, etc.) with optional assertion |
Get Property |
locator, property_name, assertion_operator=, expected=, message=, timeout= |
Get element property with optional assertion |
Get Properties |
locator, assertion_operator=, expected=, message= |
Get dict of common properties |
Table Keywords with Assertions
| Keyword | Arguments | Description |
|---|---|---|
Get Table Cell Value |
locator, row, column, assertion_operator=, expected=, message=, timeout= |
Get cell value with optional assertion |
Get Table Row Count |
locator, assertion_operator=, expected=, message=, timeout= |
Get row count with optional numeric assertion |
Get Table Column Count |
locator, assertion_operator=, expected=, message=, timeout= |
Get column count with optional numeric assertion |
Get Table Row Values |
locator, row, assertion_operator=, expected=, message= |
Get all values from a row |
Get Table Column Values |
locator, column, assertion_operator=, expected=, message= |
Get all values from a column |
Tree Keywords with Assertions
| Keyword | Arguments | Description |
|---|---|---|
Get Tree Node Count |
locator, path, assertion_operator=, expected=, message=, timeout= |
Get child node count with optional assertion |
Get Tree Node Children |
locator, path, assertion_operator=, expected=, message=, timeout= |
Get child nodes with optional assertion |
List Keywords with Assertions
| Keyword | Arguments | Description |
|---|---|---|
Get List Items |
locator, assertion_operator=, expected=, message= |
Get list items with optional assertion |
Get List Item Count |
locator, assertion_operator=, expected=, message=, timeout= |
Get item count with optional numeric assertion |
Configuration Keywords
| Keyword | Arguments | Description |
|---|---|---|
Set Assertion Timeout |
timeout |
Set default assertion retry timeout (seconds) |
Set Assertion Interval |
interval |
Set retry interval between attempts (seconds) |
SWT Keywords
Assertion-Enabled Get Keywords
| Keyword | Arguments | Description |
|---|---|---|
Get Widget Text |
locator, assertion_operator=, expected=, message=, timeout= |
Get SWT widget text with optional assertion |
Get Widget Count |
locator, assertion_operator=, expected=, message=, timeout= |
Count SWT widgets with optional assertion |
Get Widget Property |
locator, property_name, assertion_operator=, expected=, message=, timeout= |
Get SWT property with optional assertion |
Is Widget Enabled |
locator, assertion_operator=, expected=, message=, timeout= |
Check widget enabled state |
SWT Table Keywords with Assertions
| Keyword | Arguments | Description |
|---|---|---|
Get SWT Table Cell Value |
locator, row, column, assertion_operator=, expected=, message=, timeout= |
Get SWT table cell value |
Get SWT Table Row Count |
locator, assertion_operator=, expected=, message=, timeout= |
Get SWT table row count |
Get SWT Table Column Count |
locator, assertion_operator=, expected=, message=, timeout= |
Get SWT table column count |
SWT Tree Keywords with Assertions
| Keyword | Arguments | Description |
|---|---|---|
Get SWT Tree Node Count |
locator, path, assertion_operator=, expected=, message=, timeout= |
Get SWT tree node count |
Get SWT Tree Node Children |
locator, path, assertion_operator=, expected=, message=, timeout= |
Get SWT tree node children |
SWT Configuration Keywords
| Keyword | Arguments | Description |
|---|---|---|
Set SWT Assertion Timeout |
timeout |
Set SWT assertion retry timeout |
Set SWT Assertion Interval |
interval |
Set SWT retry interval |
RCP Keywords
Assertion-Enabled RCP Keywords
| Keyword | Arguments | Description |
|---|---|---|
Get Open View Count |
assertion_operator=, expected=, message=, timeout= |
Get count of open views with optional assertion |
Get Open Editor Count |
assertion_operator=, expected=, message=, timeout= |
Get count of open editors with optional assertion |
Get Active Perspective Id |
assertion_operator=, expected=, message=, timeout= |
Get active perspective ID with optional assertion |
Get Editor Dirty State |
title, assertion_operator=, expected=, message=, timeout= |
Check if editor has unsaved changes |
Common Keywords (All Libraries)
Connection Keywords
| Keyword | Arguments | Description |
|---|---|---|
Connect To Application |
main_class=, title=, host=, port=, timeout= |
Connect to an app launched with -javaagent |
Attach To Application |
pid=, main_class=, title=, host=, port=, toolkit=, timeout= |
Inject the agent into an already-running JVM and connect (no -javaagent needed) โ see Attach to a Running Application |
List Applications |
include_launchers= |
List discovered Java processes you can attach to |
Launch Web Start Application |
jnlp, launcher=, host=, port=, toolkit=, settle=, timeout= |
Launch a JNLP app, attach at runtime, and connect |
Disconnect |
Disconnect from the application | |
Is Connected |
Returns connection status |
Element Finding
| Keyword | Arguments | Description |
|---|---|---|
Find Element |
locator |
Find single element |
Find Elements |
locator |
Find all matching elements |
Element Should Exist |
locator |
Assert element exists |
Element Should Not Exist |
locator |
Assert element doesn't exist |
Mouse Actions
| Keyword | Arguments | Description |
|---|---|---|
Click |
locator |
Single click |
Double Click |
locator |
Double click |
Right Click |
locator |
Context menu click |
Click Button |
locator |
Click a button |
Text Input
| Keyword | Arguments | Description |
|---|---|---|
Input Text |
locator, text, clear=True |
Enter text (optionally clear first) |
Type Text |
locator, text |
Type text character by character |
Clear Text |
locator |
Clear text field |
Get Element Text |
locator |
Get element's text content |
Table Operations
| Keyword | Arguments | Description |
|---|---|---|
Get Table Row Count |
locator |
Get number of rows |
Get Table Column Count |
locator |
Get number of columns |
Get Table Cell Value |
locator, row, column |
Get cell value |
Get Table Data |
locator |
Get all table data as list |
Select Table Cell |
locator, row, column |
Select a cell |
Select Table Row |
locator, row |
Select a row |
Tree Operations
| Keyword | Arguments | Description |
|---|---|---|
Expand Tree Node |
locator, path |
Expand a tree node |
Collapse Tree Node |
locator, path |
Collapse a tree node |
Select Tree Node |
locator, path |
Select a tree node |
Get Tree Nodes |
locator |
Get all tree nodes |
List Operations
| Keyword | Arguments | Description |
|---|---|---|
Get List Items |
locator |
Get all list items |
Select From List |
locator, value |
Select item by value |
Select List Item By Index |
locator, index |
Select item by index |
Form Controls
| Keyword | Arguments | Description |
|---|---|---|
Select From Combobox |
locator, value |
Select dropdown value |
Check Checkbox |
locator |
Check a checkbox |
Uncheck Checkbox |
locator |
Uncheck a checkbox |
Select Radio Button |
locator |
Select radio button |
Select Tab |
locator, tab_name |
Select tab in tabbed pane |
Verification
| Keyword | Arguments | Description |
|---|---|---|
Element Should Be Visible |
locator |
Assert element is visible |
Element Should Be Enabled |
locator |
Assert element is enabled |
Element Should Be Selected |
locator |
Assert element is selected |
Element Text Should Be |
locator, expected |
Assert exact text match |
Element Text Should Contain |
locator, expected |
Assert text contains |
Wait Operations
| Keyword | Arguments | Description |
|---|---|---|
Wait For Element |
locator, timeout= |
Wait for element to exist |
Wait Until Element Visible |
locator, timeout= |
Wait for visibility |
Wait Until Element Enabled |
locator, timeout= |
Wait for enabled state |
Wait Until Element Contains |
locator, text, timeout= |
Wait for text content |
UI Tree Inspection
The library provides powerful component tree inspection with advanced filtering capabilities:
| Keyword | Arguments | Description |
|---|---|---|
Get Component Tree |
locator=, format=text, max_depth=, types=, exclude_types=, visible_only=False, enabled_only=False, focusable_only=False |
Get component hierarchy with depth control, type filtering, and state filtering. Supports multiple output formats: text, json, xml, yaml, csv, markdown |
Get Component Subtree |
locator, format=text, max_depth=, types=, exclude_types=, visible_only=, enabled_only=, focusable_only= |
Get subtree starting from specific component (faster for large UIs) |
Log Component Tree |
locator=, format=text, level=INFO |
Log component tree to Robot Framework log |
Refresh Component Tree |
Refresh cached component tree | |
Get Ui Tree |
format=text |
(Legacy) Get component hierarchy - use Get Component Tree instead |
Log Ui Tree |
(Legacy) Log UI tree - use Log Component Tree instead | |
Refresh Ui Tree |
(Legacy) Refresh tree - use Refresh Component Tree instead |
Component Tree Features:
- 6 Output Formats:
text(default),json,xml,yaml,csv,markdown - Type Filtering: Include/exclude by component type with wildcard support (
J*Button,JText*) - State Filtering: Filter by visible, enabled, or focusable state
- Depth Control: Limit tree depth for performance (recommended for large UIs)
- Performance: 50x faster subtree retrieval vs. full tree on large applications
Quick Examples:
# Get tree with multiple formats
${text}= Get Component Tree format=text
${json}= Get Component Tree format=json max_depth=5
${xml}= Get Component Tree format=xml
# Advanced filtering
${buttons}= Get Component Tree types=J*Button visible_only=${True}
${inputs}= Get Component Tree types=JButton,JTextField enabled_only=${True}
${tree}= Get Component Tree exclude_types=JLabel,JPanel max_depth=10
# Subtree for performance
${form}= Get Component Subtree JPanel[name='loginForm'] format=json
See Component Tree Documentation for complete guide.
Screenshots
| Keyword | Arguments | Description |
|---|---|---|
Capture Screenshot |
filename= |
Capture window screenshot |
Set Screenshot Directory |
directory |
Set output directory |
Properties
| Keyword | Arguments | Description |
|---|---|---|
Get Element Property |
locator, property |
Get specific property |
Get Element Properties |
locator |
Get all properties |
Examples
Swing Examples
Login Test with Assertions
*** Settings ***
Documentation Login functionality test suite with assertion engine
Library JavaGui.Swing
Library Process
Suite Setup Start Application
Suite Teardown Stop Application
*** Variables ***
${APP_JAR} path/to/myapp.jar
${AGENT_JAR} path/to/javagui-agent.jar
${PORT} 5678
*** Keywords ***
Start Application
${cmd}= Set Variable java -javaagent:${AGENT_JAR}=port=${PORT} -jar ${APP_JAR}
Start Process ${cmd} shell=True alias=app
Sleep 3s
Connect To Application main_class=com.example.MyApp port=${PORT}
Stop Application
Disconnect
Terminate Process app kill=True
*** Test Cases ***
Valid Login Should Succeed
[Documentation] Test login with inline assertions
Input Text JTextField[name='username'] admin
Input Text JPasswordField[name='password'] password123
Click JButton[text='Login']
# Inline assertion with automatic retry
Get Text JLabel[name='status'] == Welcome, admin! timeout=5
Invalid Login Should Show Error
[Documentation] Test error handling with assertions
Input Text [name='username'] invalid
Input Text [name='password'] wrong
Click JButton[text='Login']
# Assert text contains with retry
Get Text JLabel[name='status'] contains Invalid credentials
Verify Button States
[Documentation] Test element states with assertions
# Check submit button is enabled
Get Element States JButton[name='submit'] contains enabled
# Check login form is visible
Get Element States JPanel[name='loginForm'] contains visible
Table Operations with Assertions
*** Test Cases ***
Verify Table Data With Assertions
[Documentation] Table verification using assertion engine
# Assert minimum row count
Get Table Row Count JTable[name='dataTable'] >= 5
# Assert cell values with retry
Get Table Cell Value JTable[name='dataTable'] 0 1 == John Doe
Get Table Cell Value JTable[name='dataTable'] 0 2 contains @example.com
# Assert column count
Get Table Column Count JTable[name='dataTable'] == 5
Process Table Rows With Validation
[Documentation] Iterate and validate table rows
# First verify we have data
Get Table Row Count JTable[name='users'] > 0
# Get row values and validate
${row}= Get Table Row Values JTable[name='users'] 0
Should Not Be Empty ${row}
Tree Navigation with Assertions
*** Test Cases ***
Navigate And Validate Tree
[Documentation] Tree operations with assertion engine
# Expand and verify node count
Expand Tree Node JTree[name='fileTree'] Root
Get Tree Node Count JTree[name='fileTree'] Root > 0
# Verify children exist
Get Tree Node Children JTree[name='fileTree'] Root contains Documents
SWT Examples
SWT Application Testing
*** Settings ***
Documentation SWT application test suite
Library JavaGui.Swt
Suite Setup Connect To SWT Application
Suite Teardown Disconnect
*** Keywords ***
Connect To SWT Application
Connect To Application main_class=com.example.SwtApp port=5678
*** Test Cases ***
Verify SWT Widget Text
[Documentation] Test SWT text retrieval with assertions
# Assert label text
Get Widget Text Label[name='status'] == Ready
# Assert with formatters
Get Widget Text Label[name='title'] == application name formatters=['lowercase', 'strip']
# Assert text contains
Get Widget Text Text[name='description'] contains Welcome
Verify SWT Widget States
[Documentation] Test SWT widget states
# Check widget is enabled
Is Widget Enabled Button[name='submit'] == ${True}
# Get widget count
Get Widget Count Button > 5
SWT Table Verification
[Documentation] SWT table testing with assertions
# Assert table has data
Get SWT Table Row Count Table[name='data'] >= 1
# Assert cell value
Get SWT Table Cell Value Table[name='data'] 0 0 == First Row
SWT Tree Navigation
[Documentation] SWT tree testing
# Verify tree has children
Get SWT Tree Node Count Tree[name='nav'] Root > 0
# Verify specific children exist
Get SWT Tree Node Children Tree[name='nav'] Root contains Settings
SWT Property Assertions
[Documentation] Assert widget properties
# Check specific property
Get Widget Property Button[name='submit'] enabled == true
Get Widget Property Text[name='input'] editable == true
RCP Examples
Eclipse RCP Application Testing
*** Settings ***
Documentation Eclipse RCP application test suite
Library JavaGui.Rcp
Suite Setup Connect To RCP Application
Suite Teardown Disconnect
*** Keywords ***
Connect To RCP Application
# Start Eclipse with agent
# eclipse -vmargs -javaagent:path/to/agent.jar=port=5678
Connect To Application main_class=org.eclipse.ui.PlatformUI port=5678
*** Test Cases ***
Verify Perspective
[Documentation] Test RCP perspective with assertions
# Assert active perspective
Get Active Perspective Id == org.eclipse.ui.resourcePerspective
# Or use contains for partial match
Get Active Perspective Id contains resource
Verify Open Views
[Documentation] Test RCP views with assertions
# Assert at least one view is open
Get Open View Count >= 1
# Assert specific number of views
Get Open View Count == 3 message=Expected 3 views to be open
Verify Open Editors
[Documentation] Test RCP editors with assertions
# Assert editors are open
Get Open Editor Count > 0
# After opening specific file
Get Open Editor Count == 2
Test Editor Dirty State
[Documentation] Test unsaved changes detection
# Verify editor has no unsaved changes
Get Editor Dirty State MyFile.java == ${False}
# After making changes
Input Text StyledText[name='editor'] // new code
Get Editor Dirty State MyFile.java == ${True}
Complete RCP Workflow
[Documentation] Full RCP workflow with assertions
# Verify starting state
Get Active Perspective Id contains Java
# Open a view and verify count increases
${initial_views}= Get Open View Count
Click JMenuItem[text='Show View']
Click JMenuItem[text='Console']
Get Open View Count > ${initial_views}
# Open editor and verify
Double Click TreeItem[text='MyProject/src/Main.java']
Get Open Editor Count >= 1
Get Editor Dirty State Main.java == ${False}
Advanced Examples
Using Formatters
*** Test Cases ***
Text Formatting Examples
[Documentation] Using formatters for flexible assertions
# Normalize whitespace before comparison
Get Text JLabel[name='formatted'] == Hello World formatters=['normalize_spaces']
# Case-insensitive comparison
Get Text JLabel[name='status'] == success formatters=['lowercase']
# Chain multiple formatters
Get Text JLabel[name='message'] == hello formatters=['strip', 'lowercase']
Custom Validation
*** Test Cases ***
Custom Validation Examples
[Documentation] Using validate operator for complex assertions
# Validate numeric range
Get Text JLabel[name='count'] validate 10 <= int(value) <= 100
# Validate email format
Get Text JTextField[name='email'] validate '@' in value and '.' in value
# Validate string length
Get Text JTextField[name='code'] validate len(value) == 6
# Validate with regex
Get Text JLabel[name='phone'] matches ^\\d{3}-\\d{3}-\\d{4}$
Handling Dynamic Content
*** Test Cases ***
Dynamic Content With Assertions
[Documentation] Handle async updates with assertion retry
Click JButton[name='loadData']
# Assertions auto-retry until timeout
Get Element States JLabel[name='loading'] contains hidden timeout=10
Get Table Row Count JTable[name='results'] > 0 timeout=10
Get Text JLabel[name='status'] == Data loaded timeout=15
Architecture
robotframework-javagui/
โโโ python/ # Python package
โ โโโ JavaGui/ # Robot Framework library
โ โโโ __init__.py # Library exports (Swing, Swt, Rcp)
โ โโโ assertions/ # Assertion engine integration
โ โ โโโ __init__.py # Retry wrappers, ElementState
โ โ โโโ formatters.py # Text formatters
โ โ โโโ security.py # Secure expression evaluator
โ โโโ keywords/ # Keyword implementations
โ โโโ getters.py # Swing Get* keywords
โ โโโ tables.py # Swing Table/Tree/List keywords
โ โโโ swt_getters.py # SWT Get* keywords
โ โโโ swt_tables.py # SWT Table keywords
โ โโโ swt_trees.py # SWT Tree keywords
โ โโโ rcp_keywords.py # RCP-specific keywords
โโโ src/ # Rust source code
โ โโโ lib.rs # PyO3 bindings
โ โโโ locator/ # Locator parsing (pest grammar)
โ โโโ connection/ # RPC client
โ โโโ element/ # Element operations
โโโ agent/ # Java agent
โ โโโ src/ # Agent source
โโโ demo/ # Demo Swing application
โโโ tests/ # Test suites
โโโ robot/ # Robot Framework tests
How It Works
- Java Agent: Attaches to the JVM and provides RPC endpoints for UI inspection and control
- Rust Core: High-performance element matching, locator parsing, and RPC communication
- Python Bindings: PyO3-based interface exposing Robot Framework keywords
- Assertion Engine: Integration with
robotframework-assertion-enginefor inline assertions with retry - Robot Framework: Test execution and reporting
Assertion Flow
Get Text keyword called with assertion operator
โ
Retry wrapper starts (default 5s timeout, 0.1s interval)
โ
Get value from Java agent via Rust core
โ
Apply formatters (if specified)
โ
AssertionEngine.verify_assertion() checks condition
โ
Pass: Return value | Fail: Retry until timeout
Development
Building from Source
# Install development dependencies
uv pip install -e ".[dev]"
# Build Rust extension
maturin develop
# Build Java agent
cd agent && mvn package
# Build demo app
cd demo && mvn package
Running Tests
# Run Robot Framework tests
uv run robot tests/robot/
# Run Python unit tests
uv run pytest tests/python/
# Run specific test suite
uv run robot tests/robot/02_locators.robot
Project Structure
| Directory | Description |
|---|---|
python/ |
Python Robot Framework library |
src/ |
Rust core library |
agent/ |
Java instrumentation agent |
demo/ |
Demo Swing application |
tests/robot/ |
Robot Framework test suites |
tests/python/ |
Python unit tests |
docs/ |
Documentation |
schemas/ |
JSON/YAML schemas |
Configuration
Agent Configuration
The Java agent accepts these JVM arguments:
java -javaagent:swing-agent.jar=port=5678,debug=true -jar app.jar
| Option | Default | Description |
|---|---|---|
port |
5678 | RPC server port |
debug |
false | Enable debug logging |
Library Configuration
*** Settings ***
# Swing library with options
Library JavaGui.Swing timeout=30 screenshot_dir=screenshots
# SWT library
Library JavaGui.Swt timeout=30
# RCP library
Library JavaGui.Rcp timeout=30
| Option | Default | Description |
|---|---|---|
timeout |
10 | Default wait timeout (seconds) |
screenshot_dir |
. | Screenshot output directory |
Assertion Configuration
Configure assertion behavior in your test:
*** Test Cases ***
Configure Assertion Defaults
# Set default assertion retry timeout (seconds)
Set Assertion Timeout 10
# Set retry interval between attempts (seconds)
Set Assertion Interval 0.2
# For SWT library
Set SWT Assertion Timeout 10
Set SWT Assertion Interval 0.2
| Setting | Default | Description |
|---|---|---|
| Assertion Timeout | 5.0 | How long to retry assertion before failing |
| Assertion Interval | 0.1 | Time between retry attempts |
Timeout Priority (highest to lowest):
- Keyword argument:
Get Text loc == value timeout=30 - Library configuration:
Set Assertion Timeout 10 - Global default: 5.0 seconds
Troubleshooting
Connection Issues
SwingConnectionError: Connection refused
- Ensure the application is running with the agent loaded
- Verify the port matches between agent and library
- Check firewall settings
Element Not Found
ElementNotFoundError: Element not found: JButton[name='xyz']
- Use
Log Ui Treeto inspect available elements - Verify element names and attributes
- Check if element is visible/enabled
EDT Threading Errors
SwingConnectionError: EDT callable failed
- Some operations require visible components
- Use wait keywords before interacting
- Ensure proper tab/window focus
Assertion Timeout Errors
AssertionError: Get Text: Timeout 5.0s exceeded
- Increase timeout:
Get Text loc == value timeout=30 - Check if element exists and has the expected value
- Use
Log Ui Treeto verify element state - Consider if the value changes dynamically (use longer timeout)
Assertion Value Mismatch
AssertionError: Get Text: 'Actual Value' should be 'Expected Value'
- Check for whitespace issues - use
formatters=['strip', 'normalize_spaces'] - Check for case sensitivity - use
formatters=['lowercase'] - Verify the expected value matches exactly (or use
containsoperator)
Validate Expression Errors
SecurityError: Expression contains blocked operation
- The
validateoperator blocks dangerous operations for security - Only use allowed builtins:
len,int,str,bool,float, etc. - Avoid:
eval,exec,open,__import__, attribute access like__class__
SWT/RCP Specific Issues
SWTException: Widget is disposed
- The widget was destroyed before the operation completed
- Add wait for the widget to be ready
- Check if a dialog or view was closed unexpectedly
WorkbenchException: View not found
- Verify the view ID is correct
- Ensure the perspective allows the view
- Check if the view is available in the current product
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
Apache License 2.0. See LICENSE for details.
Acknowledgments
- Robot Framework - Test automation framework
- robotframework-assertion-engine - Inline assertion library
- Browser Library - Inspiration for inline assertion pattern
- PyO3 - Rust bindings for Python
- pest - Parser library for Rust
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file robotframework_javagui-0.8.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: robotframework_javagui-0.8.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b2e3360d03f201ddd50125d9d75f3d68899cbae85cb9cfc71710afcf84d3d8c
|
|
| MD5 |
bf1f267086787b35440f324a8ae80ce0
|
|
| BLAKE2b-256 |
0e0c4f5bbf2508af1350e26e6beb5680eb4008b8c24abac9ff4f54c40186a19d
|
File details
Details for the file robotframework_javagui-0.8.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: robotframework_javagui-0.8.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f8a24240535123b0ab5e91636716a12e72f49df88fc02e23fe772aad718f7bc7
|
|
| MD5 |
604c167373f505b8835d52deb409ffa9
|
|
| BLAKE2b-256 |
a6f2298fe8b5577ac032c3d71511471e354afbdf0efb4ded844220d2d16e52a8
|
File details
Details for the file robotframework_javagui-0.8.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: robotframework_javagui-0.8.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.8 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c45d8e56df5c1b3d4ff999d05ab9a04f542f4eace251028cac44ab6b4e10dcdd
|
|
| MD5 |
f893ab81117fa47583e0b6d1d9874f95
|
|
| BLAKE2b-256 |
e9d40b46a1c0a9acde0050e7b759fc7c69304aae834794bd47f5bc3630e4877f
|