Metadata-Version: 2.4
Name: innoharmony
Version: 5.3.0
Summary: innoHarmony by Innominds: unified quality engineering framework for UI, API, data and device testing on pytest + Playwright
Author-email: Shan Konduru <RKonduru@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: 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==1.54.0
Requires-Dist: pytest==9.1.1
Requires-Dist: pytest-cov==7.1.0
Requires-Dist: pytest-xdist==3.8.0
Requires-Dist: pytest-rerunfailures==16.4
Requires-Dist: PyYAML<7,>=6.0.2
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: httpx>=0.27.0
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==2.16.0; extra == "allure-reporting"
Provides-Extra: html-reporting
Requires-Dist: pytest-html==4.2.0; 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: 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: 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==2.16.0; extra == "all"
Requires-Dist: pytest-html==4.2.0; 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/readme/hero.png" alt="innoHarmony™ by Innominds — Unified Quality Engineering Framework" width="100%">
</p>

<p align="center">
  <a href="https://pypi.org/project/innoharmony/"><img src="https://img.shields.io/pypi/v/innoharmony?color=E84925&label=PyPI" alt="PyPI version"></a>
  <a href="https://pypi.org/project/innoharmony/"><img src="https://img.shields.io/pypi/pyversions/innoharmony?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-151C47?logo=playwright&logoColor=white" alt="Playwright 1.54">
  <img src="https://img.shields.io/badge/MCP-19%20tools-EFA523" alt="MCP: 19 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 and the devices it talks to —<br>
  with one pytest-native framework, one configuration model and one set of reports.</b>
</p>

---

## Why innoHarmony™

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. **innoHarmony™** 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 and device 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.

<p align="center">
  <img src="https://raw.githubusercontent.com/ShanInnominds/innoHarmony-assets/main/readme/capabilities.png" alt="innoHarmony capabilities: Web UI, API, data validation, device and embedded testing, self-healing locators, release quality gates, observability, AI-ready MCP server" width="100%">
</p>

## Install

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

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

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

## Quick start

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

export INNOHARMONY_TEST_USERNAME=standard_user    # demo login for saucedemo.com
export INNOHARMONY_TEST_PASSWORD=secret_sauce

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

On Windows PowerShell, set the credentials with:

```powershell
$env:INNOHARMONY_TEST_USERNAME = "standard_user"
$env:INNOHARMONY_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 "innoharmony[data-comparison]"`.

<p align="center">
  <img src="https://raw.githubusercontent.com/ShanInnominds/innoHarmony-assets/main/readme/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 innoharmony 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 innoharmony 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 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
```

**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 --innoharmony-dut-mode hil        # real hardware, same test
```

## Run it your way

| Goal | Command |
|---|---|
| Pick environment and browser | `pytest --ih-env qa --ih-browser firefox` (or set `INNOHARMONY_ENV=qa`) |
| Watch the browser | `pytest --ih-headed` |
| Emulate a phone | `pytest --ih-device "iPhone 13"` |
| Run in parallel | `pytest -n auto` |
| Run a suite by marker | `pytest -m smoke` · `pytest -m regression` |
| Check the environment first | `pytest --innoharmony-readiness-check` |
| Gate the release | `pytest --innoharmony-quality-gate` — exits 1 on **BLOCK** |
| Enforce suite ordering | `pytest --innoharmony-orchestration` |
| Update visual baselines | `pytest --innoharmony-update-snapshots` |

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

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

## AI-ready: MCP server

innoHarmony 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 and page
objects, read resolved configuration and test results, and get a release recommendation.
Every tool is also a terminal command.

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

## Documentation

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

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

| Topic | Covers |
|---|---|
| `quickstart` · `install` · `cli` | First test in 10 minutes, installation, every command and `--innoharmony-*` option |
| `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 |
| `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

innoHarmony is developed and supported by **Innominds**. For onboarding, enterprise support or
custom integrations, contact [RKonduru@innominds.com](mailto:RKonduru@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/readme/footer.png" alt="Engineered by Innominds" width="100%"></a>
</p>

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