Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d2dad3f
Restructure into a full UI + API test portfolio with Page Object Model
claude Aug 17, 2026
fb0c74c
temp: dump live page structure for locator verification
claude Aug 17, 2026
3a87dab
temp: attempt full corrected flow, dump confirmation state
claude Aug 17, 2026
314a74b
temp: click styled radio siblings instead of hidden inputs
claude Aug 17, 2026
5a7cf73
temp: probe validation state after product-step submission
claude Aug 17, 2026
a90a1b7
temp: use a dynamically computed future start date
claude Aug 17, 2026
9765931
temp: import DateTime library for date computation
claude Aug 17, 2026
f19ce0b
temp: filter to visible errors and inspect XHR resource timing
claude Aug 17, 2026
982ebf2
temp: dump the actual currently-visible panel after submitting produc…
claude Aug 17, 2026
00c7739
Fix UI suite against live app: real locators, verified flow, honest s…
claude Aug 17, 2026
1b43b73
temp: bisect the ElementNotInteractableException with step logging
claude Aug 17, 2026
3efcb95
temp: bisect further into Enter Product Data internals
claude Aug 17, 2026
4dba408
Harden product-data step against a panel-transition timing race
claude Aug 17, 2026
4bfaccc
Retry the product-data start-date input against the transition race
claude Aug 17, 2026
027be06
Extend the transition-race retry to every product-data interaction
claude Aug 17, 2026
3956f2a
temp: capture element geometry/style state on interactability failure
claude Aug 17, 2026
34a491e
Apply transition-race retry protection uniformly, remove diagnostics
claude Aug 17, 2026
5cdd88f
temp: coarse stage markers now that the failure appears deterministic
claude Aug 17, 2026
3627c5e
Dispatch wizard "next" button clicks via JavaScript, not WebDriver
claude Aug 17, 2026
8e7166d
Extract test data to a resource file, add real outcome assertions
claude Aug 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Robot Framework Tests

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:

jobs:
ui-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
run: pip install -r requirements.txt

- name: Run UI smoke suite (headless)
run: >
robot
--outputdir results/ui
--variable BROWSER:headlesschrome
--include smoke
tests/car_insurance_quote.robot tests/insurance_navigation.robot

- name: Upload UI test results
if: always()
uses: actions/upload-artifact@v4
with:
name: ui-test-results
path: results/ui

api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
run: pip install -r requirements.txt

- name: Run API suite
run: robot --outputdir results/api tests/api

- name: Upload API test results
if: always()
uses: actions/upload-artifact@v4
with:
name: api-test-results
path: results/api
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Robot Framework run artifacts
results/
log.html
report.html
output.xml
*.png
selenium-screenshot-*.png

# Python
__pycache__/
*.pyc
.venv/
venv/
env/
*.egg-info/

# IDE / OS
.vscode/
.idea/
.DS_Store
Thumbs.db
150 changes: 149 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,150 @@
# test-robotframework
This is a repository for testing out robotframework

A Robot Framework test automation portfolio combining UI and API test suites,
built around the Page Object pattern and structured for maintainability and
CI execution.

