Files
JWeBot/tests/test_release_064.py
2026-10-15 18:08:55 +08:00

189 lines
6.7 KiB
Python

"""Behavioral coverage for the CS Major autochess 0.6.6 flow."""
from __future__ import annotations
import json
import tempfile
import unittest
from pathlib import Path
from test_jwebot_edge import MODULE, config
from jwebot_official_extensions import cs_autochess as AUTOCHESS
class Release064AutochessTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.engine = MODULE.EdgeApplication(config(Path(self.temp.name)))
self.counter = 0
def tearDown(self):
self.engine.close()
self.temp.cleanup()
def command(self, question, *, sender="Alice", event_id=None):
self.counter += 1
response = self.engine.accept(
{
"event_id": event_id or f"autochess-{self.counter}",
"group_fingerprint": "group-a",
"sender": sender,
"text": "@JWeBot " + question,
"mention_bot": True,
"confidence": 1.0,
"sender_confidence": 1.0,
"body_confidence": 1.0,
}
)
self.assertEqual(response["status"], "reply")
return list(response.get("texts") or [response["text"]])
def state(self):
row = self.engine.ledger.connection.execute(
"""
SELECT state_json FROM autochess_runs
WHERE group_fingerprint = 'group-a'
ORDER BY season_number DESC
LIMIT 1
"""
).fetchone()
self.assertIsNotNone(row)
return json.loads(row[0])
def start_two_human_two_ai(self):
self.command("/自走棋开始")
self.command("/自走棋报名", sender="Bob")
self.command("/自走棋加AI战队")
return self.command("/自走棋开赛")
def finish_draft(self):
self.command("/选1")
self.command("/选1", sender="Bob")
self.command("/选1", sender="Bob")
self.command("/选1")
self.command("/选1")
return self.command("/选1", sender="Bob")
def ready_all(self):
state = self.state()
replies = []
for key in list(state.get("ready_keys") or []):
replies.extend(
self.command(
"/结束回合",
sender=state["players"][key]["display_name"],
)
)
return replies
def test_static_pool_parser_and_coach_pool(self):
self.assertGreaterEqual(len(AUTOCHESS.PLAYER_POOL), 100)
self.assertEqual(
len({card["id"] for card in AUTOCHESS.PLAYER_POOL}),
len(AUTOCHESS.PLAYER_POOL),
)
self.assertGreaterEqual(len(AUTOCHESS.COACH_POOL), 18)
self.assertEqual(
len({coach["id"] for coach in AUTOCHESS.COACH_POOL}),
len(AUTOCHESS.COACH_POOL),
)
self.assertEqual(
AUTOCHESS.parse_autochess_action("/自走棋开始"),
("create", ""),
)
self.assertEqual(
AUTOCHESS.parse_autochess_action("/选6"),
("buy", "6"),
)
self.assertEqual(
AUTOCHESS.parse_autochess_action("/战术残局"),
("tactic", "残局"),
)
def test_launch_starts_multimessage_coach_draft_not_full_rosters(self):
response = self.start_two_human_two_ai()
state = self.state()
self.assertGreaterEqual(len(response), 5)
self.assertIn("第一轮选秀", "\n".join(response))
self.assertIn("1. zonic", "\n".join(response))
self.assertEqual(state["phase"], "draft_coach_1")
self.assertEqual(state["ai_test_variant"], "two_plus_two")
self.assertEqual(
state["seed_order"][2:],
[AUTOCHESS.AI_PERSON_KEY, AUTOCHESS.AI_SECOND_PERSON_KEY],
)
for player in state["players"].values():
self.assertEqual(player["board"], [])
self.assertEqual(player["coach_id"], "")
def test_three_round_draft_training_rounds_and_group_intro(self):
self.start_two_human_two_ai()
final_draft = self.finish_draft()
state = self.state()
self.assertIn("三轮选秀结束", "\n".join(final_draft))
self.assertEqual(state["phase"], "lineup_prep")
for player in state["players"].values():
self.assertEqual(len(player["board"]), 5)
self.assertEqual(len(player["bench"]), 3)
self.assertTrue(player["coach_id"])
training = self.ready_all()
training_text = "\n".join(training)
self.assertIn("训练赛第 1/3 轮", training_text)
self.assertIn("Team", training_text)
self.assertNotIn("目标", training_text)
self.assertNotIn("发挥", training_text)
self.assertEqual(self.state()["phase"], "training_manage")
round_two = "\n".join(self.ready_all())
self.assertIn("训练赛第 2/3 轮", round_two)
round_three = "\n".join(self.ready_all())
self.assertIn("训练赛第 3/3 轮", round_three)
self.assertEqual(self.state()["phase"], "training_complete_manage")
group = self.ready_all()
self.assertIn("正赛小组赛", "\n".join(group))
state = self.state()
self.assertEqual(state["phase"], "group_ready")
self.assertEqual(len(state["group_matches"]), 6)
def test_full_tournament_completes_and_only_active_playoff_players_ready(self):
self.start_two_human_two_ai()
self.finish_draft()
seen_playoff_prompt = False
for _ in range(80):
state = self.state()
if state["status"] == "completed":
break
ready_keys = list(state.get("ready_keys") or [])
self.assertTrue(ready_keys, state["phase"])
if state["phase"] in {"semifinal_ready", "final_ready"}:
pair = set(state["current_match"]["pair"])
self.assertEqual(set(ready_keys), pair & set(AUTOCHESS._human_keys(state)))
seen_playoff_prompt = True
self.ready_all()
else:
self.fail("tournament did not complete")
state = self.state()
self.assertTrue(seen_playoff_prompt)
self.assertEqual(state["status"], "completed")
self.assertEqual(state["phase"], "completed")
self.assertTrue(state["champion_key"])
def test_multimessage_response_replays_identically(self):
self.command("/自走棋开始")
self.command("/自走棋报名", sender="Bob")
self.command("/自走棋加AI战队")
first = self.command("/自走棋开赛", event_id="same-launch")
replay = self.command("/自走棋开赛", event_id="same-launch")
self.assertEqual(first, replay)
self.assertGreater(len(first), 1)
if __name__ == "__main__":
unittest.main()