add tests #7
@@ -4,7 +4,7 @@
|
||||
|
||||
## 文件结构
|
||||
|
||||
程序主要分为两部分,游戏主体和分析工具
|
||||
程序主要分为三部分,游戏主体、分析工具和测试。
|
||||
|
||||
### 游戏主体
|
||||
|
||||
@@ -26,6 +26,30 @@
|
||||
|
||||
`json_convert.py` 用于将json游戏记录转为可读文本
|
||||
|
||||
### 测试
|
||||
|
||||
所有的测试位于`test`文件夹中
|
||||
|
||||
运行前先安装
|
||||
|
||||
```bash
|
||||
pip install -r ./test/requirements.txt
|
||||
```
|
||||
|
||||
运行全部测试:
|
||||
|
||||
```bash
|
||||
|
||||
pytest tests/ -v --cov=.
|
||||
|
||||
```
|
||||
|
||||
生成HTML报告:
|
||||
|
||||
```bash
|
||||
pytest --cov=. --cov-report=html
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
使用conda环境配置相应依赖包:
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_llm_calls(monkeypatch):
|
||||
"""Mock all LLM API calls"""
|
||||
def mock_chat(*args, **kwargs):
|
||||
return ("mocked response", "")
|
||||
|
||||
monkeypatch.setattr("llm_client.LLMClient.chat", mock_chat)
|
||||
@@ -0,0 +1,2 @@
|
||||
pytest>=7.0
|
||||
pytest-cov>=4.0
|
||||
@@ -0,0 +1,23 @@
|
||||
import pytest
|
||||
from game import Game
|
||||
from player import Player
|
||||
|
||||
@pytest.fixture
|
||||
def sample_game():
|
||||
return Game([
|
||||
{"name": "P1", "model": "m1"},
|
||||
{"name": "P2", "model": "m2"}
|
||||
])
|
||||
|
||||
def test_game_initialization(sample_game):
|
||||
assert len(sample_game.players) == 2
|
||||
assert sample_game.game_record is not None
|
||||
assert sample_game.deck == []
|
||||
|
||||
def test_handle_system_challenge(sample_game, mocker):
|
||||
mocker.patch.object(sample_game, 'check_other_players_no_cards', return_value=True)
|
||||
current_player = sample_game.players[0]
|
||||
current_player.hand = ["A", "B"]
|
||||
|
||||
sample_game.handle_system_challenge(current_player)
|
||||
assert len(current_player.hand) == 0
|
||||
@@ -0,0 +1,32 @@
|
||||
import pytest
|
||||
import tempfile
|
||||
import json
|
||||
import os
|
||||
from game_analyze import analyze_game_records
|
||||
|
||||
@pytest.fixture
|
||||
def sample_game_data():
|
||||
return {
|
||||
"winner": "PlayerA",
|
||||
"rounds": [{
|
||||
"play_history": [{
|
||||
"player_name": "PlayerA",
|
||||
"next_player": "PlayerB",
|
||||
"was_challenged": True,
|
||||
"challenge_result": True
|
||||
}],
|
||||
"round_result": {
|
||||
"shooter_name": "PlayerA",
|
||||
"bullet_hit": True
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
def test_analysis_calculation(sample_game_data):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
with open(os.path.join(tmpdir, "test.json"), 'w') as f:
|
||||
json.dump(sample_game_data, f)
|
||||
|
||||
stats = analyze_game_records(tmpdir)
|
||||
assert stats['wins']['PlayerA'] == 1
|
||||
assert stats['shots_fired']['PlayerA'] == 1
|
||||
@@ -0,0 +1,37 @@
|
||||
import pytest
|
||||
import tempfile
|
||||
import json
|
||||
import os
|
||||
from json_convert import process_game_records
|
||||
|
||||
@pytest.fixture
|
||||
def sample_json_game():
|
||||
return {
|
||||
"game_id": "TEST123",
|
||||
"rounds": [{
|
||||
"target_card": "A",
|
||||
"play_history": [{
|
||||
"player_name": "P1",
|
||||
"played_cards": ["A"],
|
||||
"remaining_cards": []
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
def test_json_conversion(sample_json_game):
|
||||
with tempfile.TemporaryDirectory() as input_dir, \
|
||||
tempfile.TemporaryDirectory() as output_dir:
|
||||
|
||||
# Create test input
|
||||
input_path = os.path.join(input_dir, "test.json")
|
||||
with open(input_path, 'w') as f:
|
||||
json.dump(sample_json_game, f)
|
||||
|
||||
process_game_records(input_dir, output_dir)
|
||||
|
||||
# Verify output
|
||||
output_path = os.path.join(output_dir, "test.txt")
|
||||
assert os.path.exists(output_path)
|
||||
with open(output_path, 'r') as f:
|
||||
content = f.read()
|
||||
assert "游戏ID: TEST123" in content
|
||||
@@ -0,0 +1,45 @@
|
||||
import pytest
|
||||
import json
|
||||
from unittest.mock import Mock, patch
|
||||
from player import Player
|
||||
|
||||
@pytest.fixture
|
||||
def mock_player():
|
||||
player = Player("TestPlayer", "test-model")
|
||||
player.hand = ["A", "B", "C"]
|
||||
player.llm_client = Mock()
|
||||
return player
|
||||
|
||||
def test_choose_cards_to_play_valid_response(mock_player):
|
||||
mock_response = json.dumps({
|
||||
"played_cards": ["A"],
|
||||
"behavior": "保守出牌",
|
||||
"play_reason": "测试原因"
|
||||
})
|
||||
mock_player.llm_client.chat.return_value = (mock_response, "")
|
||||
|
||||
result = mock_player.choose_cards_to_play("", "", "")
|
||||
assert "played_cards" in result
|
||||
assert set(result["played_cards"]).issubset(mock_player.hand)
|
||||
|
||||
def test_decide_challenge_retry_logic(mock_player):
|
||||
mock_player.llm_client.chat.side_effect = [
|
||||
("invalid_response", ""),
|
||||
('{"was_challenged": true, "challenge_reason": ""}', "")
|
||||
]
|
||||
|
||||
result, _ = mock_player.decide_challenge("", "", "", "", "")
|
||||
assert mock_player.llm_client.chat.call_count == 2
|
||||
assert result["was_challenged"] is True
|
||||
|
||||
def test_reflect_updates_opinions(mock_player):
|
||||
mock_player.llm_client.chat.return_value = ("新的印象分析", "")
|
||||
|
||||
mock_player.reflect(
|
||||
["OtherPlayer"],
|
||||
"Round Info",
|
||||
"Action Info",
|
||||
"Result Info"
|
||||
)
|
||||
|
||||
assert "OtherPlayer" in mock_player.opinions
|
||||
Reference in New Issue
Block a user