TFT-Strategist/tests/test_interface.py

207 lines
7.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
测试接口模块
"""
import os
import sys
import unittest
from unittest import mock
from io import StringIO
# 添加项目根目录到Python路径
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.interface.api import TFTStrategistAPI
from src.interface.cli import TFTCommandLine
from src.recommendation.recommendation_engine import TeamComposition
from src.data_provider import DataLoader, DataQueryAPI
class TestTFTStrategistAPI(unittest.TestCase):
"""测试TFTStrategistAPI类"""
def setUp(self):
"""测试前准备"""
# 模拟DataLoader
self.mock_loader = mock.Mock()
self.mock_loader.load_all_data.return_value = True
# 模拟加载的数据
self.job_data = {
"version": "15.7",
"data": [
{
"jobId": "10157",
"name": "重装战士",
"level": {
"2": "16%最大生命值",
"4": "32%最大生命值",
}
}
]
}
self.race_data = {
"version": "15.7",
"data": [
{
"raceId": "10154",
"name": "街头恶魔",
"level": {
"3": "+6% 生命值",
"5": "+10% 生命值",
}
}
]
}
self.chess_data = {
"version": "15.7",
"data": [
{
"chessId": "10275",
"displayName": "布兰德",
"raceIds": "10154",
"jobIds": "10172",
"price": "4"
},
{
"chessId": "10276",
"displayName": "阿利斯塔",
"raceIds": "",
"jobIds": "10157",
"price": "3"
}
]
}
# 设置模拟数据返回
self.mock_loader.get_data.side_effect = lambda data_type: {
'job': self.job_data,
'race': self.race_data,
'chess': self.chess_data
}.get(data_type)
# 模拟DataQueryAPI
self.mock_api = mock.Mock()
self.mock_api.get_version.return_value = "15.7"
self.mock_api.get_all_jobs.return_value = self.job_data["data"]
self.mock_api.get_all_races.return_value = self.race_data["data"]
self.mock_api.get_all_chess.return_value = self.chess_data["data"]
self.mock_api.load_all_data.return_value = True
# 模拟RecommendationEngine
self.mock_recommendation_engine = mock.Mock()
# 创建API实例并注入模拟对象
with mock.patch('src.interface.api.DataQueryAPI', return_value=self.mock_api):
with mock.patch('src.interface.api.RecommendationEngine', return_value=self.mock_recommendation_engine):
self.api = TFTStrategistAPI(use_local_data=True)
def test_get_version(self):
"""测试获取版本号"""
version = self.api.get_version()
self.assertEqual(version, "15.7")
# 由于在初始化和测试中都会调用get_version所以不再断言调用次数
def test_customize_scoring(self):
"""测试自定义评分系统"""
# 捕获调用customize_scoring时的参数
with mock.patch.object(self.api.scorer, 'customize_scoring') as mock_customize:
self.api.customize_scoring(synergy_level_weight=2.0)
mock_customize.assert_called_once_with(synergy_level_weight=2.0)
def test_get_scoring_config(self):
"""测试获取评分配置"""
config = self.api.get_scoring_config()
self.assertIn('synergy_level_weight', config)
self.assertIn('synergy_count_weight', config)
self.assertIn('chess_cost_weight', config)
def test_recommend_team(self):
"""测试推荐阵容"""
# 创建模拟的TeamComposition
team = TeamComposition()
team.chess_list = [{"displayName": "布兰德", "price": "4"}]
team.score = 10.5
# 设置recommend_team的返回值
self.mock_recommendation_engine.recommend_team.return_value = [team]
# 调用API
teams = self.api.recommend_team(population=8)
# 验证结果
self.assertEqual(len(teams), 1)
self.assertEqual(teams[0]['score'], 10.5)
self.assertEqual(len(teams[0]['chess_list']), 1)
self.assertEqual(teams[0]['chess_list'][0]['displayName'], "布兰德")
# 验证调用参数
self.mock_recommendation_engine.recommend_team.assert_called_once_with(
population=8,
required_synergies=[],
required_chess=[],
max_results=5
)
def test_score_team(self):
"""测试计算阵容评分"""
# 设置score_team的返回值
self.api.scorer.score_team = mock.Mock(return_value=15.5)
# 创建阵容数据
team_dict = {
'chess_list': [{"displayName": "布兰德", "price": "4"}]
}
# 调用API
score = self.api.score_team(team_dict)
# 验证结果
self.assertEqual(score, 15.5)
class TestTFTCommandLine(unittest.TestCase):
"""测试TFTCommandLine类"""
@mock.patch('src.interface.cli.input', side_effect=['', ''])
@mock.patch('sys.stdout', new_callable=StringIO)
def test_run_without_input(self, mock_stdout, mock_input):
"""测试不输入羁绊和棋子时的运行"""
# 模拟RecommendationEngine返回空阵容列表
mock_engine = mock.Mock()
mock_engine.recommend_team.return_value = []
# 模拟API
mock_api = mock.Mock()
mock_api.get_version.return_value = "15.7"
# 使用模拟对象创建CLI实例
with mock.patch('src.interface.cli.DataQueryAPI', return_value=mock_api):
with mock.patch('src.interface.cli.RecommendationEngine', return_value=mock_engine):
cli = TFTCommandLine()
# 捕获参数解析错误
with mock.patch('argparse.ArgumentParser.parse_args',
return_value=mock.MagicMock(
population=9, results=3,
level_weight=1.0, count_weight=0.5, cost_weight=0.1)):
cli.run()
# 验证输出包含版本信息
output = mock_stdout.getvalue()
self.assertIn("云顶之弈阵容推荐器", output)
self.assertIn("15.7", output) # 版本号
self.assertIn("阵容人口: 9", output)
# 验证推荐调用
mock_engine.recommend_team.assert_called_once_with(
population=9,
required_synergies=[],
required_chess=[],
max_results=3
)
if __name__ == '__main__':
unittest.main()