Option C Tools
Loading...
Searching...
No Matches
test_venv_warning.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_health/test_venv_warning.py
4
5"""
6Purpose
7-------
8FS-504 regression coverage — ``oct health`` must surface a prominent
9top-of-report banner when the operator runs the dashboard from outside
10a virtual environment. The banner is what upgrades "naked Python" from
11an easily-missed per-section ``[WARN]`` into something the operator
12cannot overlook before reading the rest of the report.
13
14The banner uses ``!`` as the rule character (70 columns) and carries
15the literal string "WARNING: not running inside a virtual environment.".
16
17Diagnostics
18-----------
19Domain: HEALTH-TESTS
20Levels:
21 L2 — test lifecycle
22
23Contracts
24---------
25- ``venv.active == False`` → banner rendered.
26- ``venv.active == True`` → banner absent (per-section [OK] still there).
27- Banner never appears in JSON output (machine-readable path unchanged).
28"""
29
30from __future__ import annotations
31
32import io
33import json
34from contextlib import redirect_stdout
35
36import pytest
37
38from oct.health.oct_health import _print_json_report, _print_terminal_report
39
40
41_BANNER_TEXT = "WARNING: not running inside a virtual environment."
42
43
44def _minimal_report(*, venv_active: bool) -> dict:
45 """Smallest ``report`` dict that satisfies ``_print_terminal_report``."""
46 return {
47 "project": "demo",
48 "oct_version": "0.17.0",
49 "timestamp": "2026-04-16T00:00:00",
50 "excluded_dirs": [],
51 "disabled_rules": [],
52 "lint": {
53 "total_files": 0,
54 "fully_compliant": 0,
55 "compliance_pct": 100.0,
56 "checks": {},
57 "files": [],
58 },
59 "fixable": {"total": 0},
60 "docs": {"total_present": 0, "total_required": 0, "files": []},
61 "tests": {"status": "skip", "summary": ""},
62 "compat": {
63 "installed": True, "compatible": True, "version": "0.0.0", "message": "",
64 },
65 "venv": {
66 "active": venv_active,
67 "venv_found": venv_active,
68 "own_venv": venv_active,
69 "status": "OK" if venv_active else "WARN",
70 "message": "Project .venv active" if venv_active else "No venv active.",
71 "venv_path": None,
72 },
73 "git": None,
74 }
75
76
77def _render(report: dict) -> str:
78 buf = io.StringIO()
79 with redirect_stdout(buf):
80 _print_terminal_report(report, verbose=False)
81 return buf.getvalue()
82
83
85 """FS-504: banner appears once and lands above the per-section summary."""
86 out = _render(_minimal_report(venv_active=False))
87 assert _BANNER_TEXT in out
88 banner_pos = out.index(_BANNER_TEXT)
89 # Banner precedes the per-section "Virtual Env:" line.
90 assert banner_pos < out.index("Virtual Env:")
91 # Exactly one banner occurrence.
92 assert out.count(_BANNER_TEXT) == 1
93
94
96 """FS-504: active venv → no banner; [OK] status still visible."""
97 out = _render(_minimal_report(venv_active=True))
98 assert _BANNER_TEXT not in out
99 assert "Virtual Env:" in out
100 assert "[OK]" in out
101
102
103def test_banner_absent_in_json_output(capsys: pytest.CaptureFixture):
104 """FS-504: JSON output is machine-readable — never gains a banner."""
105 _print_json_report(_minimal_report(venv_active=False))
106 captured = capsys.readouterr().out
107 parsed = json.loads(captured)
108 assert parsed["venv"]["active"] is False
109 assert _BANNER_TEXT not in captured
110
111
113 """FS-504: banner body mentions the exact ``python -m venv .venv`` remedy."""
114 out = _render(_minimal_report(venv_active=False))
115 assert "python -m venv .venv" in out
test_banner_absent_in_json_output(pytest.CaptureFixture capsys)
dict _minimal_report(*, bool venv_active)