8000 test: comprehensive coverage for remaining modules (91%) by dominicusin · Pull Request #69 · dominicusin/package-maximizer · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions tests/test_benchmark.py
solver_name="greedy",
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"""Tests for utils.benchmark — BenchmarkRunner and BenchmarkReport."""

from __future__ import annotations

import pytest

from package_maximizer.utils.benchmark import BenchmarkRunner, BenchmarkResult, BenchmarkReport
from package_maximizer.core.package import Package


class TestBenchmarkResult:
"""BenchmarkResult dataclass."""

def test_creation(self):
result = BenchmarkResult(
solver_name="greedy",
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
)
assert result.solver_name == "greedy"
assert result.success is True
assert result.error is None


class TestBenchmarkReport:
"""BenchmarkReport methods."""

def test_add_result(self):
report = BenchmarkReport()
result = BenchmarkResult(
solver_name="greedy",
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
)
report.add_result(result)
assert len(report.results) == 1

def test_get_summary_empty(self):
report = BenchmarkReport()
summary = report.get_summary()
assert summary == {}

def test_get_summary_with_results(self):
report = BenchmarkReport()
report.add_result(BenchmarkResult(
solver_name="greedy",
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
))
report.add_result(BenchmarkResult(
solver_name="z3",
package_count=10,
conflict_count=2,
total_time=1.0,
avg_time=0.2,
min_time=0.1,
max_time=0.3,
selected_count=8,
success=True,
))
summary = report.get_summary()
assert summary["total_solvers"] == 2
assert summary["best_solver"] == "greedy"
assert summary["worst_solver"] == "z3"


class TestBenchmarkRunner:
"""BenchmarkRunner methods."""

def test_init_defaults(self):
runner = BenchmarkRunner()
assert runner.runs == 5
assert runner.time_limit == 10000

def test_init_custom(self):
runner = BenchmarkRunner(runs=3, time_limit=5000)
assert runner.runs == 3
assert runner.time_limit == 5000

def test_generate_test_packages(self):
runner = BenchmarkRunner()
pkgs = runner.generate_test_packages(10)
assert len(pkgs) == 10
assert all(isinstance(p, Package) for p in pkgs)

def test_generate_test_packages_with_conflicts(self):
runner = BenchmarkRunner()
pkgs = runner.generate_test_packages(20, conflict_probability=0.5)
assert len(pkgs) == 20
has_conflicts = any(p.conflicts for p in pkgs)
assert has_conflicts

def test_generate_test_packages_no_conflicts(self):
runner = BenchmarkRunner()
pkgs = runner.generate_test_packages(10, conflict_probability=0.0)
assert len(pkgs) == 10
assert all(not p.conflicts for p in pkgs)

def test_print_report(self):
runner = BenchmarkRunner(runs=1)
report = BenchmarkReport()
report.add_result(BenchmarkResult(
solver_name="greedy",
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
))
runner.print_report(report)

def test_print_full_report(self):
runner = BenchmarkRunner(runs=1)
reports = {10: BenchmarkReport()}
reports[10].add_result(BenchmarkResult(
solver_name="greedy",
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
))
runner.print_full_report(reports)

def test_export_report_json(self):
report = BenchmarkReport()
report.add_result(BenchmarkResult(
solver_name="greedy",
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
))
result = BenchmarkRunner.export_report(report, format="json")
assert isinstance(result, str)
assert "greedy" in result

def test_export_report_csv(self):
report = BenchmarkReport()
report.add_result(BenchmarkResult(
package_count=10,
conflict_count=2,
total_time=0.5,
avg_time=0.1,
min_time=0.05,
max_time=0.15,
selected_count=8,
success=True,
))
result = BenchmarkRunner.export_report(report, format="csv")
assert isinstance(result, str)
150 changes: 150 additions & 0 deletions tests/test_brew_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"""Tests for parsers.brew_parser — Homebrew package parser."""

from __future__ import annotations

import pytest
from unittest.mock import patch, MagicMock

from package_maximizer.parsers.brew_parser import BrewParser
from package_maximizer.core.package import Package


