SignalWire

 view release on metacpan or  search on metacpan

porting-sdk/tests/audit_coverage_smoke.py  view on Meta::CPAN



def test_known_covered_symbol_in_covered_list() -> None:
    """``RestClient.__init__`` is covered by every conftest.py and many
    direct constructor tests.  If this is ever uncovered, the audit's
    constructor-tracking is broken."""
    target = "signalwire.rest.client.RestClient.__init__"
    entry = COVERAGE.get(target)
    assert entry is not None, f"{target} is not in the symbol index"
    assert entry.status() == "covered", (
        f"{target} expected covered but got {entry.status()}"
    )

    # And another: CallingNamespace.dial is exercised by an
    # ``assert_called_with`` style test.
    dial = COVERAGE["signalwire.rest.namespaces.calling.CallingNamespace.dial"]
    assert dial.status() == "covered", dial.status()


# ---------------------------------------------------------------------------
# Test 4: module summary counts add up
# ---------------------------------------------------------------------------


def test_module_summary_counts_add_up() -> None:
    """For every module the per-status totals must sum to the total
    symbol count for that module."""
    by_module: dict[str, list] = defaultdict(list)
    for entry in COVERAGE.values():
        by_module[entry.module].append(entry)

    for module, entries in by_module.items():
        c = sum(1 for e in entries if e.status() == "covered")
        p = sum(1 for e in entries if e.status() == "partial")
        u = sum(1 for e in entries if e.status() == "uncovered")
        assert c + p + u == len(entries), (
            f"{module}: covered+partial+uncovered != total "
            f"({c}+{p}+{u} != {len(entries)})"
        )


# ---------------------------------------------------------------------------
# Test 5: the audit covers all the target modules listed in the spec
# ---------------------------------------------------------------------------


def test_target_modules_present() -> None:
    """Spec calls out specific modules: each must appear in the audit."""
    modules = {entry.module for entry in COVERAGE.values()}
    required = {
        "signalwire.rest._base",
        "signalwire.rest.client",
        "signalwire.rest.namespaces.calling",
        "signalwire.rest.namespaces.fabric",
        "signalwire.rest.namespaces.phone_numbers",
        "signalwire.relay.client",
        "signalwire.relay.call",
        "signalwire.relay.message",
        "signalwire.relay.event",
    }
    missing = required - modules
    assert not missing, f"audit missing target modules: {sorted(missing)}"


# ---------------------------------------------------------------------------
# Test 6: report renders without error
# ---------------------------------------------------------------------------


def test_render_report_produces_markdown() -> None:
    md = audit.render_report(COVERAGE, SCAN, LOG)
    assert md.startswith("# Python Test Coverage"), md.splitlines()[0]
    # Summary table present
    assert "| Module | Symbols | Covered | Partial | Uncovered |" in md
    # At least one section heading per module of interest
    for mod in (
        "signalwire.rest.namespaces.calling",
        "signalwire.relay.call",
        "signalwire.rest._base",
    ):
        assert f"## {mod}" in md, f"missing section for {mod}"


# ---------------------------------------------------------------------------
# Test 7: action wait/result methods on relay calls — should be partially
# or fully covered (test_call.py exercises action.wait)
# ---------------------------------------------------------------------------


def test_play_action_wait_is_covered() -> None:
    """``action.wait()`` is hit at tests/unit/relay/test_call.py:641; this
    confirms the fixture-return inference works (call -> Call -> PlayAction)."""
    entry = COVERAGE["signalwire.relay.call.PlayAction.wait"]
    # Inherits from Action; either covered or covered-via-inheritance is fine.
    assert entry.status() == "covered", (
        f"PlayAction.wait expected covered, got {entry.status()}; "
        f"asserted={entry.asserted!r}"
    )


# ---------------------------------------------------------------------------
# Test 8: integration tests are excluded
# ---------------------------------------------------------------------------


def test_integration_tests_excluded() -> None:
    """No site recorded should reference tests/integration/."""
    for entry in COVERAGE.values():
        for site in (*entry.asserted, *entry.touched, *entry.referenced_only):
            assert "/integration/" not in str(site.file), (
                f"integration test leaked into {entry.qualname}: {site.file}"
            )


def test_audit_handles_unparseable_test_file(tmp_path_factory=None) -> None:
    """The audit must not crash if a test file has a SyntaxError; the spec
    says it should "skip + log, don't crash"."""
    import tempfile
    import shutil

    # Build a tiny replica with a deliberately broken test file.



( run in 0.842 second using v1.01-cache-2.11-cpan-71847e10f99 )