Metadata-Version: 2.4
Name: iharmony
Version: 7.3.2
Summary: iHarmony by Innominds: unified quality engineering framework for UI, API, data and device testing on pytest + Playwright
Author-email: iHarmony <iHarmony@innominds.com>
License: MIT
Project-URL: Homepage, https://www.innominds.com
Project-URL: Repository, https://github.com/ShanInnominds/innoHarmony
Project-URL: Bug Tracker, https://github.com/ShanInnominds/innoHarmony/issues
Keywords: playwright,pytest,test-automation,quality-engineering,api-testing,data-validation,iot-testing,self-healing,mcp,innominds
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Framework :: Pytest
Classifier: Topic :: Software Development :: Testing
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: playwright<2,>=1.54
Requires-Dist: pytest<10,>=9.1
Requires-Dist: pytest-xdist<4,>=3.8
Requires-Dist: pytest-rerunfailures<17,>=16.4
Requires-Dist: PyYAML<7,>=6.0.2
Requires-Dist: python-dotenv<2,>=1.2.2
Requires-Dist: httpx<1,>=0.27
Provides-Extra: coverage
Requires-Dist: pytest-cov<8,>=7.1; extra == "coverage"
Provides-Extra: api-client
Requires-Dist: httpx>=0.27.0; extra == "api-client"
Requires-Dist: jmespath>=1.0.0; extra == "api-client"
Provides-Extra: graphql-client
Requires-Dist: gql[httpx]>=3.5.0; extra == "graphql-client"
Requires-Dist: httpx>=0.27.0; extra == "graphql-client"
Provides-Extra: soap-client
Requires-Dist: zeep>=4.3.3; extra == "soap-client"
Provides-Extra: data-comparison
Requires-Dist: pandas>=2.0.0; extra == "data-comparison"
Requires-Dist: openpyxl>=3.1.0; extra == "data-comparison"
Requires-Dist: xlrd>=2.0.1; extra == "data-comparison"
Provides-Extra: postgresql
Requires-Dist: psycopg2-binary>=2.9.0; extra == "postgresql"
Provides-Extra: sqlserver
Requires-Dist: pyodbc>=4.0.0; extra == "sqlserver"
Provides-Extra: oracle
Requires-Dist: oracledb>=1.0.0; extra == "oracle"
Provides-Extra: db2
Requires-Dist: ibm_db>=3.0.0; extra == "db2"
Provides-Extra: informix
Requires-Dist: IfxPy>=3.0.0; extra == "informix"
Provides-Extra: mysql
Requires-Dist: mysql-connector-python>=8.0.0; extra == "mysql"
Provides-Extra: snowflake
Requires-Dist: snowflake-connector-python>=3.0.0; extra == "snowflake"
Provides-Extra: allure-reporting
Requires-Dist: allure-pytest<3,>=2.16; extra == "allure-reporting"
Provides-Extra: html-reporting
Requires-Dist: pytest-html<5,>=4.2; extra == "html-reporting"
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.2; extra == "mcp"
Provides-Extra: contracts
Requires-Dist: jsonschema>=4.0; extra == "contracts"
Requires-Dist: openapi-spec-validator>=0.5; extra == "contracts"
Requires-Dist: schemathesis>=3.0; extra == "contracts"
Provides-Extra: pact
Requires-Dist: pact-python>=2.0; extra == "pact"
Provides-Extra: accessibility
Requires-Dist: axe-playwright-python>=0.1.3; extra == "accessibility"
Provides-Extra: visual
Requires-Dist: Pillow>=10.0; extra == "visual"
Provides-Extra: mongodb
Requires-Dist: pymongo>=4.0.0; extra == "mongodb"
Provides-Extra: telemetry
Requires-Dist: opentelemetry-api>=1.0; extra == "telemetry"
Requires-Dist: opentelemetry-sdk>=1.0; extra == "telemetry"
Requires-Dist: opentelemetry-exporter-otlp>=1.0; extra == "telemetry"
Provides-Extra: prometheus
Requires-Dist: prometheus-client>=0.17; extra == "prometheus"
Provides-Extra: dashboard
Requires-Dist: fastapi>=0.100; extra == "dashboard"
Requires-Dist: uvicorn>=0.20; extra == "dashboard"
Provides-Extra: vault
Requires-Dist: hvac>=1.0; extra == "vault"
Provides-Extra: aws
Requires-Dist: boto3>=1.26; extra == "aws"
Provides-Extra: azure
Requires-Dist: azure-keyvault-secrets>=4.0; extra == "azure"
Requires-Dist: azure-identity>=1.0; extra == "azure"
Provides-Extra: devices-serial
Requires-Dist: pyserial>=3.5; extra == "devices-serial"
Provides-Extra: devices-mqtt
Requires-Dist: paho-mqtt>=2.0; extra == "devices-mqtt"
Provides-Extra: devices-ssh
Requires-Dist: paramiko>=5.0; extra == "devices-ssh"
Provides-Extra: devices-coap
Requires-Dist: aiocoap>=0.4.7; extra == "devices-coap"
Provides-Extra: devices-modbus
Requires-Dist: pymodbus<5,>=3.15; extra == "devices-modbus"
Provides-Extra: devices-can
Requires-Dist: python-can>=4.4; extra == "devices-can"
Requires-Dist: cantools>=39; extra == "devices-can"
Provides-Extra: devices-ble
Requires-Dist: bleak>=0.22; extra == "devices-ble"
Provides-Extra: devices-adb
Requires-Dist: adbutils>=2.8; extra == "devices-adb"
Provides-Extra: devices-pool
Requires-Dist: filelock>=3.20.3; extra == "devices-pool"
Provides-Extra: devices-pool-redis
Requires-Dist: filelock>=3.20.3; extra == "devices-pool-redis"
Requires-Dist: redis>=5; extra == "devices-pool-redis"
Provides-Extra: devices-power
Requires-Dist: hidapi>=0.14; extra == "devices-power"
Provides-Extra: devices-sim
Requires-Dist: amqtt>=0.12; extra == "devices-sim"
Requires-Dist: asyncssh>=2.23.1; extra == "devices-sim"
Provides-Extra: devices
Requires-Dist: pyserial>=3.5; extra == "devices"
Requires-Dist: paho-mqtt>=2.0; extra == "devices"
Requires-Dist: paramiko>=5.0; extra == "devices"
Requires-Dist: aiocoap>=0.4.7; extra == "devices"
Requires-Dist: amqtt>=0.12; extra == "devices"
Requires-Dist: asyncssh>=2.23.1; extra == "devices"
Requires-Dist: pymodbus<5,>=3.15; extra == "devices"
Requires-Dist: python-can>=4.4; extra == "devices"
Requires-Dist: cantools>=39; extra == "devices"
Requires-Dist: bleak>=0.22; extra == "devices"
Requires-Dist: adbutils>=2.8; extra == "devices"
Requires-Dist: filelock>=3.20.3; extra == "devices"
Requires-Dist: redis>=5; extra == "devices"
Requires-Dist: hidapi>=0.14; extra == "devices"
Provides-Extra: apps
Requires-Dist: Appium-Python-Client>=4; extra == "apps"
Provides-Extra: apps-android
Requires-Dist: Appium-Python-Client>=4; extra == "apps-android"
Requires-Dist: adbutils>=2.8; extra == "apps-android"
Provides-Extra: all-databases
Requires-Dist: psycopg2-binary>=2.9.0; extra == "all-databases"
Requires-Dist: pyodbc>=4.0.0; extra == "all-databases"
Requires-Dist: oracledb>=1.0.0; extra == "all-databases"
Requires-Dist: ibm_db>=3.0.0; extra == "all-databases"
Requires-Dist: IfxPy>=3.0.0; extra == "all-databases"
Requires-Dist: mysql-connector-python>=8.0.0; extra == "all-databases"
Requires-Dist: snowflake-connector-python>=3.0.0; extra == "all-databases"
Provides-Extra: all-api-clients
Requires-Dist: httpx>=0.27.0; extra == "all-api-clients"
Requires-Dist: jmespath>=1.0.0; extra == "all-api-clients"
Requires-Dist: gql[httpx]>=3.5.0; extra == "all-api-clients"
Requires-Dist: zeep>=4.3.3; extra == "all-api-clients"
Provides-Extra: all
Requires-Dist: httpx>=0.27.0; extra == "all"
Requires-Dist: jmespath>=1.0.0; extra == "all"
Requires-Dist: gql[httpx]>=3.5.0; extra == "all"
Requires-Dist: zeep>=4.3.3; extra == "all"
Requires-Dist: pandas>=2.0.0; extra == "all"
Requires-Dist: openpyxl>=3.1.0; extra == "all"
Requires-Dist: xlrd>=2.0.1; extra == "all"
Requires-Dist: psycopg2-binary>=2.9.0; extra == "all"
Requires-Dist: pyodbc>=4.0.0; extra == "all"
Requires-Dist: oracledb>=1.0.0; extra == "all"
Requires-Dist: ibm_db>=3.0.0; extra == "all"
Requires-Dist: IfxPy>=3.0.0; extra == "all"
Requires-Dist: mysql-connector-python>=8.0.0; extra == "all"
Requires-Dist: snowflake-connector-python>=3.0.0; extra == "all"
Requires-Dist: allure-pytest<3,>=2.16; extra == "all"
Requires-Dist: pytest-html<5,>=4.2; extra == "all"
Requires-Dist: pytest-cov<8,>=7.1; extra == "all"
Provides-Extra: docs
Requires-Dist: pandas>=2.0.0; extra == "docs"
Requires-Dist: openpyxl>=3.1.0; extra == "docs"
Requires-Dist: xlrd>=2.0.1; extra == "docs"

