207 lines
7.1 KiB
Python
207 lines
7.1 KiB
Python
"""
|
||
测试接口模块
|
||
"""
|
||
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() |