feat(ack): bind test env to deployer and add regression mode
ACK 0.19.0 hands test-environment deploys to the deployer skill, documents bug-fix as a first-class scenario, and adds docs/ack/regression.yaml harvest plus a /ack regression run.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
SCRIPTS_DIR = REPO_ROOT / "skills" / "ack" / "scripts"
|
||||
VALIDATOR = SCRIPTS_DIR / "validate_regression.py"
|
||||
SELECTOR = SCRIPTS_DIR / "select_regression.py"
|
||||
EXAMPLE = REPO_ROOT / "skills" / "ack" / "examples" / "regression.example.yaml"
|
||||
sys.path.insert(0, str(SCRIPTS_DIR))
|
||||
|
||||
import select_regression # noqa: E402
|
||||
import validate_regression # noqa: E402
|
||||
|
||||
|
||||
def empty_catalog() -> dict:
|
||||
return {
|
||||
"version": 1,
|
||||
"updatedAt": "2026-08-25T10:00:00+08:00",
|
||||
"project": {"name": "demo"},
|
||||
"cases": [],
|
||||
}
|
||||
|
||||
|
||||
def sample_case(**overrides: object) -> dict:
|
||||
case = {
|
||||
"id": "REG-login-001",
|
||||
"title": "登录后进入工作台",
|
||||
"status": "active",
|
||||
"source": {"taskId": "BUG-001", "kind": "bug"},
|
||||
"suite": "smoke",
|
||||
"surface": "browser",
|
||||
"setup": "使用测试账号 A,未登录",
|
||||
"steps": ["打开 /login", "输入账号 A 并提交"],
|
||||
"expected": [
|
||||
{"kind": "visible-text", "value": "工作台"},
|
||||
{"kind": "url", "value": "/dashboard"},
|
||||
],
|
||||
}
|
||||
case.update(overrides)
|
||||
return case
|
||||
|
||||
|
||||
class AckRegressionValidationTests(unittest.TestCase):
|
||||
def test_example_and_template_are_valid(self) -> None:
|
||||
for no_site_packages in (False, True):
|
||||
command = [sys.executable]
|
||||
if no_site_packages:
|
||||
command.append("-S")
|
||||
result = subprocess.run(
|
||||
[*command, str(VALIDATOR), str(EXAMPLE)],
|
||||
cwd=REPO_ROOT,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
with self.subTest(no_site_packages=no_site_packages):
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("回归目录校验通过", result.stdout)
|
||||
|
||||
template = REPO_ROOT / "skills" / "ack" / "templates" / "regression.template.yaml"
|
||||
rendered = template.read_text(encoding="utf-8").replace(
|
||||
"<project_name>", "demo"
|
||||
).replace("<YYYY-MM-DDTHH:mm:ss+TZ>", "2026-08-25T10:00:00+08:00")
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
path = Path(temp_dir) / "regression.yaml"
|
||||
path.write_text(rendered, encoding="utf-8")
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(VALIDATOR), str(path)],
|
||||
cwd=REPO_ROOT,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
|
||||
def test_rejects_duplicate_ids_and_unknown_fields(self) -> None:
|
||||
catalog = empty_catalog()
|
||||
catalog["cases"] = [sample_case(), sample_case()]
|
||||
errors = validate_regression.validate_builtin(catalog)
|
||||
self.assertTrue(any("不能重复" in item for item in errors))
|
||||
|
||||
catalog["cases"] = [sample_case(extra="nope")]
|
||||
errors = validate_regression.validate_builtin(catalog)
|
||||
self.assertTrue(any("未知字段" in item for item in errors))
|
||||
|
||||
def test_selects_smoke_by_default_and_full_includes_all_active(self) -> None:
|
||||
catalog = empty_catalog()
|
||||
catalog["cases"] = [
|
||||
sample_case(),
|
||||
sample_case(
|
||||
id="REG-notes-create-001",
|
||||
suite="full",
|
||||
surface="api",
|
||||
source={"taskId": "FEAT-012", "kind": "feature"},
|
||||
),
|
||||
sample_case(id="REG-old-001", status="retired"),
|
||||
]
|
||||
smoke = select_regression.select_cases(
|
||||
catalog, suite="smoke", case_ids=[], limit=50
|
||||
)
|
||||
full = select_regression.select_cases(
|
||||
catalog, suite="full", case_ids=[], limit=50
|
||||
)
|
||||
self.assertEqual([case["id"] for case in smoke], ["REG-login-001"])
|
||||
self.assertEqual(
|
||||
[case["id"] for case in full],
|
||||
["REG-login-001", "REG-notes-create-001"],
|
||||
)
|
||||
|
||||
def test_selector_cli_and_task_link(self) -> None:
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(SELECTOR), str(EXAMPLE), "--format", "ids"],
|
||||
cwd=REPO_ROOT,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(result.stdout.strip(), "REG-login-001")
|
||||
|
||||
tasks = {
|
||||
"project": {
|
||||
"name": "notes-web",
|
||||
"regressionFile": "docs/ack/regression.yaml",
|
||||
},
|
||||
"regressionRuns": [],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "BUG-001",
|
||||
"regressionRefs": ["REG-login-001"],
|
||||
}
|
||||
],
|
||||
}
|
||||
catalog = validate_regression.load_yaml(EXAMPLE, "回归目录")
|
||||
self.assertEqual(validate_regression.validate_tasks_link(catalog, tasks), [])
|
||||
|
||||
tasks["project"]["regressionFile"] = "docs/ack/other.yaml"
|
||||
errors = validate_regression.validate_tasks_link(catalog, tasks)
|
||||
self.assertTrue(any("必须固定为 docs/ack/regression.yaml" in item for item in errors))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user