<p align="center">
  <img src="https://raw.githubusercontent.com/ShanInnominds/innoHarmony-assets/main/iHarmony/hero.png" alt="iHarmony™ by Innominds — Unified Quality Engineering Framework" width="100%">
</p>

<p align="center">
  <a href="https://pypi.org/project/iharmony/"><img src="https://img.shields.io/pypi/v/iharmony?color=E84925&label=PyPI" alt="PyPI version"></a>
  <a href="https://pypi.org/project/iharmony/"><img src="https://img.shields.io/pypi/pyversions/iharmony?color=151C47" alt="Python versions"></a>
  <img src="https://img.shields.io/badge/pytest-plugin-151C47?logo=pytest&logoColor=white" alt="pytest plugin">
  <img src="https://img.shields.io/badge/Playwright-1.54%2B-151C47?logo=playwright&logoColor=white" alt="Playwright 1.54+">
  <img src="https://img.shields.io/badge/MCP-24%20tools-EFA523" alt="MCP: 24 tools">
  <a href="https://www.innominds.com"><img src="https://img.shields.io/badge/by-Innominds-E84925" alt="by Innominds"></a>
</p>

<p align="center">
  <b>Test the web app, the API behind it, the data it writes, the devices it talks to and the mobile and desktop apps around it —<br>
  with one pytest-native framework, one configuration model and one set of reports.</b>
