testreporthub 1.0.0__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.
Files changed (34) hide show
  1. testreporthub-1.0.0/.github/workflows/release.yaml +48 -0
  2. testreporthub-1.0.0/.github/workflows/test.yaml +27 -0
  3. testreporthub-1.0.0/.gitignore +39 -0
  4. testreporthub-1.0.0/PKG-INFO +116 -0
  5. testreporthub-1.0.0/README.md +91 -0
  6. testreporthub-1.0.0/VISION.md +80 -0
  7. testreporthub-1.0.0/action/action.yaml +178 -0
  8. testreporthub-1.0.0/examples/run_demo.sh +10 -0
  9. testreporthub-1.0.0/pyproject.toml +42 -0
  10. testreporthub-1.0.0/src/testreporthub/__init__.py +3 -0
  11. testreporthub-1.0.0/src/testreporthub/__main__.py +4 -0
  12. testreporthub-1.0.0/src/testreporthub/aggregator.py +61 -0
  13. testreporthub-1.0.0/src/testreporthub/cli.py +343 -0
  14. testreporthub-1.0.0/src/testreporthub/db.py +406 -0
  15. testreporthub-1.0.0/src/testreporthub/models.py +107 -0
  16. testreporthub-1.0.0/src/testreporthub/parsers/__init__.py +4 -0
  17. testreporthub-1.0.0/src/testreporthub/parsers/base.py +27 -0
  18. testreporthub-1.0.0/src/testreporthub/parsers/cypress_json.py +92 -0
  19. testreporthub-1.0.0/src/testreporthub/parsers/junit_xml.py +114 -0
  20. testreporthub-1.0.0/src/testreporthub/parsers/newman_json.py +99 -0
  21. testreporthub-1.0.0/src/testreporthub/parsers/playwright_json.py +145 -0
  22. testreporthub-1.0.0/src/testreporthub/parsers/registry.py +51 -0
  23. testreporthub-1.0.0/src/testreporthub/reporter.py +83 -0
  24. testreporthub-1.0.0/tests/conftest.py +8 -0
  25. testreporthub-1.0.0/tests/fixtures/cypress.json +31 -0
  26. testreporthub-1.0.0/tests/fixtures/junit.xml +15 -0
  27. testreporthub-1.0.0/tests/fixtures/junit2.xml +15 -0
  28. testreporthub-1.0.0/tests/fixtures/newman.json +28 -0
  29. testreporthub-1.0.0/tests/fixtures/playwright.json +41 -0
  30. testreporthub-1.0.0/tests/test_aggregator.py +15 -0
  31. testreporthub-1.0.0/tests/test_db.py +230 -0
  32. testreporthub-1.0.0/tests/test_models.py +22 -0
  33. testreporthub-1.0.0/tests/test_parser.py +53 -0
  34. testreporthub-1.0.0/tests/test_reporter.py +19 -0
