# nihantra-patel/testcase_manager architecture

> Architecture diagram of the GitHub repository nihantra-patel/testcase_manager, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-23). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/nihantra-patel/testcase_manager
- Repository: https://github.com/nihantra-patel/testcase_manager

## Overview

1. **Top-level shape**
   - This repository is a **Frappe app** with a separate **Vue 3 single-page frontend** under `frontend/`.
   - The backend serves the app at `/testcase_manager`, and the built frontend is copied into `testcase_manager/www/testcase_manager.html` plus `testcase_manager/public/frontend/` during build.

2. **Main domain objects**
   - The persistent model is centered on three DocTypes:
     - **`Testcase`**: one discovered test method/spec.
     - **`Testcase Run`**: one execution record, including status, timing, output, and traceback.
     - **`Testcase Log`**: summary counts for a run, used for history/listing.
   - These are the key persistence boundaries for the whole system.

3. **Discovery subsystem**
   - `testcase_manager/testcase_manager/discovery.py` performs **AST-based discovery** of Python tests (`test_*.py`) across installed apps without importing them.
   - `ui_discovery.py` separately discovers **Cypress/UI specs** using the app’s test file conventions.
   - Discovery is automatically refreshed by hooks after migrations and on a daily scheduler run.

4. **API boundary**
   - `api.py` exposes the **whitelisted server endpoints** consumed by the SPA.
   - `queries.py` provides read-side listing/filtering queries for the UI.
   - The frontend talks to these endpoints through `frontend/src/api.js`.

5. **Python test execution path**
   - `executor.py` runs selected Python tests, typically in-process, and coordinates inline vs background execution depending on scope.
   - It is the core execution engine for method/file/doctype/app/batch runs.
   - Run lifecycle is managed so results can be persisted after completion.

6. **UI/Cypress execution path**
   - `ui_executor.py` runs UI tests via `bench run-ui-tests` in a background job.
   - This path is separate from Python execution because it is slower, headless-browser-based, and always run asynchronously.
   - It streams output back just like Python runs, so the frontend treats both execution types similarly.

7. **Realtime console and run lifecycle**
   - Execution output is published through Frappe realtime events, especially for live console updates.
   - The frontend’s `socket.js`, `useTestRunner.js`, and `Console.vue` form the live subscription/display layer.
   - The UI can stop queued or running jobs, and partial output is preserved in the saved run record.

8. **Frontend structure**
   - The SPA is organized around views in `frontend/src/pages/`:
     - **RunnerView**: discover/filter/select/run tests.
     - **HistoryView**: browse past runs.
     - **RunDetailView**: inspect one saved run.
     - **ProfilerView**: profile document actions.
   - `router.js` handles history-mode navigation inside the single app, while `App.vue` is the shell.

9. **Test-impact analysis**
   - `impact.py` statically analyzes the app’s git diff to infer affected tests without running them.
   - It uses import-graph relationships plus DocType links to select candidate tests.
   - This is an analysis-only subsystem; it feeds the runner with a narrowed batch selection.

10. **Document profiling subsystem**
    - `profiling.py` profiles a single document’s `submit` or `cancel` using `cProfile`.
    - The operation runs inside a database savepoint and is rolled back, so hooks execute and timings are real, but nothing persists.
    - This is a distinct non-persistent execution path from test runs.

11. **Routing, hosting, and platform hooks**
    - `hooks.py` wires the app into Frappe routing, scheduler events, and log-retention behavior.
    - `website_route_rules` maps SPA routes under `/testcase_manager/...` to the single HTML entrypoint.
    - `default_log_clearing_doctypes` controls retention for run/log records.

12. **Build and deployment boundary**
    - The frontend is built with **Vite** and packaged into the Frappe app during `bench build`.
    - The root `package.json` and `frontend/package.json` split workspace/build concerns from the app runtime.
    - GitHub Actions run backend tests, frontend build/lint checks, and separate UI test jobs, but these are CI concerns rather than runtime dependencies.