</p>

---

## Why iHarmony™

Quality teams usually stitch together a UI tool, an API tool, a data-diff script and a hardware
harness, each with its own conventions and reports. **iHarmony™** puts all of them on
**pytest + Playwright** with a shared page-object model, YAML configuration, observability and a
release quality gate — so a 5-person team and a 100-person programme work the same way.

- **One workflow** — UI, API, database, file, device and mobile / desktop app tests are ordinary pytest tests.
- **Enterprise by default** — multi-project layouts, environment overlays, org → business-unit →
  project governance, secrets from environment variables or vaults, never from code.
- **Resilient** — self-healing locators, retries and flaky-test detection cut maintenance noise.
- **Decision-ready** — every run ends in reports for engineers, QA and leadership, plus an optional
  **PASS / WARN / BLOCK** verdict your pipeline can act on.
- **Opt-in everything** — install only the extras you need; features are off until enabled in YAML.

**13 capability areas:** Web UI Automation · Mobile & Desktop Apps · API & Contract Testing · Data & Database Validation · Device & IoT Testing · Test Data Management · Self-Healing & Resilience · Observability & Reporting · Release Quality Gate · Enterprise Governance · Security Built In · Scale, CI/CD & Integrations · AI-Ready (MCP Server).

<p align="center">
  <img src="https://raw.githubusercontent.com/ShanInnominds/innoHarmony-assets/main/iHarmony/capabilities.png" alt="iHarmony™ capabilities, 13 areas: Web UI Automation, Mobile & Desktop Apps, API & Contract Testing, Data & Database Validation, Device & IoT Testing, Test Data Management, Self-Healing & Resilience, Observability & Reporting, Release Quality Gate, Enterprise Governance, Security Built In, Scale, CI/CD & Integrations, AI-Ready (MCP Server)" width="100%">
