testsAndMisc/python_pkg/sql_drills/tests/test_check.py
Krzysztof kuhy Rudnicki ee78ae44cc
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Add sql_drills MySQL exact-match harness
Docker mysql:8.0.33 container, judge-style output grading, 12 original drills with live-verified references kept in tests only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzxdWZewj4WS5X6AZyjWDp
2026-11-01 21:13:18 +01:00

106 lines
3.3 KiB
Python

"""``run_check`` orchestration with the engine mocked."""
from __future__ import annotations
from pathlib import Path
from typing import Any
from unittest.mock import patch
import pytest
from python_pkg.sql_drills import _check, _drills, _engine
from python_pkg.sql_drills._engine import SqlResult
def _drill(tmp_path: Path, expected: str = "a 1\n") -> _drills.Drill:
(tmp_path / "DOCS-task.md").write_text("# T\n")
(tmp_path / "schema.sql").write_text("CREATE TABLE t (a INT);")
(tmp_path / "expected.txt").write_text(expected)
return _drills.Drill(
"09_x",
tmp_path / "DOCS-task.md",
tmp_path / "schema.sql",
tmp_path / "expected.txt",
)
def _query(tmp_path: Path) -> Path:
q = tmp_path / "q.sql"
q.write_text("SELECT 'a', 1;")
return q
def _patch_engine(*results: SqlResult, ready: bool = True) -> tuple[Any, Any]:
return (
patch.object(_engine, "is_ready", return_value=ready),
patch.object(_engine, "run_sql", side_effect=list(results)),
)
OK = SqlResult(0, "", "")
def test_pass(tmp_path: Path) -> None:
ready, run = _patch_engine(OK, OK, SqlResult(0, "a\t1\n", ""))
with ready, run as run_sql:
res = _check.run_check(_drill(tmp_path), _query(tmp_path))
assert res.status == "pass"
assert run_sql.call_args_list[0].args[0].startswith("DROP DATABASE IF EXISTS")
assert run_sql.call_args_list[2].kwargs["database"] == "drill_09_x"
def test_mismatch_includes_diff(tmp_path: Path) -> None:
ready, run = _patch_engine(OK, OK, SqlResult(0, "a\t2\n", ""))
with ready, run:
res = _check.run_check(_drill(tmp_path), _query(tmp_path))
assert res.status == "fail"
assert "expected: a 1" in res.message
assert "actual : a 2" in res.message
def test_sql_error_reports_stderr(tmp_path: Path) -> None:
ready, run = _patch_engine(OK, OK, SqlResult(1, "", "ERROR 1064: syntax"))
with ready, run:
res = _check.run_check(_drill(tmp_path), _query(tmp_path))
assert res.status == "error"
assert "ERROR 1064" in res.message
def test_not_ready_tells_user_to_start(tmp_path: Path) -> None:
ready, run = _patch_engine(ready=False)
with ready, run:
res = _check.run_check(_drill(tmp_path), _query(tmp_path))
assert res.status == "error"
assert "start" in res.message
def test_schema_failure_is_error(tmp_path: Path) -> None:
ready, run = _patch_engine(OK, SqlResult(1, "", "bad schema"))
with ready, run:
res = _check.run_check(_drill(tmp_path), _query(tmp_path))
assert res.status == "error"
assert "bad schema" in res.message
def test_reset_failure_is_error(tmp_path: Path) -> None:
ready, run = _patch_engine(SqlResult(1, "", "no perms"))
with ready, run:
res = _check.run_check(_drill(tmp_path), _query(tmp_path))
assert res.status == "error"
def test_missing_query_file(tmp_path: Path) -> None:
ready, run = _patch_engine()
with ready, run:
res = _check.run_check(_drill(tmp_path), tmp_path / "nope.sql")
assert res.status == "error"
assert "nope.sql" in res.message
def test_engine_error_propagates_to_cli(tmp_path: Path) -> None:
with (
patch.object(_engine, "is_ready", side_effect=_engine.EngineError("no docker")),
pytest.raises(_engine.EngineError),
):
_check.run_check(_drill(tmp_path), _query(tmp_path))