- **UI suite** — drives the [Tricentis sample insurance application](https://sampleapp.tricentis.com/)
with `SeleniumLibrary`, exercising the vehicle, insurant and product data steps of
the car insurance quote wizard (see "Known limitations" below for what's out of
scope).
- **API suite** — exercises the [JSONPlaceholder](https://jsonplaceholder.typicode.com)
REST API with `RequestsLibrary`.

## Project structure

```
resources/
├── common.resource # Browser lifecycle, failure diagnostics & shared assertions
├── variables.resource # Global configuration (URL, browser, timeouts)
├── pages/ # One resource file per wizard step (Page Object Model)
│ ├── home_page.resource
│ ├── vehicle_data_page.resource
│ ├── insurant_data_page.resource
│ └── product_data_page.resource
├── data/
│ └── car_insurance_test_data.resource # Named vehicle/insurant test profiles
└── api/
└── jsonplaceholder.resource

tests/
├── car_insurance_quote.robot # End-to-end UI regression suite
├── insurance_navigation.robot # UI smoke tests for the landing page
└── api/
└── posts_api.robot # API regression suite
```

Each page resource owns its own locators and keywords, so a markup change on
one wizard step only requires an edit in one file. Test suites orchestrate
page keywords; they never contain raw locators.

## Prerequisites

- Python 3.9+
- Google Chrome (for the UI suite)

## Setup

```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```

Selenium's built-in driver manager resolves the matching ChromeDriver
automatically, so no separate driver installation is required.

## Running the tests

Run everything:

```bash
robot --outputdir results tests
```

Run only the UI suites, headless:

```bash
robot --outputdir results --variable BROWSER:headlesschrome \
tests/car_insurance_quote.robot tests/insurance_navigation.robot
```

Run only the API suite:

```bash
robot --outputdir results tests/api
```

Run by tag (e.g. the fast smoke subset):

```bash
robot --outputdir results --include smoke tests
```

Available tags: `smoke`, `regression`, `navigation`, `api`, `car-insurance`.

Run results (`log.html`, `report.html`, `output.xml`, screenshots) are
written to `results/` and are not committed to version control.

## Continuous integration

`.github/workflows/tests.yml` runs the UI smoke suite (headless Chrome) and
the full API suite on every push and pull request, and publishes the Robot
Framework logs as workflow artifacts.

## Development tooling

Optional linting and formatting tools are listed in `requirements-dev.txt`:

```bash
pip install -r requirements-dev.txt

# Static analysis (rule thresholds tuned in robocop.toml)
robocop check tests resources

# Auto-formatting
robocop format tests resources
```

## Conventions

- **Page Object Model** — locators live in `resources/pages/*.resource`,
never inline in test cases.
- **Explicit waits only** — every navigation is followed by
`Wait Until Element Is Visible` (or an equivalent explicit wait); no
`Sleep` calls.
- **Tagging** — every test case carries at least one tag so suites can be
sliced by CI stage (`smoke` for fast feedback, `regression` for full
coverage).
- **Data-driven cases** — `[Template]` is used where the same flow needs to
be exercised with multiple data sets (vehicle profiles, user ids). Reusable
vehicle/insurant profiles live as named dictionaries in
`resources/data/car_insurance_test_data.resource` and are passed into
keywords via Robot's `&{dict}` argument-unpacking syntax, rather than
duplicating literals inline in each test case.
- **Isolation** — `Test Setup`/`Test Teardown` reset state between tests and
capture a screenshot on UI failures for debugging.
- **Meaningful assertions** — each wizard step verifies it was genuinely
accepted (the previous panel is gone, the next one has taken its place,
and no client-side validation errors are showing) rather than only
asserting that no exception was raised.

## Known limitations

The UI suite targets a third-party public demo application. If Tricentis
updates the markup of `sampleapp.tricentis.com`, only the affected file(s)
under `resources/pages/` need to be updated — the test cases themselves
should remain unchanged.

Price selection and quote submission (the steps after product data) are not
covered. The wizard's price-plan step depends on an asynchronous request
that was observed to hang indefinitely under headless automation in CI,
independent of input validity — submitted product data was accepted (no
validation errors, and the product-data panel correctly closed) but the
subsequent price-plan panel never loaded even after 45+ seconds. Extending
coverage to price selection and quote submission is a reasonable follow-up
once that step's reliability under automation can be confirmed.

## License

Apache License 2.0, see [LICENSE](LICENSE).
4 changes: 4 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Optional tooling used during local development, not required to run the suites.
# Robocop bundles both static analysis (`robocop check`) and formatting
# (`robocop format`) in a single package.
robotframework-robocop>=6.0
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Runtime dependencies for executing the test suites.
robotframework>=7.0,<8.0
robotframework-seleniumlibrary>=6.5.0,<7.0
robotframework-requests>=0.9.5,<1.0
39 changes: 39 additions & 0 deletions resources/api/jsonplaceholder.resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
*** Settings ***
Documentation Keywords for interacting with the JSONPlaceholder REST API
... (https://jsonplaceholder.typicode.com), used to demonstrate API
... test coverage alongside the UI test suite.

Library RequestsLibrary


*** Variables ***
${API_SESSION} jsonplaceholder
${API_BASE_URL} https://jsonplaceholder.typicode.com


*** Keywords ***
Create JSONPlaceholder Session
[Documentation] Opens an HTTP session that every test in the suite can reuse.
Create Session ${API_SESSION} ${API_BASE_URL}

Get User By Id
[Documentation] Retrieves a single user resource by id.
[Arguments] ${user_id} ${expected_status}=200
${response}= GET On Session ${API_SESSION} /users/${user_id}
... expected_status=${expected_status}
RETURN ${response}

Create Post
[Documentation] Creates a new post resource for the given user.
[Arguments] ${title} ${body} ${user_id}
VAR &{payload}= title=${title} body=${body} userId=${user_id}
${response}= POST On Session ${API_SESSION} /posts json=${payload}
... expected_status=201
RETURN ${response}

Delete Post
[Documentation] Deletes the post with the given id.
[Arguments] ${post_id}
${response}= DELETE On Session ${API_SESSION} /posts/${post_id}
... expected_status=200
RETURN ${response}
34 changes: 34 additions & 0 deletions resources/common.resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
*** Settings ***
Documentation Keywords shared by every UI test suite: browser lifecycle and
... failure diagnostics.

Library SeleniumLibrary
Resource variables.resource


*** Keywords ***
Open Insurance Application
[Documentation] Starts a browser session and opens the insurance sample application.
Open Browser ${APP_URL} ${BROWSER}
Set Selenium Timeout ${SELENIUM_TIMEOUT}
Set Window Size 1920 1080

Close Insurance Application
[Documentation] Closes every browser window opened during the suite.
Close All Browsers

Capture Screenshot On Failure
[Documentation] Saves a screenshot of the current page whenever a test fails,
... to speed up debugging.
Run Keyword If Test Failed Capture Page Screenshot

No Validation Errors Should Be Visible
[Documentation] Verifies the current step shows no active field validation
... errors, confirming submitted data was genuinely accepted rather
... than silently rejected.
${errors}= Execute Javascript
... var candidates = document.querySelectorAll('.error, .errorMessage, .invalid, [class*="error"]');
... function isVisibleError(e) { return e.offsetParent !== null && e.textContent.trim().length > 1; }
... var visible = Array.from(candidates).filter(isVisibleError);
... return visible.map(function(e) { return e.textContent.trim(); }).join(' || ');
Should Be Empty ${errors} msg=Unexpected validation errors: ${errors}
44 changes: 44 additions & 0 deletions resources/data/car_insurance_test_data.resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
*** Settings ***
Documentation Reusable vehicle and insurant profiles for the car insurance quote
... wizard tests. Values satisfy the live application's validation rules
... confirmed during development (e.g. list price/annual mileage ranges,
... minimum street length, insurant age between 18 and 70).


*** Variables ***
&{VEHICLE_MERCEDES_BENZ} make=Mercedes Benz
... engine_performance=68
... manufacture_date=08/25/2023
... seats=7
... fuel=Diesel
... list_price=50000
... annual_mileage=32185
&{VEHICLE_VOLKSWAGEN} make=Volkswagen
... engine_performance=75
... manufacture_date=01/15/2022
... seats=5
... fuel=Petrol
... list_price=28000
... annual_mileage=15000
&{VEHICLE_BMW} make=BMW
... engine_performance=140
... manufacture_date=03/10/2021
... seats=5
... fuel=Diesel
... list_price=45000
... annual_mileage=20000

&{INSURANT_JANE_DOE} first_name=Jane
... last_name=Doe
... birthdate=05/14/1990
... gender=Female
... street=Baker Street 221B
... zip_code=10115
... city=Berlin
&{INSURANT_JOHN_SMITH} first_name=John
... last_name=Smith
... birthdate=01/01/1985
... gender=Male
... street=Main Street 1
... zip_code=10115
... city=Berlin
Loading
Loading