</p>

## Install

```bash
pip install iharmony
playwright install chromium        # or: playwright install  (all browsers)
```

Requires **Python 3.11+**. Add extras for the capabilities you use:

| Extra | Adds |
|---|---|
| `iharmony[data-comparison]` | Excel / CSV / JSON comparison and HTML mismatch reports (pandas, openpyxl) |
| `iharmony[postgresql]` · `[mysql]` · `[sqlserver]` · `[oracle]` · `[db2]` · `[informix]` · `[snowflake]` · `[mongodb]` | Database drivers (SQLite needs none) — or `[all-databases]` |
| `iharmony[graphql-client]` · `[soap-client]` · `[contracts]` · `[pact]` | GraphQL, SOAP, OpenAPI / JSON-Schema and consumer-driven contract testing |
| `iharmony[accessibility]` | WCAG checks with axe-core |
| `iharmony[apps]` · `[apps-android]` | Mobile (Android, iOS) and desktop (Windows) app testing through Appium — preview |
| `iharmony[devices]` | Every device transport and the simulator (or pick `devices-serial`, `devices-mqtt`, `devices-can`, `devices-ble`, `devices-adb`, …) |
| `iharmony[mcp]` | MCP server for AI assistants |
| `iharmony[allure-reporting]` · `[html-reporting]` · `[dashboard]` · `[telemetry]` · `[prometheus]` | Reporting, live dashboard and OpenTelemetry / Prometheus export |
| `iharmony[vault]` · `[aws]` · `[azure]` | HashiCorp Vault, AWS Secrets Manager, Azure Key Vault |
| `iharmony[all]` | API clients, data comparison, all databases and reporting in one go |

## Quick start

```bash
iharmony init my-qe-suite       # scaffold a suite with runnable demos
cd my-qe-suite

export IHARMONY_TEST_USERNAME=standard_user    # demo login for saucedemo.com
export IHARMONY_TEST_PASSWORD=secret_sauce

pytest tests/demo/functional/api tests/demo/functional/ui
```

On Windows PowerShell, set the credentials with:

```powershell
$env:IHARMONY_TEST_USERNAME = "standard_user"
$env:IHARMONY_TEST_PASSWORD = "secret_sauce"
```

The scaffold contains configuration, page objects and demo UI, API and database tests.
The data-comparison demos also need `pip install "iharmony[data-comparison]"`.

<p align="center">
  <img src="https://raw.githubusercontent.com/ShanInnominds/innoHarmony-assets/main/iHarmony/workflow.png" alt="How it works: write pytest tests and page objects, configure per environment, run locally or in CI, decide with reports and a quality-gate verdict" width="100%">
</p>

## What tests look like

**Web UI** — locators live in page objects; tests read like the business flow.

