Initial project structure for spice2wireviz
SPICE netlist to WireViz YAML converter with: - Custom lightweight netlist parser (.net/.cir/.sp) - Single-module mapper (subcircuit external interface) - Inter-module mapper (multi-board wiring) - Filter engine with glob patterns - Click CLI with auto-detection, inspection commands - Optional .asc parser via spicelib - Comprehensive test suite with fixtures
This commit is contained in:
commit
e20a956f51
24 changed files with 2630 additions and 0 deletions
130
tests/test_cli.py
Normal file
130
tests/test_cli.py
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
"""Tests for the Click CLI."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
from spice2wireviz.cli import main
|
||||
|
||||
FIXTURES = Path(__file__).parent / "fixtures"
|
||||
|
||||
|
||||
class TestCLIBasic:
|
||||
def test_version(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, ["--version"])
|
||||
assert result.exit_code == 0
|
||||
assert "2026-02-13" in result.output
|
||||
|
||||
def test_list_subcircuits(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [str(FIXTURES / "multi_board.net"), "--list-subcircuits"])
|
||||
assert result.exit_code == 0
|
||||
assert "power_supply" in result.output
|
||||
assert "amplifier" in result.output
|
||||
assert "io_board" in result.output
|
||||
|
||||
def test_list_components(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [str(FIXTURES / "multi_board.net"), "--list-components"])
|
||||
assert result.exit_code == 0
|
||||
assert "J_CHASSIS" in result.output
|
||||
assert "TP_VCC" in result.output
|
||||
|
||||
def test_nonexistent_file(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, ["/nonexistent/file.net"])
|
||||
assert result.exit_code != 0
|
||||
|
||||
|
||||
class TestCLISingleModule:
|
||||
def test_single_mode_explicit(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main,
|
||||
[str(FIXTURES / "simple_board.net"), "-m", "single", "-s", "amplifier_board"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "connectors:" in result.output
|
||||
assert "amplifier_board" in result.output
|
||||
|
||||
def test_single_mode_auto_detect(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main, [str(FIXTURES / "simple_board.net"), "-s", "amplifier_board"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "connectors:" in result.output
|
||||
|
||||
def test_single_mode_only_subcircuit(self):
|
||||
"""When netlist has one subcircuit and no instances, auto-detect single mode."""
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [str(FIXTURES / "simple_board.net")])
|
||||
assert result.exit_code == 0
|
||||
assert "connectors:" in result.output
|
||||
|
||||
def test_dry_run(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main,
|
||||
[str(FIXTURES / "simple_board.net"), "-s", "amplifier_board", "--dry-run"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Mode: single" in result.output
|
||||
assert "Connectors:" in result.output
|
||||
|
||||
|
||||
class TestCLIInterModule:
|
||||
def test_inter_mode_explicit(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main, [str(FIXTURES / "multi_board.net"), "-m", "inter"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "connectors:" in result.output
|
||||
assert "cables:" in result.output
|
||||
|
||||
def test_inter_mode_auto_detect(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [str(FIXTURES / "multi_board.net")])
|
||||
assert result.exit_code == 0
|
||||
assert "connectors:" in result.output
|
||||
|
||||
def test_output_to_file(self, tmp_path):
|
||||
out = tmp_path / "output.yml"
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main, [str(FIXTURES / "multi_board.net"), "-o", str(out)]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert out.exists()
|
||||
content = out.read_text()
|
||||
assert "connectors:" in content
|
||||
|
||||
|
||||
class TestCLIFiltering:
|
||||
def test_no_ground(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main, [str(FIXTURES / "multi_board.net"), "--no-ground"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
# GND should not appear in pinlabels
|
||||
assert "- GND" not in result.output
|
||||
|
||||
def test_include_prefixes(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main,
|
||||
[str(FIXTURES / "multi_board.net"), "--include-prefixes", "J"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_exclude_refs(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
main,
|
||||
[str(FIXTURES / "multi_board.net"), "--exclude-refs", "X1,TP_VCC"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "X1:" not in result.output
|
||||
Loading…
Add table
Add a link
Reference in a new issue