13. **Architecture summary for a diagram**
    - A good diagram should show:
      - **Browser SPA** → **Frappe whitelisted APIs** → **discovery/execution/profiling services**.
      - **Discovery** populating the **Testcase** table.
      - **Execution** creating/updating **Testcase Run** and **Testcase Log** records.
      - **Realtime events** streaming back to the console over websockets.
      - **Scheduler/migration hooks** keeping discovered tests in sync over time.

Main entry points: [`testcase_manager/testcase_manager/api.py`](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/api.py) (API), [`frontend/src/api.js`](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/api.js) (API Client), [`frontend/src/router.js`](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/router.js) (Router), [`testcase_manager/testcase_manager/executor.py`](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/executor.py) (Python Executor)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend SPA"]
  node_browser_spa(("Browser SPA<br/>vue app<br/>[App.vue]"))
  node_runner_view["Runner<br/>page<br/>[RunnerView.vue]"]
  node_history_view["History<br/>page<br/>[HistoryView.vue]"]
  node_run_detail_view["Run Detail<br/>page<br/>[RunDetailView.vue]"]
  node_profiler_view["Profiler<br/>page<br/>[ProfilerView.vue]"]
  node_console["Console<br/>[Console.vue]"]
  node_api_client["API Client<br/>frontend api<br/>[api.js]"]
  node_socket_layer["Realtime Socket<br/>frontend realtime<br/>[socket.js]"]
  node_test_runner_hook["Run Hook<br/>frontend state<br/>[useTestRunner.js]"]
  node_router["Router<br/>spa routing<br/>[router.js]"]
end

subgraph group_backend["Frappe Backend"]
  node_api["API<br/>server endpoints<br/>[api.py]"]
  node_queries["Queries<br/>read model<br/>[queries.py]"]
  node_discovery["Python Discovery<br/>ast scanner<br/>[discovery.py]"]
  node_ui_discovery["UI Discovery<br/>spec scanner<br/>[ui_discovery.py]"]
  node_executor["Python Executor<br/>run engine<br/>[executor.py]"]
  node_ui_executor["UI Executor<br/>ui run job<br/>[ui_executor.py]"]
  node_impact["Impact Analysis<br/>diff analyzer<br/>[impact.py]"]
  node_profiling["Profiling<br/>profile runner<br/>[profiling.py]"]
  node_hooks["Hooks<br/>[hooks.py]"]
  node_site_entry["Site Entry<br/>frappe page"]
end

subgraph group_data["Persistence"]
  node_testcase_doc[("Testcase<br/>DocType<br/>[testcase.json]")]
  node_run_doc[("Testcase Run<br/>DocType<br/>[testcase_run.json]")]
  node_log_doc[("Testcase Log<br/>DocType<br/>[testcase_log.json]")]
end

node_browser_spa -->|"navigates"| node_router
node_browser_spa -->|"uses"| node_api_client
node_browser_spa -->|"subscribes"| node_socket_layer
node_router -->|"loads"| node_runner_view
node_router -->|"loads"| node_history_view
node_router -->|"loads"| node_run_detail_view
node_router -->|"loads"| node_profiler_view
node_runner_view -->|"requests"| node_api_client
node_history_view -->|"requests"| node_api_client
node_run_detail_view -->|"requests"| node_api_client
node_profiler_view -->|"requests"| node_api_client
node_api_client -->|"calls"| node_api
node_api -->|"reads via"| node_queries
node_api -->|"triggers"| node_discovery
node_api -->|"triggers"| node_executor
node_api -->|"triggers"| node_ui_executor
node_api -->|"uses"| node_impact
node_api -->|"uses"| node_profiling
node_api -->|"publishes"| node_socket_layer
node_socket_layer -->|"feeds"| node_console
node_executor -->|"writes"| node_run_doc
node_executor -->|"summarizes"| node_log_doc
node_executor -->|"consumes"| node_testcase_doc
node_ui_executor -->|"writes"| node_run_doc
node_ui_executor -->|"summarizes"| node_log_doc
node_ui_discovery -->|"populates"| node_testcase_doc
node_discovery -->|"populates"| node_testcase_doc
node_hooks -->|"schedules"| node_discovery
node_hooks -->|"routes"| node_site_entry
node_site_entry -->|"serves"| node_browser_spa
node_impact -->|"narrows selection"| node_executor
node_profiling -.->|"does not persist"| node_run_doc