```python
import pytest
from iharmony import BasePage


class LoginPage(BasePage):
    USERNAME = "#user-name"
    PASSWORD = "#password"
    SUBMIT = "#login-button"

    def login(self, user: str, password: str) -> None:
        self.fill(self.USERNAME, user)
        self.fill(self.PASSWORD, password)
        self.click(self.SUBMIT)


@pytest.mark.smoke
def test_login(page, runtime_options, login_test_data):
    login = LoginPage(page, runtime_options["resilience_policy"])
    login.navigate(runtime_options["base_url"])
    user = login_test_data["valid_user"]          # values resolved from ${ENV_VAR} placeholders
    login.login(user["username"], user["password"])
```

**API** — an HTTP client with retries, auth and chainable assertions.

```python
from iharmony import ApiClient, ResponseValidator


def test_create_order(base_url):
    api = ApiClient(base_url=base_url, retries=3)
    response = api.post("/orders", json_body={"sku": "A-100", "qty": 2})
    ResponseValidator.assert_status_code(response, 201)
    ResponseValidator.assert_json_has_keys(response, ["id", "status"])
    ResponseValidator.assert_response_time_less_than(response, 800)
```

**Data** — compare extracts, files and tables with keys, tolerances and column mappings.

```python
from iharmony.utils.data_comparison_utils import compare_excel_files


def test_migration_matches_legacy():
    result = compare_excel_files(
        "legacy_extract.xlsx", "new_platform_extract.xlsx",
        key_columns=["employee_id"], float_tolerance=0.01, ignore_fields={"updated_at"},
    )
    assert result.passed, result.summary    # interactive HTML report at result.report_path
```

For database migrations, check the schema (names, types, nullability), row counts and totals first, then every
row and column. Comparisons stream both databases in chunks and report rows missing in the target, rows that
exist only in the target, and changed values, so they scale to full production tables.

```python
from iharmony.utils.db_validation_helper import DbValidationHelper as V


def test_orders_migrated(src_db, tgt_db):
    V.assert_row_counts_match_chunked(src_db, "SELECT COUNT(*) FROM orders",
                                      tgt_db, "SELECT COUNT(*) FROM orders", label="orders")
    V.assert_datasets_match_chunked(
        src_db, "SELECT * FROM orders ORDER BY order_id",
        tgt_db, "SELECT * FROM orders ORDER BY order_id",
        key_column="order_id", float_tolerance_map={"amount": 0.01},
    )
```

**Devices** — the same test runs against a digital twin or real hardware.

```python
import pytest


@pytest.mark.device
@pytest.mark.requires_dut(capability="thermostat")
def test_heats_up(dut):
    dut.set_target(22)
    dut.wait_until_temperature(22, timeout=900)
```

```bash
pytest -m device                                   # simulated twin
pytest -m device --iharmony-dut-mode hil        # real hardware, same test
```

**Mobile & desktop apps** *(preview)* — Android native, hybrid and mobile web on phones and tablets, plus Windows
desktop apps, through Appium (iOS support is in the preview and still to be verified on a Mac). Screen objects
hold per-platform locators with self-healing fallbacks.

```python
import pytest
from iharmony.apps import BaseScreen, Locator


class LoginScreen(BaseScreen):
    USERNAME = Locator(android="id=com.example.shop:id/username", ios="accessibility_id=username")
    PASSWORD = Locator("accessibility_id=password")
    SIGN_IN = Locator("accessibility_id=sign_in", fallbacks=["xpath=//*[@text='Sign in']"])

    def login(self, user: str, password: str) -> None:
        self.type(self.USERNAME, user)
        self.type(self.PASSWORD, password, secret=True)   # kept out of the logs
        self.tap(self.SIGN_IN)


@pytest.mark.mobile
@pytest.mark.app("shop")
def test_login(app_session, runtime_options):
    LoginScreen(app_session, runtime_options["resilience_policy"]).login("demo", "s3cret")
```

`app_session.device` drives the device itself: lock and unlock, Wi-Fi, mobile data, airplane mode, Bluetooth,
dark mode, orientation, location, hardware buttons and the notification shade.

