6c9c7fe7f3
CI / integration tests (3.13) (push) Failing after 1s
Commit lint / pull request title (push) Has been skipped
Docs / links (push) Failing after 1s
CI / unit tests (3.13) (push) Failing after 1s
CI / lint (push) Failing after 1s
CI / integration tests (push) Failing after 1s
CI / package build (push) Failing after 1s
Commit lint / commit messages (push) Failing after 1s
CI / unit tests (push) Failing after 1s
164 lines
4.4 KiB
Python
164 lines
4.4 KiB
Python
"""Unit tests for BenchmarkConfig loading."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
def test_defaults_construct_without_error() -> None:
|
|
"""BenchmarkConfig() with defaults must construct and have all fields."""
|
|
from benchmarks.config import BenchmarkConfig
|
|
|
|
cfg = BenchmarkConfig()
|
|
assert isinstance(cfg.methods, str)
|
|
assert cfg.top_k > 0
|
|
assert cfg.cascade_timeout > 0
|
|
assert cfg.batch_size > 0
|
|
assert isinstance(cfg.answer_model, str)
|
|
assert isinstance(cfg.judge_model, str)
|
|
assert cfg.judge_runs >= 1
|
|
assert cfg.conversations_concurrency >= 1
|
|
assert cfg.eval_concurrency >= 1
|
|
assert cfg.search_concurrency >= 1
|
|
|
|
|
|
def test_from_toml_loads_default_config() -> None:
|
|
"""from_toml('config') loads benchmarks/config.toml successfully."""
|
|
from benchmarks.config import BenchmarkConfig
|
|
|
|
cfg = BenchmarkConfig.from_toml("config")
|
|
assert isinstance(cfg.methods, str)
|
|
assert isinstance(cfg.judge_model, str)
|
|
|
|
|
|
def test_from_toml_override(tmp_path: Path) -> None:
|
|
"""A custom TOML overrides specific fields, rest stay default."""
|
|
from benchmarks.config import BenchmarkConfig
|
|
|
|
(tmp_path / "custom.toml").write_text(
|
|
'methods = "hybrid"\ntop_k = 20\n', encoding="utf-8"
|
|
)
|
|
cfg = BenchmarkConfig.from_toml("custom", config_dir=tmp_path)
|
|
assert cfg.methods == "hybrid"
|
|
assert cfg.top_k == 20
|
|
assert cfg.judge_model == "gpt-4o-mini" # untouched
|
|
|
|
|
|
def test_from_toml_missing_file_raises() -> None:
|
|
"""from_toml with nonexistent name raises FileNotFoundError."""
|
|
from benchmarks.config import BenchmarkConfig
|
|
|
|
with pytest.raises(FileNotFoundError):
|
|
BenchmarkConfig.from_toml("nonexistent")
|
|
|
|
|
|
def test_frozen_model() -> None:
|
|
"""BenchmarkConfig instances are immutable."""
|
|
from benchmarks.config import BenchmarkConfig
|
|
|
|
cfg = BenchmarkConfig()
|
|
with pytest.raises(Exception): # noqa: B017 — ValidationError
|
|
cfg.top_k = 999
|
|
|
|
|
|
def test_concurrency_fields_exist() -> None:
|
|
"""Concurrency fields exist and are positive; no legacy 'concurrency' attr."""
|
|
from benchmarks.config import BenchmarkConfig
|
|
|
|
cfg = BenchmarkConfig()
|
|
assert cfg.conversations_concurrency >= 1
|
|
assert cfg.eval_concurrency >= 1
|
|
assert cfg.search_concurrency >= 1
|
|
assert not hasattr(cfg, "concurrency")
|
|
|
|
|
|
def test_search_result_frozen() -> None:
|
|
from benchmarks.config import SearchResult
|
|
|
|
sr = SearchResult(
|
|
index=0,
|
|
question="q",
|
|
golden_answer="a",
|
|
category=1,
|
|
evidence=[],
|
|
episodes=[],
|
|
profiles=[],
|
|
search_time_s=0.5,
|
|
method="agentic",
|
|
)
|
|
assert sr.index == 0
|
|
with pytest.raises(Exception): # noqa: B017
|
|
sr.index = 99
|
|
|
|
|
|
def test_search_result_jsonl_roundtrip() -> None:
|
|
from benchmarks.config import SearchResult
|
|
|
|
sr = SearchResult(
|
|
index=0,
|
|
question="q",
|
|
golden_answer="a",
|
|
category=1,
|
|
evidence=["e1"],
|
|
episodes=[{"id": "ep1"}],
|
|
profiles=[],
|
|
search_time_s=0.5,
|
|
method="agentic",
|
|
)
|
|
line = sr.model_dump_json()
|
|
restored = SearchResult.model_validate_json(line)
|
|
assert restored == sr
|
|
|
|
|
|
def test_answer_result_tracks_tokens() -> None:
|
|
from benchmarks.config import AnswerResult
|
|
|
|
ar = AnswerResult(
|
|
index=0,
|
|
question="q",
|
|
golden_answer="a",
|
|
category=1,
|
|
generated_answer="ans",
|
|
answer_time_s=1.0,
|
|
answer_attempts=1,
|
|
answer_tokens=500,
|
|
)
|
|
assert ar.answer_tokens == 500
|
|
|
|
|
|
def test_judge_result_jsonl_roundtrip() -> None:
|
|
from benchmarks.config import JudgeResult
|
|
|
|
jr = JudgeResult(
|
|
index=0,
|
|
question="q",
|
|
golden_answer="a",
|
|
generated_answer="ans",
|
|
category=1,
|
|
is_correct=True,
|
|
judgments=[True, True, False],
|
|
judge_tokens=200,
|
|
)
|
|
line = jr.model_dump_json()
|
|
restored = JudgeResult.model_validate_json(line)
|
|
assert restored == jr
|
|
assert restored.is_correct is True
|
|
|
|
|
|
def test_run_spec_includes_git_hash() -> None:
|
|
from benchmarks.config import RunSpec
|
|
|
|
spec = RunSpec(
|
|
run_name="v1",
|
|
config={},
|
|
conversations=[0, 1],
|
|
stages=["add", "search"],
|
|
git_hash="abc1234",
|
|
python_version="3.12.11",
|
|
everos_version="1.1.0",
|
|
started_at="2026-06-28T22:30:00Z",
|
|
)
|
|
assert spec.git_hash == "abc1234"
|