testsAndMisc-archive/python_pkg/praca_magisterska_video/tests/test_gen_q9q12.py
Krzysztof kuhy Rudnicki 996617d4a0 test: achieve 100% branch coverage across all python_pkg packages
- Add comprehensive tests for all packages (3572 tests, 100% branch coverage)
- Split oversized test files to stay under 500-line limit
- Add per-file ruff ignores for test-appropriate suppressions
- Fix _cache_decks.py to properly convert JSON lists to tuples
- Add session-scoped conftest fixture for logging handler cleanup (Python 3.14)
- Update ruff pre-commit hook to v0.15.2
- Add codespell ignore words for test data
- Add generated output files to .gitignore
2026-03-21 17:51:36 +01:00

296 lines
8.5 KiB
Python

"""Tests for Q9/Q12 diagram generation (networking/optimization)."""
from __future__ import annotations
import matplotlib as mpl
import matplotlib.pyplot as plt
import pytest
@pytest.fixture(autouse=True)
def _patch_savefig(monkeypatch: pytest.MonkeyPatch) -> None:
"""Prevent matplotlib from writing files to disk."""
monkeypatch.setattr(mpl.figure.Figure, "savefig", lambda *_a, **_kw: None)
monkeypatch.setattr(plt, "savefig", lambda *_a, **_kw: None)
# =====================================================================
# _q9q12_common
# =====================================================================
class TestQ9Q12Common:
"""Tests for _q9q12_common constants and helpers."""
def test_constants_exist(self) -> None:
from _q9q12_common import (
_CENTER_Y,
_LAST_CONDITION_INDEX,
BG,
DPI,
FS,
FS_EDGE,
FS_SMALL,
FS_TITLE,
GRAY1,
LIGHT_BLUE,
LIGHT_GREEN,
LIGHT_ORANGE,
LIGHT_RED,
LIGHT_YELLOW,
LN,
OUTPUT_DIR,
)
assert DPI == 300
assert BG == "white"
assert LN == "black"
assert FS == 8
assert FS_TITLE == 11
assert _LAST_CONDITION_INDEX == 3
assert _CENTER_Y == 2.5
assert isinstance(FS_EDGE, int)
assert isinstance(FS_SMALL, float)
assert isinstance(GRAY1, str)
assert isinstance(LIGHT_GREEN, str)
assert isinstance(LIGHT_RED, str)
assert isinstance(LIGHT_BLUE, str)
assert isinstance(LIGHT_YELLOW, str)
assert isinstance(LIGHT_ORANGE, str)
assert isinstance(OUTPUT_DIR, str)
def test_draw_box_rounded(self) -> None:
from _q9q12_common import draw_box
fig, ax = plt.subplots()
draw_box(ax, 1.0, 2.0, 3.0, 1.0, "test")
assert len(ax.patches) == 1
plt.close(fig)
def test_draw_box_not_rounded(self) -> None:
from _q9q12_common import draw_box
fig, ax = plt.subplots()
draw_box(ax, 0.0, 0.0, 2.0, 1.0, "rect", rounded=False)
assert len(ax.patches) == 1
plt.close(fig)
def test_draw_box_custom_edgecolor(self) -> None:
from _q9q12_common import draw_box
fig, ax = plt.subplots()
draw_box(ax, 0.0, 0.0, 2.0, 1.0, "custom", edgecolor="red")
assert len(ax.patches) == 1
plt.close(fig)
def test_draw_arrow(self) -> None:
from _q9q12_common import draw_arrow
fig, ax = plt.subplots()
draw_arrow(ax, 0.0, 0.0, 1.0, 1.0)
plt.close(fig)
def test_save_fig(self) -> None:
from _q9q12_common import save_fig
fig, _ax = plt.subplots()
save_fig(fig, "test_q9q12.png")
def test_draw_network_node(self) -> None:
from _q9q12_common import draw_network_node
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
draw_network_node(ax, "A", (2.5, 2.5), color="white", fontsize=10, r=0.3)
assert len(ax.patches) == 1
plt.close(fig)
def test_draw_network_edge_directed(self) -> None:
from _q9q12_common import draw_network_edge
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
draw_network_edge(
ax,
(1.0, 1.0),
(4.0, 4.0),
label="10",
directed=True,
)
plt.close(fig)
def test_draw_network_edge_undirected(self) -> None:
from _q9q12_common import draw_network_edge
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
draw_network_edge(
ax,
(1.0, 1.0),
(4.0, 4.0),
label="5",
directed=False,
)
plt.close(fig)
def test_draw_network_edge_no_label(self) -> None:
from _q9q12_common import draw_network_edge
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
draw_network_edge(ax, (1.0, 1.0), (4.0, 4.0), label="")
plt.close(fig)
def test_draw_network_edge_zero_length(self) -> None:
from _q9q12_common import draw_network_edge
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
# Same start and end => length 0, should return early
draw_network_edge(ax, (2.0, 2.0), (2.0, 2.0), label="x")
plt.close(fig)
def test_draw_network_edge_with_offset(self) -> None:
from _q9q12_common import draw_network_edge
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
draw_network_edge(
ax,
(1.0, 1.0),
(4.0, 4.0),
label="off",
offset=0.5,
label_bg="#EEEEEE",
)
plt.close(fig)
# =====================================================================
# _q9q12_network_flow
# =====================================================================
class TestQ9Q12NetworkFlow:
"""Tests for network flow diagrams."""
def test_gen_ford_fulkerson(self) -> None:
from _q9q12_network_flow import gen_ford_fulkerson
gen_ford_fulkerson()
def test_gen_hungarian(self) -> None:
from _q9q12_network_flow import gen_hungarian
gen_hungarian()
def test_gen_min_cost_flow(self) -> None:
from _q9q12_network_flow import gen_min_cost_flow
gen_min_cost_flow()
# =====================================================================
# _q9q12_network_graph
# =====================================================================
class TestQ9Q12NetworkGraph:
"""Tests for network graph diagrams."""
def test_gen_cpm(self) -> None:
from _q9q12_network_graph import gen_cpm
gen_cpm()
def test_gen_kruskal(self) -> None:
from _q9q12_network_graph import gen_kruskal
gen_kruskal()
def test_gen_tsp(self) -> None:
from _q9q12_network_graph import gen_tsp
gen_tsp()
# =====================================================================
# _q9q12_processes
# =====================================================================
class TestQ9Q12Processes:
"""Tests for process diagrams (IPC, deadlock, producer-consumer)."""
def test_gen_ipc_mechanisms(self) -> None:
from _q9q12_processes import gen_ipc_mechanisms
gen_ipc_mechanisms()
def test_gen_deadlock_illustration(self) -> None:
from _q9q12_processes import gen_deadlock_illustration
gen_deadlock_illustration()
def test_gen_producer_consumer(self) -> None:
from _q9q12_processes import gen_producer_consumer
gen_producer_consumer()
def test_deadlock_coffman_conditions(self) -> None:
"""Verify all 4 Coffman conditions rendered, with last highlighted."""
from _q9q12_processes import gen_deadlock_illustration
gen_deadlock_illustration()
# =====================================================================
# generate_q9_q12_diagrams
# =====================================================================
class TestGenerateQ9Q12Diagrams:
"""Tests for the Q9/Q12 diagram generation entrypoint."""
def test_imports_work(self) -> None:
from generate_q9_q12_diagrams import (
gen_cpm,
gen_deadlock_illustration,
gen_ford_fulkerson,
gen_hungarian,
gen_ipc_mechanisms,
gen_kruskal,
gen_min_cost_flow,
gen_producer_consumer,
gen_tsp,
)
assert callable(gen_ford_fulkerson)
assert callable(gen_hungarian)
assert callable(gen_min_cost_flow)
assert callable(gen_cpm)
assert callable(gen_kruskal)
assert callable(gen_tsp)
assert callable(gen_ipc_mechanisms)
assert callable(gen_deadlock_illustration)
assert callable(gen_producer_consumer)
def test_all_generators_run(self) -> None:
from generate_q9_q12_diagrams import (
gen_cpm,
gen_deadlock_illustration,
gen_ford_fulkerson,
gen_hungarian,
gen_ipc_mechanisms,
gen_kruskal,
gen_min_cost_flow,
gen_producer_consumer,
gen_tsp,
)
gen_ipc_mechanisms()
gen_deadlock_illustration()
gen_producer_consumer()
gen_ford_fulkerson()
gen_hungarian()
gen_cpm()
gen_kruskal()
gen_tsp()
gen_min_cost_flow()