```python
@pytest.mark.mobile
@pytest.mark.app("shop")
def test_wifi_off(app_session):
    app_session.device.set_wifi(False)
    assert not app_session.device.wifi_enabled()
```

Apps and targets (emulators, devices, desktops, cloud hubs) live in `config/apps.yaml`, off until
`apps.enabled: true`; `iharmony apps check` asks each target's Appium server whether it is ready. Failing tests
keep a screenshot, the page source and the capabilities used (`iharmony docs app-automation`).

## Run it your way

| Goal | Command |
|---|---|
| Pick environment and browser | `pytest --ih-env qa --ih-browser firefox` (or set `IHARMONY_ENV=qa`) |
| Watch the browser | `pytest --ih-headed` |
| Emulate a phone | `pytest --ih-device "iPhone 13"` |
| Run app tests on a target | `pytest -m mobile --ih-app api-demos --ih-target android-emulator` |
| Check the app lab | `iharmony apps check` — exits 1 when an Appium server is not ready |
| Turn manual test cases into scripts | `iharmony generate-tests cases.csv --type ui` (or `api`, `database`, `device`, `mobile`) |
| Run in parallel | `pytest -n auto` |
| Run a suite by marker | `pytest -m smoke` · `pytest -m regression` |
| Check the environment first | `pytest --iharmony-readiness-check` |
| Gate the release | `pytest --iharmony-quality-gate` — exits 1 on **BLOCK** |
| Enforce suite ordering | `pytest --iharmony-orchestration` |
| Update visual baselines | `pytest --iharmony-update-snapshots` |

Every `--iharmony-<name>` option has the short alias `--ih-<name>`.

CI templates for **GitHub Actions**, **Jenkins** and **Azure DevOps** are included
(`iharmony docs ci`).

## AI-ready: MCP server

iHarmony™ ships a [Model Context Protocol](https://modelcontextprotocol.io) server so AI
assistants such as Claude and GitHub Copilot can discover the framework API, list tests, page and
screen objects, read resolved configuration and test results, check device benches and Appium app
targets, generate test scripts from manual test cases, and get a release recommendation.
All 24 tools are also terminal commands.

```bash
pip install "iharmony[mcp]"
iharmony-mcp serve                         # MCP server (stdio)
iharmony-mcp search-methods tolerance      # the same tools from the terminal
iharmony-mcp get-release-recommendation
```

## Documentation

Guides are installed with the package — no network or repository access needed:

```bash
iharmony docs                  # list every topic
iharmony docs quickstart       # print one
```

| Topic | Covers |
|---|---|
| `quickstart` · `install` · `cli` | First test in 10 minutes, installation, every command and `--iharmony-*` option |
| `api-policy` | What is public API, how deprecations are announced, supported Python / pytest / Playwright versions |
| `multi-project` · `test-organization` · `qe-visual-guide` | Suite layout at scale and the page-object model |
| `api-testing` · `database` · `data-validation` | REST / GraphQL / SOAP, database drivers and assertions, data comparison |
| `app-automation` | Mobile and desktop app testing with Appium (preview) |
| `architecture` · `resilience` · `observability` | How the layers fit, self-healing locators, metrics and persona reports |
| `secrets-governance` · `plugins` · `ci` · `mcp` | Secrets and org policy, plugin authoring, pipelines, the MCP server |

## Support

iHarmony™ is developed and supported by **Innominds**. For onboarding, enterprise support or
custom integrations, contact [iHarmony@innominds.com](mailto:iHarmony@innominds.com) or visit
[innominds.com](https://www.innominds.com).

<p align="center">
  <a href="https://www.innominds.com"><img src="https://raw.githubusercontent.com/ShanInnominds/innoHarmony-assets/main/iHarmony/footer.png" alt="Engineered by Innominds" width="100%"></a>
</p>

<p align="center"><sub>iHarmony™ is a trademark of Innominds. © Innominds. Released under the MIT License.</sub></p>