class TestBrewParserParse:
"""parse method with different formats."""

def test_parse_empty_string(self):
parser = BrewParser()
result = parser.parse("")
assert result == []

def test_parse_brew_list_format(self):
parser = BrewParser()
raw = "==> Formulae\nvim\nwget\npython@3.11\n==> Casks\nfirefox\ngoogle-chrome\n"
result = parser.parse(raw)
names = {p.name for p in result}
assert "vim" in names
assert "firefox" in names

def test_parse_brew_info_format(self):
parser = BrewParser()
raw = """vim:
Version: 9.1.0000
From: https://github.com/vim/vim
Dependencies: python@3.11, ncurses
Conflicts with: vim-tiny
Installed: YES
"""
result = parser.parse(raw)
assert len(result) >= 1
assert result[0].name == "vim"

def test_parse_simple_list(self):
parser = BrewParser()
raw = "vim\nwget\ncurl\n"
result = parser.parse(raw)
names = {p.name for p in result}
assert "vim" in names
assert "wget" in names
assert "curl" in names

def test_parse_info_multiple_packages(self):
parser = BrewParser()
raw = """vim:
Version: 9.1.0000
From: https://github.com/vim/vim
Installed: YES

wget:
Version: 1.21.0
From: https://ftp.gnu.org/gnu/wget/
Installed: NO
"""
result = parser.parse(raw)
assert len(result) == 2
names = {p.name for p in result}
assert "vim" in names
assert "wget" in names

def test_parse_info_with_dependencies(self):
parser = BrewParser()
raw = """vim:
Version: 9.1.0000
From: https://github.com/vim/vim
Dependencies: python@3.11, ncurses
"""
result = parser.parse(raw)
assert len(result) == 1
assert result[0].depends == ["python@3.11", "ncurses"]

def test_parse_info_with_conflicts(self):
parser = BrewParser()
raw = """vim:
Version: 9.1.0000
From: https://github.com/vim/vim
Conflicts with: vim-tiny, gvim
"""
result = parser.parse(raw)
assert len(result) == 1
assert result[0].conflicts == ["vim-tiny", "gvim"]

def test_parse_info_with_installed_status(self):
parser = BrewParser()
raw = """vim:
Version: 9.1.0000
From: https://github.com/vim/vim
Installed: YES
"""
result = parser.parse(raw)
assert len(result) == 1
assert result[0].status == "installed"


class TestBrewParserParseFromSystem:
"""parse_from_system method."""

def test_parse_from_system_all_installed(self):
parser = BrewParser()
mock_result = MagicMock()
mock_result.returncode = 0
mock_result.stdout = "==> Formulae\nvim\nwget\n"

with patch("subprocess.run", return_value=mock_result) as mock_run:
result = parser.parse_from_system()
mock_run.assert_called_once()
assert len(result) == 2

def test_parse_from_system_specific_packages(self):
parser = BrewParser()
mock_result = MagicMock()
mock_result.returncode = 0
mock_result.stdout = "vim:\nVersion: 9.1.0000\nFrom: https://github.com/vim/vim\n"

with patch("subprocess.run", return_value=mock_result):
result = parser.parse_from_system(["vim"])
assert len(result) >= 1

def test_parse_from_system_subprocess_fails(self):
parser = BrewParser()
mock_result = MagicMock()
mock_result.returncode = 1
mock_result.stderr = "Error"

with patch("subprocess.run", return_value=mock_result):
result = parser.parse_from_system(["vim"])
assert len(result) == 1
assert result[0].status == "candidate"

def test_parse_from_system_timeout(self):
parser = BrewParser()
import subprocess

with patch("subprocess.run", side_effect=subprocess.TimeoutExpired(cmd="brew", timeout=30)):
result = parser.parse_from_system()
assert result == []

def test_parse_from_system_file_not_found(self):
parser = BrewParser()

with patch("subprocess.run", side_effect=FileNotFoundError("brew not found")):
result = parser.parse_from_system()
assert result == []
Loading
Loading
0