qmpass-test-agent 1.0.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qmpass_test_agent-1.0.10/LICENSE +15 -0
- qmpass_test_agent-1.0.10/PKG-INFO +106 -0
- qmpass_test_agent-1.0.10/README.md +433 -0
- qmpass_test_agent-1.0.10/README.pypi.md +71 -0
- qmpass_test_agent-1.0.10/pyproject.toml +65 -0
- qmpass_test_agent-1.0.10/setup.cfg +4 -0
- qmpass_test_agent-1.0.10/src/qmpass/__init__.py +8 -0
- qmpass_test_agent-1.0.10/src/qmpass/__main__.py +6 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/__init__.py +6 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/artifact_upload.py +355 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/client/__init__.py +26 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/client/connect_errors.py +159 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/client/messages.py +70 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/client/websocket.py +946 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/doctor.py +216 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/__init__.py +82 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/core/__init__.py +15 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/core/controller.py +558 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/core/models.py +27 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/core/orchestrator.py +720 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/core/paths.py +9 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/core/robot_gen.py +50 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/mapping/__init__.py +13 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/mapping/mapper.py +254 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/protocol/__init__.py +298 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/adapters/angular.js +29 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/adapters/react.js +32 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/adapters/salesforce.js +27 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/adapters/standard.js +24 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/assertPick.js +507 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/content.js +123 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/detector.js +86 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/events.js +173 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/highlighter.js +159 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/rawEventCollector.js +247 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/recorder-engine/actionDetector.js +74 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/recorder-engine/config.js +33 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/recorder-engine/eventAggregator.js +177 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/recorder-engine/eventNormalizer.js +122 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/recorder-engine/keywordBuilder.js +116 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/selector.js +136 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/selectorBase.js +200 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/surfaceObserver.js +532 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/ui/qmpass-recorder-widget.js +8691 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/widget_adapter.js +329 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/content-script/widget_host.js +86 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/extension/background.js +768 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/icon.png +0 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/icon128.png +0 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/icon16.png +0 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/icon48.png +0 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/recorder/sidebar/manifest.json +83 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/__init__.py +9 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/data_files.py +126 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/models.py +193 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/paths.py +10 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/redact.py +111 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/result_mapper.py +142 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/self_healing_listener.py +57 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/robot/suite_writer.py +80 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/run_summary.py +107 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/__init__.py +12 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/cancel.py +157 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/execute.py +315 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/result_build.py +249 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/robot_process.py +372 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/task_runner.py +64 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runner/work_dir.py +187 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/runtime.py +104 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/system_info.py +86 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/tls.py +42 -0
- qmpass_test_agent-1.0.10/src/qmpass/agent/update_check.py +81 -0
- qmpass_test_agent-1.0.10/src/qmpass/cli.py +290 -0
- qmpass_test_agent-1.0.10/src/qmpass/config/__init__.py +5 -0
- qmpass_test_agent-1.0.10/src/qmpass/config/settings.py +211 -0
- qmpass_test_agent-1.0.10/src/qmpass/desktop.py +101 -0
- qmpass_test_agent-1.0.10/src/qmpass/exit_codes.py +16 -0
- qmpass_test_agent-1.0.10/src/qmpass/logging_setup.py +199 -0
- qmpass_test_agent-1.0.10/src/qmpass_test_agent.egg-info/PKG-INFO +106 -0
- qmpass_test_agent-1.0.10/src/qmpass_test_agent.egg-info/SOURCES.txt +93 -0
- qmpass_test_agent-1.0.10/src/qmpass_test_agent.egg-info/dependency_links.txt +1 -0
- qmpass_test_agent-1.0.10/src/qmpass_test_agent.egg-info/entry_points.txt +3 -0
- qmpass_test_agent-1.0.10/src/qmpass_test_agent.egg-info/requires.txt +29 -0
- qmpass_test_agent-1.0.10/src/qmpass_test_agent.egg-info/top_level.txt +1 -0
- qmpass_test_agent-1.0.10/tests/test_cli_version.py +14 -0
- qmpass_test_agent-1.0.10/tests/test_config.py +85 -0
- qmpass_test_agent-1.0.10/tests/test_doctor.py +82 -0
- qmpass_test_agent-1.0.10/tests/test_logging_and_messages.py +167 -0
- qmpass_test_agent-1.0.10/tests/test_messages_payload.py +95 -0
- qmpass_test_agent-1.0.10/tests/test_recorder_mapper.py +35 -0
- qmpass_test_agent-1.0.10/tests/test_tls_and_platform_url.py +66 -0
- qmpass_test_agent-1.0.10/tests/test_update_check.py +55 -0
- qmpass_test_agent-1.0.10/tests/test_version.py +10 -0
- qmpass_test_agent-1.0.10/tests/test_wheel_contents.py +40 -0
- qmpass_test_agent-1.0.10/tests/test_wheel_no_emit.py +29 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Qmpass Test Agent
|
|
2
|
+
Copyright (c) 2026 Qmpass. All rights reserved.
|
|
3
|
+
|
|
4
|
+
This software is proprietary. It is made available solely for use with a Qmpass subscription, to
|
|
5
|
+
connect machines you control to the Qmpass platform and run tests on them.
|
|
6
|
+
|
|
7
|
+
You may install and run unmodified copies of this software for that purpose. You may not modify,
|
|
8
|
+
redistribute, sublicense, sell, reverse engineer (except where the law permits it), or use this
|
|
9
|
+
software, or any part of it, to build a competing product or service.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. IN NO EVENT
|
|
12
|
+
SHALL QMPASS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE USE OF THE
|
|
13
|
+
SOFTWARE.
|
|
14
|
+
|
|
15
|
+
Use of the software is also subject to the Qmpass terms of service.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qmpass-test-agent
|
|
3
|
+
Version: 1.0.10
|
|
4
|
+
Summary: Run your Qmpass automated tests on your own machines, securely connected to your Jira projects.
|
|
5
|
+
Author: Qmpass
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: websockets==15.0.1
|
|
11
|
+
Requires-Dist: requests==2.34.2
|
|
12
|
+
Requires-Dist: psutil==6.1.1
|
|
13
|
+
Requires-Dist: truststore==0.10.4
|
|
14
|
+
Requires-Dist: robotframework==7.4.2
|
|
15
|
+
Requires-Dist: robotframework-browser==19.10.1
|
|
16
|
+
Requires-Dist: robotframework-requests==0.9.7
|
|
17
|
+
Requires-Dist: robotframework-datadriver==1.11.2
|
|
18
|
+
Requires-Dist: robotframework-faker==6.0.0
|
|
19
|
+
Requires-Dist: robotframework-databaselibrary==2.3.1
|
|
20
|
+
Provides-Extra: postgres
|
|
21
|
+
Requires-Dist: psycopg2-binary==2.9.10; extra == "postgres"
|
|
22
|
+
Provides-Extra: mysql
|
|
23
|
+
Requires-Dist: pymysql==1.1.1; extra == "mysql"
|
|
24
|
+
Provides-Extra: salesforce
|
|
25
|
+
Requires-Dist: rpaframework==33.0.1; extra == "salesforce"
|
|
26
|
+
Provides-Extra: desktop
|
|
27
|
+
Requires-Dist: pystray==0.19.5; extra == "desktop"
|
|
28
|
+
Requires-Dist: Pillow==11.3.0; extra == "desktop"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff>=0.6.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pip-tools>=7.0.0; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# Qmpass Test Agent
|
|
37
|
+
|
|
38
|
+
Run your [Qmpass](https://qmpass.ai) automated tests on your own laptops, servers or virtual
|
|
39
|
+
machines — faster feedback, safer releases, and full control over your test environments.
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- Python 3.10 or newer
|
|
44
|
+
- Node.js 18 or newer (for Browser tests)
|
|
45
|
+
- An agent token from Qmpass: **Project settings → Agents → Add agent**
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pipx install qmpass-test-agent # or: pipx install "qmpass-test-agent[postgres]" / [mysql] / [salesforce]
|
|
51
|
+
qmpass-agent setup # one time: installs the browser used by Browser tests
|
|
52
|
+
qmpass-agent doctor # checks everything below, with a fix for each problem
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`doctor` checks Python, Robot, Node.js and Chromium, your `QMPASS_TOKEN` / `QMPASS_URL`, that
|
|
56
|
+
Qmpass can be reached, and that the token is accepted — without starting a session, so it's safe to
|
|
57
|
+
run while an agent is already running.
|
|
58
|
+
|
|
59
|
+
Optional add-ons, only needed if your tests use them:
|
|
60
|
+
|
|
61
|
+
| Add-on | Install | For tests that |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `postgres` | `pipx install "qmpass-test-agent[postgres]"` | query a PostgreSQL database |
|
|
64
|
+
| `mysql` | `pipx install "qmpass-test-agent[mysql]"` | query a MySQL / MariaDB database |
|
|
65
|
+
| `salesforce` | `pipx install "qmpass-test-agent[salesforce]"` | work with Salesforce (large install) |
|
|
66
|
+
|
|
67
|
+
No pipx yet? `brew install pipx` (macOS), `python3 -m pip install --user pipx` (Windows / Linux),
|
|
68
|
+
then `pipx ensurepath`.
|
|
69
|
+
|
|
70
|
+
## Run
|
|
71
|
+
|
|
72
|
+
Copy the command shown with your agent token in Qmpass, or:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
export QMPASS_TOKEN=qmp_agent_…
|
|
76
|
+
qmpass-agent run
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The agent connects to `https://api.qmpass.ai` (set `QMPASS_URL` for other deployments), waits for
|
|
80
|
+
jobs, and logs one line when each run starts and finishes.
|
|
81
|
+
|
|
82
|
+
Useful options: `--worker N` (parallel jobs, up to 5), `--log-file PATH`, `--log-format json`,
|
|
83
|
+
`--log-level DEBUG`. Run `qmpass-agent --help` for all commands.
|
|
84
|
+
|
|
85
|
+
## Update
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pipx upgrade qmpass-test-agent
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
When a newer version is available, `qmpass-agent run` says so in one line at startup (and `doctor`
|
|
92
|
+
shows it). The agent never updates itself. Set `QMPASS_AGENT_UPDATE_CHECK=0` to turn the check off.
|
|
93
|
+
|
|
94
|
+
## Exit codes
|
|
95
|
+
|
|
96
|
+
| Code | Meaning |
|
|
97
|
+
|------|---------|
|
|
98
|
+
| 0 | Stopped normally |
|
|
99
|
+
| 2 | Configuration error |
|
|
100
|
+
| 3 | Refused by the platform (invalid or expired token, agent disabled) — the log says which |
|
|
101
|
+
| 4 | Agent too old — run `pipx upgrade qmpass-test-agent` |
|
|
102
|
+
| 5 | A prerequisite is missing (e.g. Node.js) — run `qmpass-agent setup` |
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
Proprietary — for use with a Qmpass subscription. See `LICENSE`.
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# Qmpass Test Agent
|
|
2
|
+
|
|
3
|
+
Python agent that connects to the **Qmpass platform gateway** via **WebSocket** and executes test jobs locally. Package namespace: `qmpass.*`.
|
|
4
|
+
|
|
5
|
+
Product Robot suite **codegen** is platform-side (`qmpass-robot-compiler`). This agent writes precompiled `robotSuites`, runs Robot Framework, and publishes results.
|
|
6
|
+
|
|
7
|
+
## How to run the agent
|
|
8
|
+
|
|
9
|
+
| Path | When to use |
|
|
10
|
+
|------|-------------|
|
|
11
|
+
| **pipx** (laptops, from PyPI) | `pipx install qmpass-test-agent`, `qmpass-agent setup` (Browser / Chromium), `qmpass-agent doctor` (checks everything) — see `README.pypi.md`, the PyPI page. |
|
|
12
|
+
| **Docker** (preferred for shared runners / CI) | Isolated image; no host Python. See [Deployment Options](#deployment-options). |
|
|
13
|
+
| **Local install in a dedicated venv** | QA laptops that must use **local browsers** (Robot Browser / Playwright on this machine). |
|
|
14
|
+
|
|
15
|
+
Do **not** install into the system Python or rely on a bare `python` on `PATH`. On many Macs that points at Python 2.7 and Robot will fail with `No module named Browser`. Always use an isolated environment so `qmpass-agent` and Robot share the same interpreter.
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- **Python 3.10+** (3.11 or 3.12 recommended) — used only to create the venv below
|
|
20
|
+
- **Node.js ≥ 18** on `PATH` (required by Robot Framework Browser / Playwright)
|
|
21
|
+
- **QMPASS_TOKEN** (from the Qmpass UI when creating an agent)
|
|
22
|
+
- **QMPASS_URL** (optional; defaults to `https://api.qmpass.ai`): set it for dev / staging / other deployments — the URL is shown with your agent token in Qmpass (Project settings → Agents → **Copy command**); plain `http://` only for a local stack such as `http://localhost:30085`
|
|
23
|
+
|
|
24
|
+
## Quick Start (local browsers — isolated `qmpass-agent` env)
|
|
25
|
+
|
|
26
|
+
Full path for a laptop that needs local Browser/Playwright. Create a **new** venv named for Qmpass, activate it, install into that env, then run. Do not use system Python.
|
|
27
|
+
|
|
28
|
+
You can create the venv from **any directory**. You only need the agent repo checkout when installing from source (`pip install -e .`). Once the agent is published as a package, install by name — no clone required.
|
|
29
|
+
|
|
30
|
+
### macOS / Linux — first-time setup
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 1) Confirm a real Python 3.10+ (do not use bare `python` if it is 2.x)
|
|
34
|
+
python3 --version
|
|
35
|
+
|
|
36
|
+
# 2) Create a dedicated env (any working directory is fine)
|
|
37
|
+
python3 -m venv ~/.venvs/qmpass-agent
|
|
38
|
+
|
|
39
|
+
# 3) Activate it (required for all following steps)
|
|
40
|
+
source ~/.venvs/qmpass-agent/bin/activate
|
|
41
|
+
# Prompt should show (qmpass-agent); `which python` → ~/.venvs/qmpass-agent/bin/python
|
|
42
|
+
|
|
43
|
+
# 4) Upgrade pip inside the venv only
|
|
44
|
+
python -m pip install --upgrade pip setuptools wheel
|
|
45
|
+
|
|
46
|
+
# 5) Install agent + Robot / Browser deps into this env
|
|
47
|
+
#
|
|
48
|
+
# From a source checkout (current / development):
|
|
49
|
+
cd /path/to/qmpass-test-agent
|
|
50
|
+
pip install -e .
|
|
51
|
+
#
|
|
52
|
+
# Later, when distributed as a package (no repo needed):
|
|
53
|
+
# pip install qmpass-test-agent
|
|
54
|
+
#
|
|
55
|
+
# Optional tray app (same env):
|
|
56
|
+
# pip install -e ".[desktop]"
|
|
57
|
+
# # or: pip install "qmpass-test-agent[desktop]"
|
|
58
|
+
# Salesforce REST (RPA.Salesforce / rpaframework) — large optional install:
|
|
59
|
+
# pip install -e ".[salesforce]"
|
|
60
|
+
# # or: pip install "qmpass-test-agent[salesforce]"
|
|
61
|
+
|
|
62
|
+
# 6) Install Playwright browsers used by Robot Framework Browser (same env)
|
|
63
|
+
python -m Browser.entry init
|
|
64
|
+
|
|
65
|
+
# 7) Configure and start (venv still activated)
|
|
66
|
+
export QMPASS_TOKEN="qmp_agent_xxxx"
|
|
67
|
+
# export QMPASS_URL="http://localhost:30085" # only off production; default is https://api.qmpass.ai
|
|
68
|
+
qmpass-agent run
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### macOS / Linux — every later session
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
source ~/.venvs/qmpass-agent/bin/activate
|
|
75
|
+
export QMPASS_TOKEN="qmp_agent_xxxx"
|
|
76
|
+
qmpass-agent run
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
(No need to `cd` into the repo unless you are reinstalling or developing.)
|
|
80
|
+
|
|
81
|
+
### Windows (PowerShell) — first-time setup
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
py -3.11 --version
|
|
85
|
+
py -3.11 -m venv $HOME\venvs\qmpass-agent
|
|
86
|
+
$HOME\venvs\qmpass-agent\Scripts\Activate.ps1
|
|
87
|
+
|
|
88
|
+
python -m pip install --upgrade pip setuptools wheel
|
|
89
|
+
|
|
90
|
+
# From source (current):
|
|
91
|
+
cd C:\path\to\qmpass-test-agent
|
|
92
|
+
pip install -e .
|
|
93
|
+
# Packaged release (later): pip install qmpass-test-agent
|
|
94
|
+
|
|
95
|
+
python -m Browser.entry init
|
|
96
|
+
|
|
97
|
+
$env:QMPASS_TOKEN = "qmp_agent_xxxx"
|
|
98
|
+
qmpass-agent run
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Verify (optional)
|
|
102
|
+
|
|
103
|
+
With `qmpass-agent` venv activated:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
which python # .../qmpass-agent/bin/python (not system 2.7)
|
|
107
|
+
which qmpass-agent # .../qmpass-agent/bin/qmpass-agent
|
|
108
|
+
python -c "import Browser, robot; print('ok', robot.__version__)"
|
|
109
|
+
node --version # >= 18
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Robot uses the same interpreter as the agent (`sys.executable`). You normally do **not** set `QMPASS_AGENT_PYTHON_BIN` when running from this venv.
|
|
113
|
+
|
|
114
|
+
## Configuration
|
|
115
|
+
|
|
116
|
+
Contributor conventions: see **[AGENTS.md](./AGENTS.md)** (includes how to add platform library adapters: Browser, RequestsLibrary, DatabaseLibrary, …).
|
|
117
|
+
|
|
118
|
+
| Variable | Required | Description |
|
|
119
|
+
| --------------------------- | -------- | --------------------------------------------------------------------------- |
|
|
120
|
+
| QMPASS_TOKEN | Yes | Token shown once when creating an agent in the UI |
|
|
121
|
+
| QMPASS_URL | No | Base URL of the gateway (shown with the agent token); default `https://api.qmpass.ai`. Must be `https://` except for localhost / 127.0.0.1 / host.docker.internal |
|
|
122
|
+
| MAX_PARALLEL_JOBS | No | Same as `--worker` / `--concurrency` when the CLI flag is omitted (default **1**, max **5**) |
|
|
123
|
+
| QMPASS_AGENT_KEEP_ROBOT_ARTIFACTS | No | If `true`, keep per-job temp dirs with Robot logs instead of deleting them |
|
|
124
|
+
| QMPASS_AGENT_RUN_ROOT | No | Base directory for per-job run artifacts (default: system temp dir) |
|
|
125
|
+
| QMPASS_AGENT_LAST_RUN_DIR | No | Fixed dir for local debug (`--worker=1` only). GATE: keeps `{target}.zip` per target |
|
|
126
|
+
| QMPASS_AGENT_PYTHON_BIN | No | Python for `python -m robot` (default: agent `sys.executable`) |
|
|
127
|
+
| QMPASS_AGENT_UPLOAD_ARTIFACTS | No | If `true`, upload Robot artifacts for DRY runs (GATE always uploads) |
|
|
128
|
+
| QMPASS_AGENT_ARTIFACT_MAX_SIZE_MB | No | Max per-file size (MB) for uploads (default 50) |
|
|
129
|
+
| QMPASS_AGENT_ROBOT_TIMEOUT_SEC | No | Default Robot timeout seconds when payload has no `timeoutMs` (default 600) |
|
|
130
|
+
| QMPASS_AGENT_ROBOT_EXIT_ON_FAILURE | No | Pass `--exitonfailure` to Robot |
|
|
131
|
+
| QMPASS_AGENT_ROBOT_INCLUDE_STEPS | No | Enrich results with `robot.steps[]` |
|
|
132
|
+
|
|
133
|
+
**Breaking change:** older env prefixes from earlier agent builds are no longer read. Use `QMPASS_AGENT_*` only.
|
|
134
|
+
|
|
135
|
+
The agent connects to `QMPASS_URL` over WebSocket at `/api/v1/agent/ws`, sending its token as `Authorization: Bearer <QMPASS_TOKEN>` (never in the URL). Jobs are pushed by the platform over the socket; results are sent back the same way. If the connection drops, running jobs carry on: the agent reconnects (backoff 2–30s, reset after a good connection) and sends any results that finished meanwhile.
|
|
136
|
+
|
|
137
|
+
## Deployment Options
|
|
138
|
+
|
|
139
|
+
- **Docker** (recommended for shared runners / CI): build from `docker/Dockerfile` using frozen locks under `requirements/` (see [`requirements/README.md`](./requirements/README.md)).
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Base image (default) — Browser / Requests / Database / DataDriver / Faker
|
|
143
|
+
docker build -f docker/Dockerfile -t qmpass-test-agent:base .
|
|
144
|
+
|
|
145
|
+
# Salesforce image — base + RPA.Salesforce (rpaframework)
|
|
146
|
+
docker build -f docker/Dockerfile --build-arg AGENT_VARIANT=salesforce -t qmpass-test-agent:salesforce .
|
|
147
|
+
|
|
148
|
+
docker run --rm -e QMPASS_TOKEN=… -e QMPASS_URL=… qmpass-test-agent:base
|
|
149
|
+
# Includes Node.js and Playwright Chromium; Browser environments must run headless in containers.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Runs as non-root. Laptop/dev can still `pip install -e .` without the lock; Docker/CI **must** use the lock files.
|
|
153
|
+
|
|
154
|
+
- **CLI (venv)**: follow [Quick Start](#quick-start-local-browsers--isolated-qmpass-agent-env). Ctrl+C triggers graceful disconnect.
|
|
155
|
+
- **Desktop**: `qmpass-agent desktop` or `qmpass-agent-desktop` — tray app; install with `pip install -e ".[desktop]"` **inside the same venv**.
|
|
156
|
+
|
|
157
|
+
## Logs and exit codes
|
|
158
|
+
|
|
159
|
+
The agent logs one line per event that matters: a startup summary, connection changes, and one
|
|
160
|
+
line when each run starts and finishes (result, duration, tests, artifacts). Robot's own console
|
|
161
|
+
output and the platform protocol are at `DEBUG`.
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
2026-10-05T09:12:03+05:30 INFO Connected as agent "QA-Laptop-01" (project DEMO). Waiting for jobs.
|
|
165
|
+
2026-10-05T09:14:10+05:30 INFO [run 3f2a1c9e] Run 3f2a1c9e started: runbook "Checkout smoke" on "Staging" (timeout 10m)
|
|
166
|
+
2026-10-05T09:14:53+05:30 INFO [run 3f2a1c9e] Run 3f2a1c9e passed in 43s: 12/12 tests passed · 5 artifacts uploaded (2.1 MB)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
| Option | Env var | Default |
|
|
170
|
+
|--------|---------|---------|
|
|
171
|
+
| `--log-level DEBUG\|INFO\|WARNING\|ERROR` | `QMPASS_AGENT_LOG_LEVEL` | `INFO` |
|
|
172
|
+
| `--log-file PATH` (rotated, 10 MB × 5) | `QMPASS_AGENT_LOG_FILE` | none (desktop app: `~/Library/Logs/Qmpass/agent.log`, `%LOCALAPPDATA%\Qmpass\Logs\agent.log`, `~/.local/state/qmpass/agent.log`) |
|
|
173
|
+
| `--log-format text\|json` (JSON: one object per line) | `QMPASS_AGENT_LOG_FORMAT` | `text` |
|
|
174
|
+
|
|
175
|
+
Agent and project tokens, presigned URL signatures and the current runs' secret values are masked
|
|
176
|
+
(`********`) in every log line.
|
|
177
|
+
|
|
178
|
+
| Exit code | Meaning |
|
|
179
|
+
|-----------|---------|
|
|
180
|
+
| 0 | Stopped normally |
|
|
181
|
+
| 2 | Configuration error (e.g. `QMPASS_URL` invalid) |
|
|
182
|
+
| 3 | The platform refused this agent: invalid or expired token, or agent disabled — the log says which |
|
|
183
|
+
| 4 | Agent too old for the platform — update `qmpass-test-agent` |
|
|
184
|
+
| 5 | A prerequisite is missing (e.g. Node.js) |
|
|
185
|
+
|
|
186
|
+
Network problems, a platform restart or another process using the token are retried (the reason is
|
|
187
|
+
logged once, then a reminder every 5 minutes).
|
|
188
|
+
|
|
189
|
+
## Security
|
|
190
|
+
|
|
191
|
+
- **Environment secrets** (database / API / Salesforce passwords and tokens) never appear in the
|
|
192
|
+
suite: it reads them as `%{QMPASS_…}`, and the agent passes their values to Robot only as
|
|
193
|
+
environment variables. After each run their values are masked (`********`) in `output.xml` and the
|
|
194
|
+
text artifacts, and `log.html` / `report.html` are rebuilt from the masked output before upload.
|
|
195
|
+
- **The agent token** never reaches Robot: runbooks can't read `%{QMPASS_TOKEN}`.
|
|
196
|
+
- **`QMPASS_URL`** defaults to production (`https://api.qmpass.ai`); a token only works on the platform
|
|
197
|
+
that issued it, so dev / staging agents set it. It must be `https://` (plain `http://` only for
|
|
198
|
+
localhost / `host.docker.internal`).
|
|
199
|
+
- **TLS** is verified against the operating system's trust store (macOS Keychain, Windows store,
|
|
200
|
+
`/etc/ssl`), so company proxies with their own root CA work and python.org Python needs no
|
|
201
|
+
"Install Certificates" step. `SSL_CERT_FILE` / `REQUESTS_CA_BUNDLE` override it; certifi is the
|
|
202
|
+
fallback. Verification is never disabled.
|
|
203
|
+
- **Run folders** under `QMPASS_AGENT_RUN_ROOT` are private to the agent's user (`0700`).
|
|
204
|
+
- **The recorder socket** (`127.0.0.1`) accepts only the Qmpass browser extension, not web pages.
|
|
205
|
+
- **Version:** the platform refuses agents older than its minimum (currently 1.0.0); update the agent
|
|
206
|
+
when it says so.
|
|
207
|
+
|
|
208
|
+
## CLI Commands
|
|
209
|
+
|
|
210
|
+
| Command | Description |
|
|
211
|
+
| ----------------------- | -------------------------------------------------------- |
|
|
212
|
+
| `qmpass-agent run` | Run agent (WebSocket connection; default **1** concurrent checkpoint job) |
|
|
213
|
+
| `qmpass-agent run --worker=N` | Up to **N** concurrent checkpoint jobs (max **5**; aliases `--workers`, `--concurrency`) |
|
|
214
|
+
| `qmpass-agent run-robot` | Run a `.robot` file using the agent's Python (libraries resolve) |
|
|
215
|
+
| `qmpass-agent desktop` | Launch desktop tray application |
|
|
216
|
+
| `qmpass-agent version` | Print version |
|
|
217
|
+
|
|
218
|
+
### Running generated .robot files
|
|
219
|
+
|
|
220
|
+
At runtime, each job is executed in its **own temporary directory** with a predictable structure.
|
|
221
|
+
|
|
222
|
+
- **Root directory**:
|
|
223
|
+
- Defaults to the system temp directory from `tempfile.gettempdir()` (e.g. `/tmp`).
|
|
224
|
+
- Can be overridden via `QMPASS_AGENT_RUN_ROOT`.
|
|
225
|
+
- **Per-job structure**:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
<QMPASS_AGENT_RUN_ROOT or /tmp>/qmpass/<scriptId>/<correlationId>/
|
|
229
|
+
runbook.robot
|
|
230
|
+
logs/
|
|
231
|
+
output.xml
|
|
232
|
+
log.html
|
|
233
|
+
report.html
|
|
234
|
+
playwright-log.txt
|
|
235
|
+
...
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The agent:
|
|
239
|
+
|
|
240
|
+
- Builds `runbook.robot` under the per-job directory.
|
|
241
|
+
- Runs `<agent-python> -m robot --outputdir <job-dir>/logs <job-dir>/runbook.robot`.
|
|
242
|
+
- Parses `<job-dir>/logs/output.xml` into the job result.
|
|
243
|
+
|
|
244
|
+
By default, the per-job directory is **deleted** after the result is built.
|
|
245
|
+
|
|
246
|
+
This uses the agent's Python environment so `Browser` and `RequestsLibrary` resolve correctly. Extra args are passed through to Robot Framework:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
qmpass-agent run-robot runbook.robot --loglevel DEBUG
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
If you want to inspect full Robot artifacts (log.html, output.xml, report.html, playwright-log.txt) per job, set:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
export QMPASS_AGENT_KEEP_ROBOT_ARTIFACTS=true
|
|
256
|
+
# optional root (still creates qmpass/<scriptId>/<correlationId>/):
|
|
257
|
+
export QMPASS_AGENT_RUN_ROOT=/Users/mehul/qmpass-runs
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
For **local debugging of only the latest run** (same path every time):
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
export QMPASS_AGENT_LAST_RUN_DIR=/Users/mehul/qmpass-runs/last
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
For **DRY / non-GATE** jobs, `$QMPASS_AGENT_LAST_RUN_DIR` keeps `runbook.robot` and `logs/` after each run (overwrites the previous job). `QMPASS_AGENT_LAST_RUN_DIR` implies keep (no cleanup).
|
|
267
|
+
|
|
268
|
+
For **GATE multi-target** runs (e.g. Chrome + Firefox), each target produces `{target}.zip` under the same directory. Staging `runbook.robot` and `logs/` are removed after each target zip is built — only the zips (plus `.qmpass-last-run-scope`) remain. Sibling target zips are kept until you start a different checkpoint.
|
|
269
|
+
|
|
270
|
+
In that case, the per-job temp directories are not removed and can be inspected manually.
|
|
271
|
+
S3 upload still runs for GATE (and for DRY when `QMPASS_AGENT_UPLOAD_ARTIFACTS=true`); keep mode
|
|
272
|
+
only skips deleting the local work dir after upload.
|
|
273
|
+
|
|
274
|
+
## Robot Execution Result Schema
|
|
275
|
+
|
|
276
|
+
When a job is executed via Robot Framework, `task_runner.execute(job)` returns a JSON-like structure that the platform uses to update execution state.
|
|
277
|
+
|
|
278
|
+
- **Top-level shape**:
|
|
279
|
+
|
|
280
|
+
```jsonc
|
|
281
|
+
{
|
|
282
|
+
"status": "PASS", // overall result: PASS / FAIL
|
|
283
|
+
"id": "6f99-...", // correlationId from TASK_REQUEST
|
|
284
|
+
"jobId": "job-123", // optional, from execution
|
|
285
|
+
"executionId": "exec-123", // optional, from execution
|
|
286
|
+
"executionTestCaseId": "etc-1", // optional, from execution
|
|
287
|
+
"runType": "DRY", // NORMAL / DRY / ...
|
|
288
|
+
"robot": { ... } // Robot-specific details
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
- **`robot` envelope**:
|
|
293
|
+
|
|
294
|
+
```jsonc
|
|
295
|
+
"robot": {
|
|
296
|
+
"status": "PASS", // suite-level PASS / FAIL
|
|
297
|
+
"startTime": "2026-03-03T12:00:01.636578",
|
|
298
|
+
"elapsedMs": 3336, // suite elapsed time in milliseconds
|
|
299
|
+
"statistics": {
|
|
300
|
+
"total": { "pass": 1, "fail": 0, "skip": 0 }
|
|
301
|
+
},
|
|
302
|
+
"tests": [
|
|
303
|
+
{
|
|
304
|
+
"id": "s1-t1",
|
|
305
|
+
"name": "Script 698cafa474778f72c4c09134",
|
|
306
|
+
"status": "PASS",
|
|
307
|
+
"startTime": "2026-03-03T12:00:03.483515",
|
|
308
|
+
"elapsedMs": 1455
|
|
309
|
+
}
|
|
310
|
+
],
|
|
311
|
+
"errors": [
|
|
312
|
+
{
|
|
313
|
+
"time": "2026-03-03T12:00:04.000000",
|
|
314
|
+
"level": "ERROR",
|
|
315
|
+
"text": "Suite setup failed: ..."
|
|
316
|
+
}
|
|
317
|
+
],
|
|
318
|
+
"robotExitCode": 0 // exit code from the Robot subprocess
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
- **Notes**:
|
|
323
|
+
- `status` at the top level mirrors `robot.status`. The platform uses this to decide if the job is considered successful.
|
|
324
|
+
- `tests[*]` maps directly to `<test>` elements in `output.xml`. Today there is one test per script: `Script <scriptId>`.
|
|
325
|
+
- `errors` contains suite-level errors from the `<errors>` block in `output.xml`.
|
|
326
|
+
- When `QMPASS_AGENT_ROBOT_INCLUDE_STEPS` is enabled, an additional `robot.steps[]` collection is populated with flattened step-level data (keywords and control structures) for debugging/analytics.
|
|
327
|
+
- Additional optional fields (for example, richer step-level data) will be added under `robot` to avoid breaking existing consumers.
|
|
328
|
+
|
|
329
|
+
## Startup & Preflight Checks
|
|
330
|
+
|
|
331
|
+
On startup (`qmpass-agent run`), the agent performs a **preflight environment check** before connecting to the platform:
|
|
332
|
+
|
|
333
|
+
- **Node.js / Browser**:
|
|
334
|
+
- Runs `node --version` and validates that:
|
|
335
|
+
- `node` is available in `PATH`.
|
|
336
|
+
- The major version is **≥ 18**.
|
|
337
|
+
- If the check fails, the agent logs a clear error like:
|
|
338
|
+
- `Browser library requires Node.js >= 18, but found 16.20.2. Agent cannot start.`
|
|
339
|
+
- In this case the agent **exits with code 1** and does not go ONLINE.
|
|
340
|
+
|
|
341
|
+
At **job execution time**, an additional per-job check is performed:
|
|
342
|
+
|
|
343
|
+
- If Node.js is not suitable when a job is received:
|
|
344
|
+
- The Robot subprocess is **not** started.
|
|
345
|
+
- The job result contains:
|
|
346
|
+
- `status: "FAIL"`
|
|
347
|
+
- `robot.error` with a human-readable message explaining the Node/Browsers requirement issue.
|
|
348
|
+
|
|
349
|
+
These checks are designed to:
|
|
350
|
+
|
|
351
|
+
- Fail fast on obvious misconfiguration at startup.
|
|
352
|
+
- Prevent individual jobs from hanging when Browser/Playwright cannot be started.
|
|
353
|
+
|
|
354
|
+
## Package Structure
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
qmpass/
|
|
358
|
+
__init__.py # __version__, Settings, run
|
|
359
|
+
cli.py # CLI entry (run, desktop, version)
|
|
360
|
+
desktop.py # Tray app (optional)
|
|
361
|
+
__main__.py # python -m qmpass
|
|
362
|
+
agent/
|
|
363
|
+
runtime.py # Process bootstrap (signals + WS loop)
|
|
364
|
+
system_info.py # x-agent-info handshake
|
|
365
|
+
client/ # WebSocket connection
|
|
366
|
+
runner/ # Job execution (execute, robot_process, work_dir, cancel)
|
|
367
|
+
robot/ # Suite generation + adapters
|
|
368
|
+
recorder/ # Recording / playback
|
|
369
|
+
artifact_upload.py
|
|
370
|
+
config/
|
|
371
|
+
settings.py # Settings SSOT from env
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Recorder extension
|
|
375
|
+
|
|
376
|
+
The recorder's browser extension ships inside the package at `src/qmpass/agent/recorder/sidebar/`
|
|
377
|
+
(package data, so pip / pipx / Docker installs all have it). The in-page widget
|
|
378
|
+
(`content-script/ui/qmpass-recorder-widget.js`) is built in **qmpass-test-recorder-web** with
|
|
379
|
+
`npm run build:widget`, which copies it there; commit the rebuilt file with the change.
|
|
380
|
+
|
|
381
|
+
## Releasing to PyPI
|
|
382
|
+
|
|
383
|
+
PyPI never accepts the same version twice, so **any** change that reaches the package, including
|
|
384
|
+
only the PyPI page (`README.pypi.md`) or `pyproject.toml` metadata, needs a new version.
|
|
385
|
+
|
|
386
|
+
**1. Bump the version** (semver: patch for fixes and docs, minor for new features, major for
|
|
387
|
+
breaking changes such as renamed env vars or CLI flags). It lives in two places, which must match:
|
|
388
|
+
|
|
389
|
+
- `pyproject.toml` → `version = "X.Y.Z"`
|
|
390
|
+
- `src/qmpass/__init__.py` → `__version__ = "X.Y.Z"` (shown by `qmpass-agent --version` and at startup)
|
|
391
|
+
|
|
392
|
+
**2. Check, then build a clean wheel**
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
source ~/.venvs/qmpass-agent/bin/activate
|
|
396
|
+
python -m pip install build twine
|
|
397
|
+
ruff check src tests && pytest -q
|
|
398
|
+
rm -rf build dist src/*.egg-info # stale files would end up in the wheel
|
|
399
|
+
python -m build --wheel # wheel only: no tests or repo files in the release
|
|
400
|
+
twine check dist/* # validates metadata and that README.pypi.md renders
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**3. Smoke-test the wheel in a throwaway env**
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
python3 -m venv /tmp/qmpass-release && /tmp/qmpass-release/bin/pip install dist/*.whl
|
|
407
|
+
/tmp/qmpass-release/bin/qmpass-agent --version # prints X.Y.Z
|
|
408
|
+
/tmp/qmpass-release/bin/qmpass-agent doctor # with QMPASS_TOKEN set
|
|
409
|
+
rm -rf /tmp/qmpass-release
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**4. Commit, then upload**
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
git commit -am "Release X.Y.Z: <what changed>"
|
|
416
|
+
twine upload dist/* # username __token__, password = your PyPI API token
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Check https://pypi.org/project/qmpass-test-agent/ shows the new version, then
|
|
420
|
+
`pipx upgrade qmpass-test-agent` (or `pip install -U qmpass-test-agent`). Running agents mention the
|
|
421
|
+
new version at startup (see `update_check.py`).
|
|
422
|
+
|
|
423
|
+
## Development
|
|
424
|
+
|
|
425
|
+
Use **VS Code** (or any editor). The repo ignores `.idea/` and `.vscode/` so local IDE settings stay out of git.
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
# Prefer the same dedicated venv as local install
|
|
429
|
+
source ~/.venvs/qmpass-agent/bin/activate
|
|
430
|
+
pip install -e ".[dev]"
|
|
431
|
+
pytest
|
|
432
|
+
ruff check src tests
|
|
433
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Qmpass Test Agent
|
|
2
|
+
|
|
3
|
+
Run your [Qmpass](https://qmpass.ai) automated tests on your own laptops, servers or virtual
|
|
4
|
+
machines — faster feedback, safer releases, and full control over your test environments.
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
- Python 3.10 or newer
|
|
9
|
+
- Node.js 18 or newer (for Browser tests)
|
|
10
|
+
- An agent token from Qmpass: **Project settings → Agents → Add agent**
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pipx install qmpass-test-agent # or: pipx install "qmpass-test-agent[postgres]" / [mysql] / [salesforce]
|
|
16
|
+
qmpass-agent setup # one time: installs the browser used by Browser tests
|
|
17
|
+
qmpass-agent doctor # checks everything below, with a fix for each problem
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`doctor` checks Python, Robot, Node.js and Chromium, your `QMPASS_TOKEN` / `QMPASS_URL`, that
|
|
21
|
+
Qmpass can be reached, and that the token is accepted — without starting a session, so it's safe to
|
|
22
|
+
run while an agent is already running.
|
|
23
|
+
|
|
24
|
+
Optional add-ons, only needed if your tests use them:
|
|
25
|
+
|
|
26
|
+
| Add-on | Install | For tests that |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `postgres` | `pipx install "qmpass-test-agent[postgres]"` | query a PostgreSQL database |
|
|
29
|
+
| `mysql` | `pipx install "qmpass-test-agent[mysql]"` | query a MySQL / MariaDB database |
|
|
30
|
+
| `salesforce` | `pipx install "qmpass-test-agent[salesforce]"` | work with Salesforce (large install) |
|
|
31
|
+
|
|
32
|
+
No pipx yet? `brew install pipx` (macOS), `python3 -m pip install --user pipx` (Windows / Linux),
|
|
33
|
+
then `pipx ensurepath`.
|
|
34
|
+
|
|
35
|
+
## Run
|
|
36
|
+
|
|
37
|
+
Copy the command shown with your agent token in Qmpass, or:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
export QMPASS_TOKEN=qmp_agent_…
|
|
41
|
+
qmpass-agent run
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The agent connects to `https://api.qmpass.ai` (set `QMPASS_URL` for other deployments), waits for
|
|
45
|
+
jobs, and logs one line when each run starts and finishes.
|
|
46
|
+
|
|
47
|
+
Useful options: `--worker N` (parallel jobs, up to 5), `--log-file PATH`, `--log-format json`,
|
|
48
|
+
`--log-level DEBUG`. Run `qmpass-agent --help` for all commands.
|
|
49
|
+
|
|
50
|
+
## Update
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pipx upgrade qmpass-test-agent
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
When a newer version is available, `qmpass-agent run` says so in one line at startup (and `doctor`
|
|
57
|
+
shows it). The agent never updates itself. Set `QMPASS_AGENT_UPDATE_CHECK=0` to turn the check off.
|
|
58
|
+
|
|
59
|
+
## Exit codes
|
|
60
|
+
|
|
61
|
+
| Code | Meaning |
|
|
62
|
+
|------|---------|
|
|
63
|
+
| 0 | Stopped normally |
|
|
64
|
+
| 2 | Configuration error |
|
|
65
|
+
| 3 | Refused by the platform (invalid or expired token, agent disabled) — the log says which |
|
|
66
|
+
| 4 | Agent too old — run `pipx upgrade qmpass-test-agent` |
|
|
67
|
+
| 5 | A prerequisite is missing (e.g. Node.js) — run `qmpass-agent setup` |
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
Proprietary — for use with a Qmpass subscription. See `LICENSE`.
|