click node_browser_spa "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/App.vue"
click node_runner_view "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/RunnerView.vue"
click node_history_view "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/HistoryView.vue"
click node_run_detail_view "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/RunDetailView.vue"
click node_profiler_view "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/ProfilerView.vue"
click node_console "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/components/Console.vue"
click node_api_client "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/api.js"
click node_socket_layer "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/socket.js"
click node_test_runner_hook "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/useTestRunner.js"
click node_router "https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/router.js"
click node_api "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/api.py"
click node_queries "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/queries.py"
click node_discovery "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/discovery.py"
click node_ui_discovery "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/ui_discovery.py"
click node_executor "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/executor.py"
click node_ui_executor "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/ui_executor.py"
click node_impact "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/impact.py"
click node_profiling "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/profiling.py"
click node_hooks "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/hooks.py"
click node_testcase_doc "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/doctype/testcase/testcase.json"
click node_run_doc "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/doctype/testcase_run/testcase_run.json"
click node_log_doc "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/doctype/testcase_log/testcase_log.json"
click node_site_entry "https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/www/testcase_manager.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_browser_spa,node_runner_view,node_history_view,node_run_detail_view,node_profiler_view,node_console,node_api_client,node_socket_layer,node_test_runner_hook,node_router toneBlue
class node_api,node_queries,node_discovery,node_ui_discovery,node_executor,node_ui_executor,node_impact,node_profiling,node_hooks,node_site_entry toneAmber
class node_testcase_doc,node_run_doc,node_log_doc toneMint
```

## Components

### Frontend SPA

Vue 3 single-page app and browser runtime

- [Browser SPA](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/App.vue): vue app · User-facing single-page test manager · `frontend/src/App.vue`
- [Runner](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/RunnerView.vue): page · Discover, filter, select, and launch tests · `frontend/src/pages/RunnerView.vue`
- [History](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/HistoryView.vue): page · Browse prior test runs · `frontend/src/pages/HistoryView.vue`
- [Run Detail](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/RunDetailView.vue): page · Inspect a saved run and its output · `frontend/src/pages/RunDetailView.vue`
- [Profiler](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/pages/ProfilerView.vue): page · Profile document actions from the UI · `frontend/src/pages/ProfilerView.vue`
- [Console](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/components/Console.vue): Live run output display · `frontend/src/components/Console.vue`
- [API Client](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/api.js): frontend api · SPA calls into whitelisted backend endpoints · `frontend/src/api.js`
- [Realtime Socket](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/socket.js): frontend realtime · Subscribes to live execution events · `frontend/src/socket.js`
- [Run Hook](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/useTestRunner.js): frontend state · Coordinates run state and output streaming · `frontend/src/useTestRunner.js`
- [Router](https://github.com/nihantra-patel/testcase_manager/blob/develop/frontend/src/router.js): spa routing · History-mode navigation for the app · `frontend/src/router.js`

### Frappe Backend

Server-side APIs, services, and hooks

- [API](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/api.py): server endpoints · Whitelisted endpoints consumed by the SPA · `testcase_manager/testcase_manager/api.py`
- [Queries](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/queries.py): read model · Listing and filtering helpers for the UI · `testcase_manager/testcase_manager/queries.py`
- [Python Discovery](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/discovery.py): ast scanner · Finds Python test methods and files without importing apps · `testcase_manager/testcase_manager/discovery.py`
- [UI Discovery](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/ui_discovery.py): spec scanner · Finds Cypress/UI specs using app conventions · `testcase_manager/testcase_manager/ui_discovery.py`
- [Python Executor](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/executor.py): run engine · Executes selected Python tests and manages run lifecycle · `testcase_manager/testcase_manager/executor.py`
- [UI Executor](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/ui_executor.py): ui run job · Runs UI tests asynchronously via bench run-ui-tests · `testcase_manager/testcase_manager/ui_executor.py`
- [Impact Analysis](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/impact.py): diff analyzer · Infers affected tests from git diff and import relationships · `testcase_manager/testcase_manager/impact.py`
- [Profiling](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/profiling.py): profile runner · Profiles document submit/cancel inside a rollback savepoint · `testcase_manager/testcase_manager/profiling.py`
- [Hooks](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/hooks.py): platform hooks · Wires routing, scheduler events, and log retention · `testcase_manager/hooks.py`
- [Site Entry](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/www/testcase_manager.py): frappe page · Bench-served entrypoint for the mounted app · `testcase_manager/www/testcase_manager.py`

### Persistence

DocTypes and stored run data

- [Testcase](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/doctype/testcase/testcase.json): DocType · Persistent record for one discovered test · `testcase_manager/testcase_manager/doctype/testcase/testcase.json`
- [Testcase Run](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/doctype/testcase_run/testcase_run.json): DocType · Persistent execution record with status, timing, and output · `testcase_manager/testcase_manager/doctype/testcase_run/testcase_run.json`
- [Testcase Log](https://github.com/nihantra-patel/testcase_manager/blob/develop/testcase_manager/testcase_manager/doctype/testcase_log/testcase_log.json): DocType · Persistent summary counts for a run · `testcase_manager/testcase_manager/doctype/testcase_log/testcase_log.json`

## Connections

- Browser SPA → Router: navigates · SPA routes between runner, history, detail, and profiler views
- Browser SPA → API Client: uses · Frontend issues data and execution requests through a thin client
- Browser SPA → Realtime Socket: subscribes · Browser listens for live run events and console updates
- Router → Runner: loads · Primary test selection and execution screen
- Router → History: loads · Past run listing screen
- Router → Run Detail: loads · Saved run inspection screen
- Router → Profiler: loads · Document profiling screen
- Runner → API Client: requests · Triggers discovery, filtering, and run actions
- History → API Client: requests · Fetches run history and summaries
- Run Detail → API Client: requests · Loads a single run record and related output
- Profiler → API Client: requests · Starts profiling operations and reads results
- API Client → API: calls · SPA consumes whitelisted backend endpoints
- API → Queries: reads via · List and filter endpoints are backed by query helpers
- API → Python Discovery: triggers · Endpoint surface can refresh discovered tests
- API → Python Executor: triggers · Launches Python test execution
- API → UI Executor: triggers · Launches UI test execution jobs
- API → Impact Analysis: uses · Supports narrowed batch selection from repository changes
- API → Profiling: uses · Exposes profiling workflow to the frontend
- API → Realtime Socket: publishes · Run progress is streamed over realtime events
- Realtime Socket → Console: feeds · Console renders live execution output
- Python Executor → Testcase Run: writes · Persists run status, timing, output, and traceback
- Python Executor → Testcase Log: summarizes · Updates run summary counts for history and listing
- Python Executor → Testcase: consumes · Executes selected discovered tests
- UI Executor → Testcase Run: writes · Persists UI execution record and streamed output
- UI Executor → Testcase Log: summarizes · Updates summary counts after UI runs
- UI Discovery → Testcase: populates · Adds UI-discovered test cases to the persistent catalog
- Python Discovery → Testcase: populates · Refreshes discovered Python tests into the catalog
- Hooks → Python Discovery: schedules · Migration and daily scheduler keep discovery in sync
- Hooks → Site Entry: routes · Maps SPA routes to the single HTML entrypoint
- Site Entry → Browser SPA: serves · Bench serves the built SPA from the Frappe app
- Impact Analysis → Python Executor: narrows selection · Feeds a candidate batch into the run engine
- Profiling → Testcase Run: does not persist · Profiles execute in rollback savepoints rather than stored runs