@@ -0,0 +1,48 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ id-token: write # Required for PyPI trusted publishing
10
+ contents: read
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: '3.11'
21
+
22
+ - name: Install build tools
23
+ run: pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Upload artifacts
29
+ uses: actions/upload-artifact@v4
30
+ with:
31
+ name: python-package
32
+ path: dist/
33
+
34
+ publish:
35
+ needs: build
36
+ runs-on: ubuntu-latest
37
+ environment:
38
+ name: pypi
39
+ url: https://pypi.org/p/testreporthub
40
+ steps:
41
+ - name: Download artifacts
42
+ uses: actions/download-artifact@v4
43
+ with:
44
+ name: python-package
45
+ path: dist/
46
+
47
+ - name: Publish to PyPI
48
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,27 @@
1
+ # .github/workflows/qa.yml
2
+ name: QA
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v4
10
+
11
+ - name: Run Playwright tests
12
+ run: npx playwright test --reporter=json
13
+
14
+ - name: Run pytest
15
+ run: pytest --junitxml=junit.xml
16
+
17
+ - name: Unify & enforce quality
18
+ uses: krishnakv-25/testreporthub@v1
19
+ with:
20
+ inputs: 'junit.xml playwright-report.json'
21
+ output: 'unified-report.html'
22
+ labels: 'org=acme,app=checkout-service,env=${{ github.ref_name }}'
23
+ enable-quality-gate: 'true'
24
+ min-pass-rate: '95'
25
+ max-flake-rate: '5'
26
+ max-regressions: '0'
27
+ fail-on-failed: 'true'
@@ -0,0 +1,39 @@
1
+ cat << 'EOF' > .gitignore
2
+ # Python
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+ *.egg-info/
7
+ dist/
8
+ build/
9
+ *.egg
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # IDEs
17
+ .vscode/
18
+ .idea/
19
+ *.swp
20
+ *.swo
21
+
22
+ # Local databases and reports
23
+ *.db
24
+ report.html
25
+ demo-report.html
26
+ unified-report.html
27
+
28
+ # OS files
29
+ .DS_Store
30
+ Thumbs.db
31
+
32
+ # Test artifacts
33
+ .pytest_cache/
34
+ .coverage
35
+ htmlcov/
36
+
37
+ # VHS demo artifacts (keep the .tape, not the generated files)
38
+ assets/*.gif
39
+ EOF
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.5
2
+ Name: testreporthub
3
+ Version: 1.0.0
4
+ Summary: Unified test reporting: ingest JUnit/Cypress/Playwright/Newman and emit one searchable HTML report.
5
+ Author: TestReportHub Contributors
6
+ License: MIT
7
+ Keywords: cypress,junit,playwright,qa,reports,testing
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Software Development :: Testing
16
+ Requires-Python: >=3.9
17
+ Requires-Dist: click>=8.1
18
+ Requires-Dist: defusedxml>=0.7
19
+ Requires-Dist: jinja2>=3.1
20
+ Requires-Dist: pydantic>=2.5
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest-cov; extra == 'dev'
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # TestReportHub
27
+
28
+ **One command. One report. Every framework.**
29
+
30
+ TestReportHub ingests test execution reports from different frameworks...
31
+ (JUnit XML, Cypress, Playwright, Newman/Postman), normalizes them into a
32
+ single data model, and emits a self-contained, searchable HTML quality report.
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install testreporthub
38
+ ```
39
+
40
+ Or from source:
41
+
42
+ ```bash
43
+ git clone https://github.com/your-org/testreporthub.git
44
+ cd testreporthub
45
+ pip install -e .
46
+ ```
47
+
48
+ ## Quick start
49
+
50
+ ```bash
51
+ # Ingest anything — JUnit XML, Cypress, Playwright, Newman
52
+ trh collect ./results/ -o report.html
53
+
54
+ # Auto-detect formats (default)
55
+ trh collect ./cypress/results ./playwright/results ./junit.xml
56
+
57
+ # Force a specific format
58
+ trh collect ./legacy.xml --format junit
59
+
60
+ # Open the report
61
+ open report.html
62
+ ```
63
+
64
+ ## 🚀 CI/CD Integration
65
+
66
+ TestReportHub is designed to run in your CI pipeline. It provides machine-readable outputs and strict exit codes.
67
+
68
+ ### Fail the build on failures
69
+ ```bash
70
+ # Exits with code 1 if any test failed or errored
71
+ trh collect ./results/ -o report.json --fail-on-failed --fail-on-error
72
+ ```
73
+
74
+ ## Supported formats
75
+
76
+ | Format | Source | Flag |
77
+ | --- | --- | --- |
78
+ | JUnit XML | pytest, Java, Go, Rust, etc. | `--format junit` |
79
+ | Cypress JSON | Mocha-based reporter | `--format cypress` |
80
+ | Playwright JSON | `--reporter=json` | `--format playwright` |
81
+ | Newman JSON | Postman collections | `--format newman` |
82
+
83
+ ## Normalized model
84
+
85
+ Every test is normalized to:
86
+
87
+ ```
88
+ id, name, full_name, suite, framework, status, duration_ms,
89
+ started_at, message, trace, error_type, tags, metadata, attachments
90
+ ```
91
+
92
+ Statuses: `passed`, `failed`, `skipped`, `error`, `xfailed`.
93
+
94
+ ## Why this matters
95
+
96
+ Teams usually have test results scattered across UI, API, regression,
97
+ and legacy automation. TestReportHub gives you:
98
+
99
+ * one command to collect results
100
+ * one normalized test-result model
101
+ * one unified report
102
+ * one place to understand failures
103
+
104
+ It's also the foundation for **TestPulse** — flaky-test detection and
105
+ failure intelligence — but the MVP stays small on purpose.
106
+
107
+ ## Development
108
+
109
+ ```bash
110
+ pip install -e ".[dev]"
111
+ pytest
112
+ ```
113
+
114
+ ## License
115
+
116
+ MIT
@@ -0,0 +1,91 @@
1
+ # TestReportHub
2
+
3
+ **One command. One report. Every framework.**
4
+
5
+ TestReportHub ingests test execution reports from different frameworks...
6
+ (JUnit XML, Cypress, Playwright, Newman/Postman), normalizes them into a
7
+ single data model, and emits a self-contained, searchable HTML quality report.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install testreporthub
13
+ ```
14
+
15
+ Or from source:
16
+
17
+ ```bash
18
+ git clone https://github.com/your-org/testreporthub.git
19
+ cd testreporthub
20
+ pip install -e .
21
+ ```
22
+
23
+ ## Quick start
24
+
25
+ ```bash
26
+ # Ingest anything — JUnit XML, Cypress, Playwright, Newman
27
+ trh collect ./results/ -o report.html
28
+
29
+ # Auto-detect formats (default)
30
+ trh collect ./cypress/results ./playwright/results ./junit.xml
31
+
32
+ # Force a specific format
33
+ trh collect ./legacy.xml --format junit
34
+
35
+ # Open the report
36
+ open report.html
37
+ ```
38
+
39
+ ## 🚀 CI/CD Integration
40
+
41
+ TestReportHub is designed to run in your CI pipeline. It provides machine-readable outputs and strict exit codes.
42
+
43
+ ### Fail the build on failures
44
+ ```bash
45
+ # Exits with code 1 if any test failed or errored
46
+ trh collect ./results/ -o report.json --fail-on-failed --fail-on-error
47
+ ```
48
+
49
+ ## Supported formats
50
+
51
+ | Format | Source | Flag |
52
+ | --- | --- | --- |
53
+ | JUnit XML | pytest, Java, Go, Rust, etc. | `--format junit` |
54
+ | Cypress JSON | Mocha-based reporter | `--format cypress` |
55
+ | Playwright JSON | `--reporter=json` | `--format playwright` |
56
+ | Newman JSON | Postman collections | `--format newman` |
57
+
58
+ ## Normalized model
59
+
60
+ Every test is normalized to:
61
+
62
+ ```
63
+ id, name, full_name, suite, framework, status, duration_ms,
64
+ started_at, message, trace, error_type, tags, metadata, attachments
65
+ ```
66
+
67
+ Statuses: `passed`, `failed`, `skipped`, `error`, `xfailed`.
68
+
69
+ ## Why this matters
70
+
71
+ Teams usually have test results scattered across UI, API, regression,
72
+ and legacy automation. TestReportHub gives you:
73
+
74
+ * one command to collect results
75
+ * one normalized test-result model
76
+ * one unified report
77
+ * one place to understand failures
78
+
79
+ It's also the foundation for **TestPulse** — flaky-test detection and
80
+ failure intelligence — but the MVP stays small on purpose.
81
+
82
+ ## Development
83
+
84
+ ```bash
85
+ pip install -e ".[dev]"
86
+ pytest
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,80 @@
1
+ # TestReportHub Vision
2
+
3
+ TestReportHub is the data ingestion layer for **TestPulse**, a test-failure intelligence platform.
4
+
5
+ ## Two-Tier Architecture
6
+
7
+ ### Tier 1: TestReportHub (Local CLI)
8
+ **Target user:** Individual engineer
9
+ **Scope:** One repo, one run
10
+ **Storage:** Stateless HTML/JSON, optional local SQLite
11
+ **Value:** "Show me this run, unified across frameworks"
12
+
13
+ Commands:
14
+ - `trh collect` — generate unified report
15
+ - `trh ingest` — persist to local SQLite with labels
16
+ - `trh flaky` — find flaky tests
17
+ - `trh compare` — diff two runs
18
+ - `trh history` — trend analysis
19
+ - `trh quality-gate` — enforce quality thresholds
20
+
21
+ ### Tier 2: TestPulse (Hosted SaaS)
22
+ **Target user:** QA leads, engineering managers
23
+ **Scope:** Entire org, all time
24
+ **Storage:** Hosted database
25
+ **Value:** "Show me the health of checkout-service across all environments"
26
+
27
+ Features (future):
28
+ - Multi-tenant web dashboard
29
+ - Team-based access control
30
+ - Slack/Jira integrations
31
+ - ML-based flake prediction
32
+ - Failure clustering and root-cause hints
33
+ - SLO tracking per app/env
34
+
35
+ ## The Bridge: Labels
36
+
37
+ The `--label` flag on `trh ingest` is the bridge between tiers. Labels like `org=acme,app=checkout,env=staging` map directly to the hierarchy in TestPulse.
38
+
39
+ Local CLI users get hierarchical filtering for free. When they're ready for the SaaS, their data model is already compatible.
40
+
41
+ ## Design Principles
42
+
43
+ 1. **Zero-config by default.** `pip install testreporthub` should be the only setup.
44
+ 2. **Self-contained outputs.** HTML reports have no external dependencies.
45
+ 3. **Labels over schema.** Don't hardcode org/app/env — use flexible key-value labels.
46
+ 4. **CLI-first, UI-later.** The SaaS is a UI on top of the same data model.
47
+ 5. **Fail fast in CI.** Quality gates should block deployments when quality drops.
48
+
49
+ ## Roadmap
50
+
51
+ ### v1.0 (Current)
52
+ - [x] Parsers: JUnit, Cypress, Playwright, Newman
53
+ - [x] HTML report with search/filter
54
+ - [x] JSON/NDJSON output
55
+ - [x] CI exit codes
56
+ - [x] SQLite backend with labels
57
+ - [x] Intelligence: flaky, compare, history, quality-gate
58
+ - [x] GitHub Action
59
+ - [x] PyPI release
60
+
61
+ ### v1.1 (Next)
62
+ - [ ] Streaming parsers for 100MB+ files
63
+ - [ ] Attachment bundling (screenshots/videos in report)
64
+ - [ ] Secret redaction (`--redact`)
65
+ - [ ] HTML trend charts in report
66
+ - [ ] More parsers: Jest, Mocha, Robot, Cucumber
67
+
68
+ ### v2.0 (TestPulse Preview)
69
+ - [ ] Hosted SaaS launch
70
+ - [ ] Web dashboard with hierarchy navigation
71
+ - [ ] Slack notifications on quality gate breaches
72
+ - [ ] Jira/GitHub issue creation from failures
73
+ - [ ] Team-based access control
74
+
75
+ ## What TestReportHub is NOT
76
+
77
+ - Not a test runner
78
+ - Not a test framework
79
+ - Not a replacement for Allure/ReportPortal (it complements them)
80
+ - Not a SaaS (yet — that's TestPulse)
@@ -0,0 +1,178 @@
1
+ name: 'TestReportHub'
2
+ description: 'Unify test reports and enforce quality gates across org/app/env hierarchies.'
3
+ author: 'TestReportHub Contributors'
4
+ branding:
5
+ icon: 'check-circle'
6
+ color: 'blue'
7
+
8
+ inputs:
9
+ # Collection inputs
10
+ inputs:
11
+ description: 'Space-separated list of files or directories to ingest.'
12
+ required: true
13
+ output:
14
+ description: 'Path to the output report file.'
15
+ required: false
16
+ default: 'unified-report.html'
17
+ format:
18
+ description: 'Output format: html, json, or ndjson.'
19
+ required: false
20
+ default: 'html'
21
+
22
+ # Labels (hierarchy)
23
+ labels:
24
+ description: 'Comma-separated key=value labels (e.g., "org=acme,app=checkout,env=staging").'
25
+ required: false
26
+ default: ''
27
+
28
+ # Quality gate
29
+ enable-quality-gate:
30
+ description: 'Run quality gate checks after ingestion.'
31
+ required: false
32
+ default: 'false'
33
+ min-pass-rate:
34
+ description: 'Minimum pass rate (%) for quality gate.'
35
+ required: false
36
+ default: '95'
37
+ max-flake-rate:
38
+ description: 'Maximum flaky test rate (%) for quality gate.'
39
+ required: false
40
+ default: '5'
41
+ max-regressions:
42
+ description: 'Maximum allowed regressions vs previous run.'
43
+ required: false
44
+ default: '0'
45
+
46
+ # Failure behavior
47
+ fail-on-failed:
48
+ description: 'Fail the action if any tests failed.'
49
+ required: false
50
+ default: 'false'
51
+ fail-on-error:
52
+ description: 'Fail the action if any tests errored.'
53
+ required: false
54
+ default: 'false'
55
+
56
+ # Persistence
57
+ db-path:
58
+ description: 'Path to the SQLite database for historical tracking.'
59
+ required: false
60
+ default: 'testpulse.db'
61
+
62
+ # Version
63
+ version:
64
+ description: 'TestReportHub version to install from PyPI.'
65
+ required: false
66
+ default: 'latest'
67
+
68
+ outputs:
69
+ report-path:
70
+ description: 'Path to the generated report'
71
+ value: ${{ inputs.output }}
72
+ quality-gate-passed:
73
+ description: 'Whether the quality gate passed (true/false/na)'
74
+ value: ${{ steps.quality-gate.outputs.passed }}
75
+
76
+ runs:
77
+ using: 'composite'
78
+ steps:
79
+ - name: Setup Python
80
+ uses: actions/setup-python@v5
81
+ with:
82
+ python-version: '3.11'
83
+
84
+ - name: Install TestReportHub
85
+ shell: bash
86
+ run: |
87
+ if [ "${{ inputs.version }}" = "latest" ]; then
88
+ pip install testreporthub
89
+ else
90
+ pip install testreporthub==${{ inputs.version }}
91
+ fi
92
+
93
+ - name: Build CLI command
94
+ id: build-cmd
95
+ shell: bash
96
+ run: |
97
+ # Parse space-separated inputs into array
98
+ INPUTS_ARRAY=(${{ inputs.inputs }})
99
+
100
+ COLLECT_CMD="trh collect"
101
+ for input in "${INPUTS_ARRAY[@]}"; do
102
+ COLLECT_CMD="$COLLECT_CMD \"$input\""
103
+ done
104
+ COLLECT_CMD="$COLLECT_CMD -o ${{ inputs.output }} --format ${{ inputs.format }}"
105
+
106
+ if [ "${{ inputs.fail-on-failed }}" = "true" ]; then
107
+ COLLECT_CMD="$COLLECT_CMD --fail-on-failed"
108
+ fi
109
+ if [ "${{ inputs.fail-on-error }}" = "true" ]; then
110
+ COLLECT_CMD="$COLLECT_CMD --fail-on-error"
111
+ fi
112
+
113
+ echo "collect_cmd=$COLLECT_CMD" >> $GITHUB_OUTPUT
114
+
115
+ - name: Generate Unified Report
116
+ shell: bash
117
+ run: |
118
+ echo "Running: ${{ steps.build-cmd.outputs.collect_cmd }}"
119
+ eval ${{ steps.build-cmd.outputs.collect_cmd }}
120
+
121
+ - name: Ingest to database (with labels)
122
+ if: inputs.enable-quality-gate == 'true'
123
+ shell: bash
124
+ run: |
125
+ INPUTS_ARRAY=(${{ inputs.inputs }})
126
+ INGEST_CMD="trh ingest"
127
+ for input in "${INPUTS_ARRAY[@]}"; do
128
+ INGEST_CMD="$INGEST_CMD \"$input\""
129
+ done
130
+ INGEST_CMD="$INGEST_CMD --db ${{ inputs.db-path }}"
131
+
132
+ # Parse comma-separated labels
133
+ if [ -n "${{ inputs.labels }}" ]; then
134
+ IFS=',' read -ra LABEL_PAIRS <<< "${{ inputs.labels }}"
135
+ for pair in "${LABEL_PAIRS[@]}"; do
136
+ INGEST_CMD="$INGEST_CMD --label $pair"
137
+ done
138
+ fi
139
+
140
+ echo "Running: $INGEST_CMD"
141
+ eval $INGEST_CMD
142
+
143
+ - name: Run Quality Gate
144
+ if: inputs.enable-quality-gate == 'true'
145
+ id: quality-gate
146
+ shell: bash
147
+ run: |
148
+ GATE_CMD="trh quality-gate --db ${{ inputs.db-path }}"
149
+ GATE_CMD="$GATE_CMD --min-pass-rate ${{ inputs.min-pass-rate }}"
150
+ GATE_CMD="$GATE_CMD --max-flake-rate ${{ inputs.max-flake-rate }}"
151
+ GATE_CMD="$GATE_CMD --max-regressions ${{ inputs.max-regressions }}"
152
+ GATE_CMD="$GATE_CMD --fail-on-breach"
153
+
154
+ # Add label filters
155
+ if [ -n "${{ inputs.labels }}" ]; then
156
+ IFS=',' read -ra LABEL_PAIRS <<< "${{ inputs.labels }}"
157
+ for pair in "${LABEL_PAIRS[@]}"; do
158
+ GATE_CMD="$GATE_CMD --label $pair"
159
+ done
160
+ fi
161
+
162
+ echo "Running: $GATE_CMD"
163
+ if eval $GATE_CMD; then
164
+ echo "passed=true" >> $GITHUB_OUTPUT
165
+ else
166
+ echo "passed=false" >> $GITHUB_OUTPUT
167
+ exit 1
168
+ fi
169
+
170
+ - name: Upload Report Artifact
171
+ if: always()
172
+ uses: actions/upload-artifact@v4
173
+ with:
174
+ name: testreporthub-report-${{ github.run_id }}
175
+ path: |
176
+ ${{ inputs.output }}
177
+ ${{ inputs.db-path }}
178
+ retention-days: 30
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd "$(dirname "$0")/.."
5
+ pip install -e . >/dev/null
6
+
7
+ # Collect every fixture and write a unified report.
8
+ trh collect tests/fixtures -o demo-report.html
9
+
10
+ echo "✓ Wrote demo-report.html — open it in a browser."
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "testreporthub"
7
+ version = "1.0.0"
8
+ description = "Unified test reporting: ingest JUnit/Cypress/Playwright/Newman and emit one searchable HTML report."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "TestReportHub Contributors" }]
13
+ keywords = ["testing", "reports", "junit", "cypress", "playwright", "qa"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Topic :: Software Development :: Testing",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ ]
24
+ dependencies = [
25
+ "click>=8.1",
26
+ "pydantic>=2.5",
27
+ "defusedxml>=0.7",
28
+ "jinja2>=3.1",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ dev = ["pytest>=8.0", "pytest-cov"]
33
+
34
+ [project.scripts]
35
+ trh = "testreporthub.cli:main"
36
+ testreporthub = "testreporthub.cli:main"
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["src/testreporthub"]
40
+
41
+ [tool.pytest.ini_options]
42
+ testpaths = ["tests"]
@@ -0,0 +1,3 @@
1
+ """TestReportHub — unified test reporting."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,4 @@
1
+ from testreporthub.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()