From 2ad84e6fad432a3486ac3035e0a0b8bd622303b4 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Mon, 19 Aug 2019 01:39:59 +0200 Subject: [PATCH] Remove Player class mocking in tests The Player class is essentially plain old data right now. Remove all mocking of it to make it easier to modify. If we ever bless Player with non-trivial behaviour, we can make a mock or an abstract class for it. FIXME - centralized creation. Signed-off-by: Igor Kotrasinski --- tests/conftest.py | 23 +- tests/unit_tests/conftest.py | 28 ++- tests/unit_tests/ladder_fixtures.py | 27 +-- tests/unit_tests/test_custom_game.py | 38 +-- tests/unit_tests/test_game.py | 149 ++++++------ tests/unit_tests/test_game_stats_service.py | 246 ++++++++++---------- tests/unit_tests/test_gameconnection.py | 6 +- tests/unit_tests/test_ladder.py | 92 +++++--- tests/unit_tests/test_laddergame.py | 10 +- tests/unit_tests/test_lobbyconnection.py | 26 +-- tests/unit_tests/test_matchmaker_queue.py | 44 ++-- 11 files changed, 358 insertions(+), 331 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 4155879e3..8d1c1a2e0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -179,28 +179,25 @@ def make_game(uid, players): @pytest.fixture -def create_player(): +def player_factory(): from server.players import Player, PlayerState - def make(login='', id=0, port=6112, state=PlayerState.HOSTING, ip='127.0.0.1', global_rating=Rating(1500, 250), ladder_rating=Rating(1500, 250)): - p = mock.create_autospec(spec=Player(login)) - p.global_rating = global_rating - p.ladder_rating = ladder_rating - p.ip = ip + # FIXME + def make(state=PlayerState.IDLE, ip='127.0.0.1', **kwargs): + p = Player(ip=ip, **kwargs) p.state = state - p.id = id - p.login = login return p + return make @pytest.fixture -def players(create_player): +def players(player_factory): from server.players import PlayerState return mock.Mock( - hosting=create_player(login='Paula_Bean', id=1, port=6112, state=PlayerState.HOSTING), - peer=create_player(login='That_Guy', id=2, port=6112, state=PlayerState.JOINING), - joining=create_player(login='James_Kirk', id=3, port=6112, state=PlayerState.JOINING) + hosting=player_factory(login='Paula_Bean', player_id=1, state=PlayerState.HOSTING), + peer=player_factory(login='That_Guy', player_id=2, state=PlayerState.JOINING), + joining=player_factory(login='James_Kirk', player_id=3, state=PlayerState.JOINING) ) @@ -285,5 +282,3 @@ def twilio_sid(): @pytest.fixture def twilio_token(): return "token_a" - - diff --git a/tests/unit_tests/conftest.py b/tests/unit_tests/conftest.py index ea066c125..83afcaca5 100644 --- a/tests/unit_tests/conftest.py +++ b/tests/unit_tests/conftest.py @@ -105,17 +105,23 @@ def add_connected_players(game: BaseGame, players): game.host = players[0] -def add_players(gameobj: BaseGame, n: int, team: int=None): - game = gameobj - current = len(game.players) - players = [] - for i in range(current, current+n): - players.append(Player(player_id=i + 1, login=f'Player {i + 1}', global_rating=(1500, 500))) +@pytest.fixture +def game_add_players(player_factory): + def add(gameobj: BaseGame, n: int, team: int=None): + game = gameobj + current = len(game.players) + players = [] + for i in range(current, current+n): + p = player_factory(player_id=i+1, login=f'Player {i + 1}', + global_rating=(1500, 500)) + players.append(p) + + add_connected_players(game, players) - add_connected_players(game, players) + if team is not None: + for p in players: + game.set_player_option(p.id, 'Team', team) - if team is not None: - for p in players: - game.set_player_option(p.id, 'Team', team) + return players - return players + return add diff --git a/tests/unit_tests/ladder_fixtures.py b/tests/unit_tests/ladder_fixtures.py index fed09b237..4fc93364b 100644 --- a/tests/unit_tests/ladder_fixtures.py +++ b/tests/unit_tests/ladder_fixtures.py @@ -1,33 +1,22 @@ -from unittest import mock - - import pytest -from server import LadderService -from server.players import Player - @pytest.fixture() def map_pool(): - return [(1, '', 'scmp_001'), (5, '', 'scmp_05'), (10, '', 'scmp_010'), (12, '', 'scmp_012'), (11, '', 'scmp_0011')] - - -def playerMock(lobbythread, id): - player_mock = mock.create_autospec(spec=Player('')) - player_mock.login = "Player %s" % id - player_mock.id = id - player_mock.lobby_connection = lobbythread - return player_mock + return [(1, '', 'scmp_001'), (5, '', 'scmp_05'), (10, '', 'scmp_010'), + (12, '', 'scmp_012'), (11, '', 'scmp_0011')] @pytest.fixture() -def player1(lobbythread): - return playerMock(lobbythread, 1) +def player1(lobbythread, player_factory): + return player_factory(login=f"Player 1", player_id=1, + lobby_connection=lobbythread) @pytest.fixture() -def player2(lobbythread): - return playerMock(lobbythread, 2) +def player2(lobbythread, player_factory): + return player_factory(login=f"Player 2", player_id=2, + lobby_connection=lobbythread) @pytest.fixture() diff --git a/tests/unit_tests/test_custom_game.py b/tests/unit_tests/test_custom_game.py index 0c41613b8..9fb64c0be 100644 --- a/tests/unit_tests/test_custom_game.py +++ b/tests/unit_tests/test_custom_game.py @@ -1,12 +1,9 @@ -from unittest import mock - import pytest import time from server.games.game import GameState, ValidityState from server.games import CustomGame -from server.players import Player -from tests.unit_tests.conftest import add_connected_players, add_players +from tests.unit_tests.conftest import add_connected_players @pytest.yield_fixture @@ -16,11 +13,12 @@ def custom_game(loop, game_service, game_stats_service): loop.run_until_complete(game.clear_data()) -async def test_rate_game_early_abort_no_enforce(game_service, game_stats_service, custom_game): +async def test_rate_game_early_abort_no_enforce( + game_service, game_stats_service, custom_game, player_factory): custom_game.state = GameState.LOBBY players = [ - Player(player_id=1, login='Dostya', global_rating=(1500, 500)), - Player(player_id=2, login='Rhiza', global_rating=(1500, 500)), + player_factory(player_id=1, login='Dostya', global_rating=(1500, 500)), + player_factory(player_id=2, login='Rhiza', global_rating=(1500, 500)), ] add_connected_players(custom_game, players) custom_game.set_player_option(1, 'Team', 2) @@ -28,16 +26,18 @@ async def test_rate_game_early_abort_no_enforce(game_service, game_stats_service await custom_game.launch() await custom_game.add_result(0, 1, 'VICTORY', 5) - custom_game.launched_at = time.time() - 60 # seconds + custom_game.launched_at = time.time() - 60 # seconds await custom_game.on_game_end() assert custom_game.validity == ValidityState.TOO_SHORT -async def test_rate_game_early_abort_with_enforce(game_service, game_stats_service, custom_game): + +async def test_rate_game_early_abort_with_enforce( + game_service, game_stats_service, custom_game, player_factory): custom_game.state = GameState.LOBBY players = [ - Player(player_id=1, login='Dostya', global_rating=(1500, 500)), - Player(player_id=2, login='Rhiza', global_rating=(1500, 500)), + player_factory(player_id=1, login='Dostya', global_rating=(1500, 500)), + player_factory(player_id=2, login='Rhiza', global_rating=(1500, 500)), ] add_connected_players(custom_game, players) custom_game.set_player_option(1, 'Team', 2) @@ -52,11 +52,12 @@ async def test_rate_game_early_abort_with_enforce(game_service, game_stats_servi assert custom_game.validity == ValidityState.VALID -async def test_rate_game_late_abort_no_enforce(game_service, game_stats_service, custom_game): +async def test_rate_game_late_abort_no_enforce( + game_service, game_stats_service, custom_game, player_factory): custom_game.state = GameState.LOBBY players = [ - Player(player_id=1, login='Dostya', global_rating=(1500, 500)), - Player(player_id=2, login='Rhiza', global_rating=(1500, 500)), + player_factory(player_id=1, login='Dostya', global_rating=(1500, 500)), + player_factory(player_id=2, login='Rhiza', global_rating=(1500, 500)), ] add_connected_players(custom_game, players) custom_game.set_player_option(1, 'Team', 2) @@ -64,22 +65,23 @@ async def test_rate_game_late_abort_no_enforce(game_service, game_stats_service, await custom_game.launch() await custom_game.add_result(0, 1, 'VICTORY', 5) - custom_game.launched_at = time.time() - 600 # seconds + custom_game.launched_at = time.time() - 600 # seconds await custom_game.on_game_end() assert custom_game.validity == ValidityState.VALID -async def test_global_rating_higher_after_custom_game_win(custom_game: CustomGame): +async def test_global_rating_higher_after_custom_game_win( + custom_game: CustomGame, game_add_players): game = custom_game game.state = GameState.LOBBY - players = add_players(game, 2) + players = game_add_players(game, 2) game.set_player_option(players[0].id, 'Team', 1) game.set_player_option(players[1].id, 'Team', 2) old_mean = players[0].global_rating[0] await game.launch() - game.launched_at = time.time() - 60*20 # seconds + game.launched_at = time.time() - 60*20 # seconds await game.add_result(0, 0, 'victory', 5) await game.add_result(0, 1, 'defeat', -5) await game.on_game_end() diff --git a/tests/unit_tests/test_game.py b/tests/unit_tests/test_game.py index 263e5e94d..6d785d2ab 100644 --- a/tests/unit_tests/test_game.py +++ b/tests/unit_tests/test_game.py @@ -8,10 +8,9 @@ from server.games import CoopGame, CustomGame from server.games.game import (Game, GameError, GameOutcome, GameState, ValidityState, Victory, VisibilityState) -from server.players import Player from tests import CoroMock from tests.unit_tests.conftest import (add_connected_player, - add_connected_players, add_players, + add_connected_players, make_mock_game_connection) from trueskill import Rating @@ -50,7 +49,7 @@ def test_instance_logging(game_stats_service): logger.debug.assert_called_with("%s created", game) -async def test_validate_game_settings(game: Game): +async def test_validate_game_settings(game: Game, game_add_players): settings = [ ('Victory', Victory.SANDBOX, ValidityState.WRONG_VICTORY_CONDITION), ('FogOfWar', 'none', ValidityState.NO_FOG_OF_WAR), @@ -62,7 +61,7 @@ async def test_validate_game_settings(game: Game): ] game.state = GameState.LOBBY - add_players(game, 2) + game_add_players(game, 2) await check_game_settings(game, settings) @@ -96,9 +95,9 @@ async def check_game_settings(game: Game, settings: List[Tuple[str, Any, Validit game.gameOptions[key] = old -async def test_ffa_not_rated(game): +async def test_ffa_not_rated(game, game_add_players): game.state = GameState.LOBBY - add_players(game, 5, team=1) + game_add_players(game, 5, team=1) await game.launch() await game.add_result(0, 1, 'VICTORY', 5) @@ -109,11 +108,11 @@ async def test_ffa_not_rated(game): assert game.validity == ValidityState.FFA_NOT_RANKED -async def test_multi_team_not_rated(game): +async def test_multi_team_not_rated(game, game_add_players): game.state = GameState.LOBBY - add_players(game, 2, team=1) - add_players(game, 2, team=2) - add_players(game, 2, team=3) + game_add_players(game, 2, team=1) + game_add_players(game, 2, team=2) + game_add_players(game, 2, team=3) await game.launch() await game.add_result(0, 1, 'VICTORY', 5) game.launched_at = time.time() - 60*20 # seconds @@ -121,10 +120,10 @@ async def test_multi_team_not_rated(game): assert game.validity == ValidityState.MULTI_TEAM -async def test_has_ai_players_not_rated(game): +async def test_has_ai_players_not_rated(game, game_add_players): game.state = GameState.LOBBY - add_players(game, 2, team=1) - add_players(game, 2, team=2) + game_add_players(game, 2, team=1) + game_add_players(game, 2, team=2) game.AIs = {'IA Tech': {'Faction': 5, 'Color': 1, 'Team': 2, 'StartSpot': 2}, 'Oum-Ashavoh (IA Tech)': {'Army': 3}} await game.launch() await game.add_result(0, 1, 'VICTORY', 5) @@ -133,10 +132,10 @@ async def test_has_ai_players_not_rated(game): assert game.validity == ValidityState.HAS_AI_PLAYERS -async def test_uneven_teams_not_rated(game): +async def test_uneven_teams_not_rated(game, game_add_players): game.state = GameState.LOBBY - add_players(game, 2, team=2) - add_players(game, 3, team=3) + game_add_players(game, 2, team=2) + game_add_players(game, 3, team=3) await game.launch() await game.add_result(0, 1, 'VICTORY', 5) @@ -147,10 +146,10 @@ async def test_uneven_teams_not_rated(game): assert game.validity == ValidityState.UNEVEN_TEAMS_NOT_RANKED -async def test_single_team_not_rated(game): +async def test_single_team_not_rated(game, game_add_players): n_players = 4 game.state = GameState.LOBBY - add_players(game, n_players, team=2) + game_add_players(game, n_players, team=2) await game.launch() game.launched_at = time.time()-60*20 @@ -263,11 +262,12 @@ async def test_game_marked_dirty_when_timed_out(game: Game): assert game in game.game_service.dirty_games -async def test_clear_slot(game: Game, mock_game_connection: GameConnection): +async def test_clear_slot(game: Game, mock_game_connection: GameConnection, + player_factory): game.state = GameState.LOBBY players = [ - Player(player_id=1, login='Dostya', global_rating=(1500, 500)), - Player(player_id=2, login='Rhiza', global_rating=(1500, 500)) + player_factory(player_id=1, login='Dostya', global_rating=(1500, 500)), + player_factory(player_id=2, login='Rhiza', global_rating=(1500, 500)) ] add_connected_players(game, players) game.set_ai_option('rush', 'StartSpot', 3) @@ -312,9 +312,9 @@ async def test_invalid_army_not_add_result(game: Game, players): assert 99 not in game._results -async def test_game_ends_in_mutually_agreed_draw(game: Game): +async def test_game_ends_in_mutually_agreed_draw(game: Game, game_add_players): game.state = GameState.LOBBY - players = add_players(game, 2) + players = game_add_players(game, 2) await game.launch() game.launched_at = time.time()-60*60 @@ -326,9 +326,10 @@ async def test_game_ends_in_mutually_agreed_draw(game: Game): assert game.validity is ValidityState.MUTUAL_DRAW -async def test_game_not_ends_in_unilatery_agreed_draw(game: Game, players): +async def test_game_not_ends_in_unilatery_agreed_draw(game: Game, players, + game_add_players): game.state = GameState.LOBBY - add_players(game, 2) + game_add_players(game, 2) await game.launch() game.launched_at = time.time()-60*60 @@ -387,16 +388,16 @@ async def test_compute_rating_computes_ladder_ratings(game: Game, players): assert players.joining in groups[1] -async def test_compute_rating_balanced_teamgame(game: Game, create_player): +async def test_compute_rating_balanced_teamgame(game: Game, player_factory): await game.clear_data() game.state = GameState.LOBBY players = [ - (create_player(**info), result, team) for info, result, team in [ - (dict(login='Paula_Bean', id=1, global_rating=Rating(1500, 250.7)), 0, 1), - (dict(login='Some_Guy', id=2, global_rating=Rating(1700, 120.1)), 0, 1), - (dict(login='Some_Other_Guy', id=3, global_rating=Rating(1200, 72.02)), 0, 2), - (dict(login='That_Person', id=4, global_rating=Rating(1200, 72.02)), 0, 2), + (player_factory(**info), result, team) for info, result, team in [ + (dict(login='Paula_Bean', player_id=1, global_rating=Rating(1500, 250.7)), 0, 1), + (dict(login='Some_Guy', player_id=2, global_rating=Rating(1700, 120.1)), 0, 1), + (dict(login='Some_Other_Guy', player_id=3, global_rating=Rating(1200, 72.02)), 0, 2), + (dict(login='That_Person', player_id=4, global_rating=Rating(1200, 72.02)), 0, 2), ] ] add_connected_players(game, [player for player, _, _ in players]) @@ -413,10 +414,11 @@ async def test_compute_rating_balanced_teamgame(game: Game, create_player): assert new_rating != Rating(*player.global_rating) -async def test_game_get_army_result_takes_most_reported_result(game): +async def test_game_get_army_result_takes_most_reported_result(game, + game_add_players): game.state = GameState.LOBBY - players = add_players(game, 1) + players = game_add_players(game, 1) await game.add_result(0, 0, 'defeat', 0) await game.add_result(0, 0, 'defeat', 0) await game.add_result(0, 0, 'victory', 0) @@ -439,11 +441,12 @@ async def test_on_game_end_does_not_call_rate_game_for_single_player(game): game.rate_game.assert_not_called() -async def test_on_game_end_calls_rate_game_with_two_players(game): +async def test_on_game_end_calls_rate_game_with_two_players(game, + game_add_players): await game.clear_data() game.rate_game = CoroMock() game.state = GameState.LOBBY - add_players(game, 2) + game_add_players(game, 2) await game.launch() @@ -470,16 +473,16 @@ async def test_name_sanitization(game): assert(game.name == "_Aâé~<1000") -async def test_to_dict(game, create_player): +async def test_to_dict(game, player_factory): await game.clear_data() game.state = GameState.LOBBY players = [ - (create_player(**info), result, team) for info, result, team in [ - (dict(login='Paula_Bean', id=1, global_rating=Rating(1500, 250.7)), 0, 1), - (dict(login='Some_Guy', id=2, global_rating=Rating(1700, 120.1)), 0, 1), - (dict(login='Some_Other_Guy', id=3, global_rating=Rating(1200, 72.02)), 0, 2), - (dict(login='That_Person', id=4, global_rating=Rating(1200, 72.02)), 0, 2), + (player_factory(**info), result, team) for info, result, team in [ + (dict(login='Paula_Bean', player_id=1, global_rating=Rating(1500, 250.7)), 0, 1), + (dict(login='Some_Guy', player_id=2, global_rating=Rating(1700, 120.1)), 0, 1), + (dict(login='Some_Other_Guy', player_id=3, global_rating=Rating(1200, 72.02)), 0, 2), + (dict(login='That_Person', player_id=4, global_rating=Rating(1200, 72.02)), 0, 2), ] ] add_connected_players(game, [player for player, _, _ in players]) @@ -513,13 +516,14 @@ async def test_to_dict(game, create_player): assert data == expected -async def test_persist_results_not_called_with_one_player(game): +async def test_persist_results_not_called_with_one_player(game, + player_factory): await game.clear_data() game.persist_results = CoroMock() game.state = GameState.LOBBY players = [ - Player(player_id=1, login='Dostya', global_rating=(1500, 500)) + player_factory(player_id=1, login='Dostya', global_rating=(1500, 500)) ] add_connected_players(game, players) await game.launch() @@ -530,10 +534,11 @@ async def test_persist_results_not_called_with_one_player(game): game.persist_results.assert_not_called() -async def test_persist_results_not_called_with_no_results(game): +async def test_persist_results_not_called_with_no_results(game, + game_add_players): game.state = GameState.LOBBY - add_players(game, 2, team=2) - add_players(game, 2, team=3) + game_add_players(game, 2, team=2) + game_add_players(game, 2, team=3) game.persist_results = CoroMock() game.launched_at = time.time() - 60*20 @@ -546,10 +551,10 @@ async def test_persist_results_not_called_with_no_results(game): game.persist_results.assert_not_called() -async def test_persist_results_called_with_two_players(game): +async def test_persist_results_called_with_two_players(game, game_add_players): await game.clear_data() game.state = GameState.LOBBY - add_players(game, 2) + game_add_players(game, 2) await game.launch() assert len(game.players) == 2 await game.add_result(0, 1, 'victory', 5) @@ -562,10 +567,10 @@ async def test_persist_results_called_with_two_players(game): assert game.get_army_score(1) == 5 -async def test_persist_results_called_for_unranked(game): +async def test_persist_results_called_for_unranked(game, game_add_players): await game.clear_data() game.state = GameState.LOBBY - add_players(game, 2) + game_add_players(game, 2) await game.launch() game.validity = ValidityState.BAD_UNIT_RESTRICTIONS assert len(game.players) == 2 @@ -579,10 +584,11 @@ async def test_persist_results_called_for_unranked(game): assert game.get_army_score(1) == 5 -async def test_get_army_score_conflicting_results_clear_winner(game): +async def test_get_army_score_conflicting_results_clear_winner(game, + game_add_players): game.state = GameState.LOBBY - add_players(game, 3, team=2) - add_players(game, 3, team=3) + game_add_players(game, 3, team=2) + game_add_players(game, 3, team=3) await game.launch() await game.add_result(0, 0, 'victory', 1000) @@ -597,10 +603,10 @@ async def test_get_army_score_conflicting_results_clear_winner(game): assert game.get_army_score(1) == 100 -async def test_get_army_score_conflicting_results_tied(game): +async def test_get_army_score_conflicting_results_tied(game, game_add_players): game.state = GameState.LOBBY - add_players(game, 2, team=2) - add_players(game, 2, team=3) + game_add_players(game, 2, team=2) + game_add_players(game, 2, team=3) await game.add_result(0, 0, 'victory', 1000) await game.add_result(1, 0, 'victory', 1234) await game.add_result(2, 1, 'defeat', 100) @@ -620,9 +626,10 @@ def test_hashing(game): assert {game: 1, Game(game.id, mock.Mock(), mock.Mock()): 1} == {game: 1} -async def test_report_army_stats_sends_stats_for_defeated_player(game: Game): +async def test_report_army_stats_sends_stats_for_defeated_player(game: Game, + game_add_players): game.state = GameState.LOBBY - players = add_players(game, 2) + players = game_add_players(game, 2) await game.launch() await game.add_result(0, 1, 'defeat', -1) @@ -635,12 +642,13 @@ async def test_report_army_stats_sends_stats_for_defeated_player(game: Game): game._game_stats_service.process_game_stats.assert_called_once_with(players[1], game, stats) -async def test_partial_stats_not_affecting_rating_persistence(custom_game, event_service, achievement_service): +async def test_partial_stats_not_affecting_rating_persistence( + custom_game, event_service, achievement_service, game_add_players): from server.stats.game_stats_service import GameStatsService game = custom_game game._game_stats_service = GameStatsService(event_service, achievement_service) game.state = GameState.LOBBY - players = add_players(game, 2) + players = game_add_players(game, 2) game.set_player_option(players[0].id, 'Team', 2) game.set_player_option(players[1].id, 'Team', 3) old_mean = players[0].global_rating[0] @@ -656,11 +664,12 @@ async def test_partial_stats_not_affecting_rating_persistence(custom_game, event assert players[0].global_rating[0] > old_mean -async def test_players_exclude_observers(game: Game): +async def test_players_exclude_observers(game: Game, game_add_players, + player_factory): game.state = GameState.LOBBY - players = add_players(game, 2) + players = game_add_players(game, 2) - obs = Player(player_id=3, login='Zoidberg', global_rating=(1500, 500)) + obs = player_factory(player_id=3, login='Zoidberg', global_rating=(1500, 500)) game.game_service.player_service[obs.id] = obs gc = make_mock_game_connection(state=GameConnectionState.CONNECTED_TO_HOST, player=obs) @@ -751,10 +760,10 @@ def test_visibility_states(): VisibilityState.to_string(enum_value) == string_value) -def test_is_even(game: Game): +def test_is_even(game: Game, game_add_players): game.state = GameState.LOBBY - add_players(game, 4, team=2) - add_players(game, 4, team=3) + game_add_players(game, 4, team=2) + game_add_players(game, 4, team=3) assert game.is_even @@ -765,16 +774,16 @@ def test_is_even_no_players(game: Game): assert game.is_even -def test_is_even_single_player(game: Game): +def test_is_even_single_player(game: Game, game_add_players): game.state = GameState.LOBBY - add_players(game, 2, team=2) + game_add_players(game, 2, team=2) assert not game.is_even -def test_is_even_ffa(game: Game): +def test_is_even_ffa(game: Game, game_add_players): game.state = GameState.LOBBY # Team 1 is the special "-" team - add_players(game, 5, team=1) + game_add_players(game, 5, team=1) assert game.is_even diff --git a/tests/unit_tests/test_game_stats_service.py b/tests/unit_tests/test_game_stats_service.py index 7d4633f14..50a319a28 100644 --- a/tests/unit_tests/test_game_stats_service.py +++ b/tests/unit_tests/test_game_stats_service.py @@ -1,26 +1,24 @@ -from unittest.mock import MagicMock, Mock +from unittest.mock import Mock import pytest from server.factions import Faction from server.games import Game -from server.lobbyconnection import LobbyConnection -from server.players import Player -from server.stats.achievement_service import * -from server.stats.event_service import * +from server.stats import achievement_service as ach +from server.stats import event_service as ev from server.stats.game_stats_service import GameStatsService from tests import CoroMock @pytest.fixture() def event_service(): - m = Mock(spec=EventService) + m = Mock(spec=ev.EventService) m.execute_batch_update = CoroMock() return m @pytest.fixture() def achievement_service(): - m = Mock(spec=AchievementService) + m = Mock(spec=ach.AchievementService) m.execute_batch_update = CoroMock() return m @@ -31,10 +29,8 @@ def game_stats_service(event_service, achievement_service): @pytest.fixture() -def player(): - player = Player(login="TestUser", player_id=42) - player._lobby_connection = MagicMock(spec=LobbyConnection) - return player +def player(player_factory): + return player_factory(login="TestUser", player_id=42) @pytest.fixture() @@ -69,65 +65,65 @@ async def test_process_game_stats(game_stats_service, event_service, achievement await game_stats_service.process_game_stats(player, game, stats) - event_service.record_event.assert_any_call(EVENT_LOST_ACUS, 0, []) - event_service.record_event.assert_any_call(EVENT_BUILT_AIR_UNITS, 1, []) - event_service.record_event.assert_any_call(EVENT_LOST_AIR_UNITS, 2, []) - event_service.record_event.assert_any_call(EVENT_BUILT_LAND_UNITS, 4, []) - event_service.record_event.assert_any_call(EVENT_LOST_LAND_UNITS, 5, []) - event_service.record_event.assert_any_call(EVENT_BUILT_NAVAL_UNITS, 33, []) - event_service.record_event.assert_any_call(EVENT_LOST_NAVAL_UNITS, 11, []) - event_service.record_event.assert_any_call(EVENT_LOST_TECH_1_UNITS, 12, []) - event_service.record_event.assert_any_call(EVENT_LOST_TECH_2_UNITS, 13, []) - event_service.record_event.assert_any_call(EVENT_LOST_TECH_3_UNITS, 14, []) - event_service.record_event.assert_any_call(EVENT_BUILT_TECH_1_UNITS, 16, []) - event_service.record_event.assert_any_call(EVENT_BUILT_TECH_2_UNITS, 17, []) - event_service.record_event.assert_any_call(EVENT_BUILT_TECH_3_UNITS, 18, []) - event_service.record_event.assert_any_call(EVENT_LOST_EXPERIMENTALS, 19, []) - event_service.record_event.assert_any_call(EVENT_BUILT_EXPERIMENTALS, 20, []) - event_service.record_event.assert_any_call(EVENT_LOST_ENGINEERS, 21, []) - event_service.record_event.assert_any_call(EVENT_BUILT_ENGINEERS, 22, []) - event_service.record_event.assert_any_call(EVENT_SERAPHIM_PLAYS, 1, []) - event_service.record_event.assert_any_call(EVENT_SERAPHIM_WINS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_ACUS, 0, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_AIR_UNITS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_AIR_UNITS, 2, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_LAND_UNITS, 4, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_LAND_UNITS, 5, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_NAVAL_UNITS, 33, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_NAVAL_UNITS, 11, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_TECH_1_UNITS, 12, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_TECH_2_UNITS, 13, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_TECH_3_UNITS, 14, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_TECH_1_UNITS, 16, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_TECH_2_UNITS, 17, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_TECH_3_UNITS, 18, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_EXPERIMENTALS, 19, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_EXPERIMENTALS, 20, []) + event_service.record_event.assert_any_call(ev.EVENT_LOST_ENGINEERS, 21, []) + event_service.record_event.assert_any_call(ev.EVENT_BUILT_ENGINEERS, 22, []) + event_service.record_event.assert_any_call(ev.EVENT_SERAPHIM_PLAYS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_SERAPHIM_WINS, 1, []) event_service.execute_batch_update.assert_called_once_with(42, []) - achievement_service.increment.assert_any_call(ACH_NOVICE, 1, []) - achievement_service.increment.assert_any_call(ACH_JUNIOR, 1, []) - achievement_service.increment.assert_any_call(ACH_SENIOR, 1, []) - achievement_service.increment.assert_any_call(ACH_VETERAN, 1, []) - achievement_service.increment.assert_any_call(ACH_ADDICT, 1, []) - achievement_service.increment.assert_any_call(ACH_THAAM, 1, []) - achievement_service.increment.assert_any_call(ACH_YENZYNE, 1, []) - achievement_service.increment.assert_any_call(ACH_SUTHANUS, 1, []) - achievement_service.increment.assert_any_call(ACH_DONT_MESS_WITH_ME, 3, []) - achievement_service.unlock.assert_any_call(ACH_HATTRICK, []) - achievement_service.increment.assert_any_call(ACH_NO_MERCY, 154, []) - achievement_service.increment.assert_any_call(ACH_DEADLY_BUGS, 147, []) - achievement_service.unlock.assert_any_call(ACH_RAINMAKER, []) - achievement_service.unlock.assert_any_call(ACH_NUCLEAR_WAR, []) - achievement_service.unlock.assert_any_call(ACH_SO_MUCH_RESOURCES, []) - achievement_service.increment.assert_any_call(ACH_IT_AINT_A_CITY, 47, []) - achievement_service.increment.assert_any_call(ACH_STORMY_SEA, 74, []) - achievement_service.unlock.assert_any_call(ACH_MAKE_IT_HAIL, []) - achievement_service.unlock.assert_any_call(ACH_I_HAVE_A_CANON, []) - achievement_service.increment.assert_any_call(ACH_LANDLUBBER, 1, []) - achievement_service.increment.assert_any_call(ACH_SEAMAN, 1, []) - achievement_service.increment.assert_any_call(ACH_ADMIRAL_OF_THE_FLEET, 1, []) - achievement_service.increment.assert_any_call(ACH_DEATH_FROM_ABOVE, 71, []) - achievement_service.increment.assert_any_call(ACH_ASS_WASHER, 37, []) - achievement_service.increment.assert_any_call(ACH_ALIEN_INVASION, 41, []) - achievement_service.increment.assert_any_call(ACH_FATTER_IS_BETTER, 73, []) - achievement_service.increment.assert_any_call(ACH_ARACHNOLOGIST, 87, []) - achievement_service.increment.assert_any_call(ACH_INCOMING_ROBOTS, 83, []) - achievement_service.increment.assert_any_call(ACH_FLYING_DEATH, 49, []) - achievement_service.increment.assert_any_call(ACH_HOLY_CRAB, 51, []) - achievement_service.increment.assert_any_call(ACH_THE_TRANSPORTER, 101, []) - achievement_service.increment.assert_any_call(ACH_DR_EVIL, 20, []) - achievement_service.increment.assert_any_call(ACH_TECHIE, 1, []) - achievement_service.increment.assert_any_call(ACH_I_LOVE_BIG_TOYS, 1, []) - achievement_service.increment.assert_any_call(ACH_EXPERIMENTALIST, 1, []) - achievement_service.set_steps_at_least.assert_any_call(ACH_WHO_NEEDS_SUPPORT, 110, []) - achievement_service.set_steps_at_least.assert_any_call(ACH_WHAT_A_SWARM, 198, []) - achievement_service.unlock.assert_any_call(ACH_THAT_WAS_CLOSE, []) + achievement_service.increment.assert_any_call(ach.ACH_NOVICE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_JUNIOR, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SENIOR, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_VETERAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_ADDICT, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_THAAM, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_YENZYNE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SUTHANUS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_DONT_MESS_WITH_ME, 3, []) + achievement_service.unlock.assert_any_call(ach.ACH_HATTRICK, []) + achievement_service.increment.assert_any_call(ach.ACH_NO_MERCY, 154, []) + achievement_service.increment.assert_any_call(ach.ACH_DEADLY_BUGS, 147, []) + achievement_service.unlock.assert_any_call(ach.ACH_RAINMAKER, []) + achievement_service.unlock.assert_any_call(ach.ACH_NUCLEAR_WAR, []) + achievement_service.unlock.assert_any_call(ach.ACH_SO_MUCH_RESOURCES, []) + achievement_service.increment.assert_any_call(ach.ACH_IT_AINT_A_CITY, 47, []) + achievement_service.increment.assert_any_call(ach.ACH_STORMY_SEA, 74, []) + achievement_service.unlock.assert_any_call(ach.ACH_MAKE_IT_HAIL, []) + achievement_service.unlock.assert_any_call(ach.ACH_I_HAVE_A_CANON, []) + achievement_service.increment.assert_any_call(ach.ACH_LANDLUBBER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SEAMAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_ADMIRAL_OF_THE_FLEET, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_DEATH_FROM_ABOVE, 71, []) + achievement_service.increment.assert_any_call(ach.ACH_ASS_WASHER, 37, []) + achievement_service.increment.assert_any_call(ach.ACH_ALIEN_INVASION, 41, []) + achievement_service.increment.assert_any_call(ach.ACH_FATTER_IS_BETTER, 73, []) + achievement_service.increment.assert_any_call(ach.ACH_ARACHNOLOGIST, 87, []) + achievement_service.increment.assert_any_call(ach.ACH_INCOMING_ROBOTS, 83, []) + achievement_service.increment.assert_any_call(ach.ACH_FLYING_DEATH, 49, []) + achievement_service.increment.assert_any_call(ach.ACH_HOLY_CRAB, 51, []) + achievement_service.increment.assert_any_call(ach.ACH_THE_TRANSPORTER, 101, []) + achievement_service.increment.assert_any_call(ach.ACH_DR_EVIL, 20, []) + achievement_service.increment.assert_any_call(ach.ACH_TECHIE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_I_LOVE_BIG_TOYS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_EXPERIMENTALIST, 1, []) + achievement_service.set_steps_at_least.assert_any_call(ach.ACH_WHO_NEEDS_SUPPORT, 110, []) + achievement_service.set_steps_at_least.assert_any_call(ach.ACH_WHAT_A_SWARM, 198, []) + achievement_service.unlock.assert_any_call(ach.ACH_THAT_WAS_CLOSE, []) achievement_service.execute_batch_update.assert_called_once_with(42, []) # In decent mock frameworks, there exists a "assert_no_more_interactions" @@ -163,7 +159,7 @@ async def test_process_game_won_ladder1v1(game_stats_service, player, game, achi await game_stats_service.process_game_stats(player, game, stats) - achievement_service.unlock.assert_any_call(ACH_FIRST_SUCCESS, []) + achievement_service.unlock.assert_any_call(ach.ACH_FIRST_SUCCESS, []) def test_category_stats_won_more_air(game_stats_service, player, achievement_service, unit_stats): @@ -173,9 +169,9 @@ def test_category_stats_won_more_air(game_stats_service, player, achievement_ser game_stats_service._category_stats(unit_stats, True, [], []) - achievement_service.increment.assert_any_call(ACH_WRIGHT_BROTHER, 1, []) - achievement_service.increment.assert_any_call(ACH_WINGMAN, 1, []) - achievement_service.increment.assert_any_call(ACH_KING_OF_THE_SKIES, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_WRIGHT_BROTHER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_WINGMAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_KING_OF_THE_SKIES, 1, []) assert len(achievement_service.mock_calls) == 3 @@ -186,9 +182,9 @@ def test_category_stats_won_more_land(game_stats_service, player, achievement_se game_stats_service._category_stats(unit_stats, True, [], []) - achievement_service.increment.assert_any_call(ACH_MILITIAMAN, 1, []) - achievement_service.increment.assert_any_call(ACH_GRENADIER, 1, []) - achievement_service.increment.assert_any_call(ACH_FIELD_MARSHAL, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_MILITIAMAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_GRENADIER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_FIELD_MARSHAL, 1, []) assert len(achievement_service.mock_calls) == 3 @@ -199,9 +195,9 @@ def test_category_stats_won_more_naval(game_stats_service, player, achievement_s game_stats_service._category_stats(unit_stats, True, [], []) - achievement_service.increment.assert_any_call(ACH_LANDLUBBER, 1, []) - achievement_service.increment.assert_any_call(ACH_SEAMAN, 1, []) - achievement_service.increment.assert_any_call(ACH_ADMIRAL_OF_THE_FLEET, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_LANDLUBBER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SEAMAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_ADMIRAL_OF_THE_FLEET, 1, []) assert len(achievement_service.mock_calls) == 3 @@ -213,10 +209,10 @@ def test_category_stats_won_more_naval_and_one_experimental(game_stats_service, game_stats_service._category_stats(unit_stats, True, [], []) - achievement_service.increment.assert_any_call(ACH_LANDLUBBER, 1, []) - achievement_service.increment.assert_any_call(ACH_SEAMAN, 1, []) - achievement_service.increment.assert_any_call(ACH_ADMIRAL_OF_THE_FLEET, 1, []) - achievement_service.increment.assert_any_call(ACH_DR_EVIL, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_LANDLUBBER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SEAMAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_ADMIRAL_OF_THE_FLEET, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_DR_EVIL, 1, []) assert len(achievement_service.mock_calls) == 4 @@ -229,25 +225,25 @@ def test_category_stats_won_more_naval_and_three_experimentals(game_stats_servic game_stats_service._category_stats(unit_stats, True, [], []) - achievement_service.increment.assert_any_call(ACH_LANDLUBBER, 1, []) - achievement_service.increment.assert_any_call(ACH_SEAMAN, 1, []) - achievement_service.increment.assert_any_call(ACH_ADMIRAL_OF_THE_FLEET, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_LANDLUBBER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SEAMAN, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_ADMIRAL_OF_THE_FLEET, 1, []) - achievement_service.increment.assert_any_call(ACH_DR_EVIL, 3, []) - achievement_service.increment.assert_any_call(ACH_TECHIE, 1, []) - achievement_service.increment.assert_any_call(ACH_I_LOVE_BIG_TOYS, 1, []) - achievement_service.increment.assert_any_call(ACH_EXPERIMENTALIST, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_DR_EVIL, 3, []) + achievement_service.increment.assert_any_call(ach.ACH_TECHIE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_I_LOVE_BIG_TOYS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_EXPERIMENTALIST, 1, []) assert len(achievement_service.mock_calls) == 7 def test_faction_played_aeon_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._faction_played(Faction.aeon, True, [], []) - event_service.record_event.assert_any_call(EVENT_AEON_PLAYS, 1, []) - event_service.record_event.assert_any_call(EVENT_AEON_WINS, 1, []) - achievement_service.increment.assert_any_call(ACH_AURORA, 1, []) - achievement_service.increment.assert_any_call(ACH_BLAZE, 1, []) - achievement_service.increment.assert_any_call(ACH_SERENITY, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_AEON_PLAYS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_AEON_WINS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_AURORA, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_BLAZE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SERENITY, 1, []) assert len(event_service.mock_calls) == 2 assert len(achievement_service.mock_calls) == 3 @@ -255,18 +251,18 @@ def test_faction_played_aeon_survived(game_stats_service, player, achievement_se def test_faction_played_aeon_died(game_stats_service, player, event_service): game_stats_service._faction_played(Faction.aeon, False, [], []) - event_service.record_event.assert_called_once_with(EVENT_AEON_PLAYS, 1, []) + event_service.record_event.assert_called_once_with(ev.EVENT_AEON_PLAYS, 1, []) assert len(event_service.mock_calls) == 1 def test_faction_played_cybran_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._faction_played(Faction.cybran, True, [], []) - event_service.record_event.assert_any_call(EVENT_CYBRAN_PLAYS, 1, []) - event_service.record_event.assert_any_call(EVENT_CYBRAN_WINS, 1, []) - achievement_service.increment.assert_any_call(ACH_MANTIS, 1, []) - achievement_service.increment.assert_any_call(ACH_WAGNER, 1, []) - achievement_service.increment.assert_any_call(ACH_TREBUCHET, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_CYBRAN_PLAYS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_CYBRAN_WINS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_MANTIS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_WAGNER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_TREBUCHET, 1, []) assert len(event_service.mock_calls) == 2 assert len(achievement_service.mock_calls) == 3 @@ -274,18 +270,18 @@ def test_faction_played_cybran_survived(game_stats_service, player, achievement_ def test_faction_played_cybran_died(game_stats_service, player, event_service): game_stats_service._faction_played(Faction.cybran, False, [], []) - event_service.record_event.assert_called_once_with(EVENT_CYBRAN_PLAYS, 1, []) + event_service.record_event.assert_called_once_with(ev.EVENT_CYBRAN_PLAYS, 1, []) assert len(event_service.mock_calls) == 1 def test_faction_played_uef_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._faction_played(Faction.uef, True, [], []) - event_service.record_event.assert_any_call(EVENT_UEF_PLAYS, 1, []) - event_service.record_event.assert_any_call(EVENT_UEF_WINS, 1, []) - achievement_service.increment.assert_any_call(ACH_MA12_STRIKER, 1, []) - achievement_service.increment.assert_any_call(ACH_RIPTIDE, 1, []) - achievement_service.increment.assert_any_call(ACH_DEMOLISHER, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_UEF_PLAYS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_UEF_WINS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_MA12_STRIKER, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_RIPTIDE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_DEMOLISHER, 1, []) assert len(event_service.mock_calls) == 2 assert len(achievement_service.mock_calls) == 3 @@ -293,18 +289,18 @@ def test_faction_played_uef_survived(game_stats_service, player, achievement_ser def test_faction_played_uef_died(game_stats_service, player, event_service): game_stats_service._faction_played(Faction.uef, False, [], []) - event_service.record_event.assert_called_once_with(EVENT_UEF_PLAYS, 1, []) + event_service.record_event.assert_called_once_with(ev.EVENT_UEF_PLAYS, 1, []) assert len(event_service.mock_calls) == 1 def test_faction_played_seraphim_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._faction_played(Faction.seraphim, True, [], []) - event_service.record_event.assert_any_call(EVENT_SERAPHIM_PLAYS, 1, []) - event_service.record_event.assert_any_call(EVENT_SERAPHIM_WINS, 1, []) - achievement_service.increment.assert_any_call(ACH_THAAM, 1, []) - achievement_service.increment.assert_any_call(ACH_YENZYNE, 1, []) - achievement_service.increment.assert_any_call(ACH_SUTHANUS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_SERAPHIM_PLAYS, 1, []) + event_service.record_event.assert_any_call(ev.EVENT_SERAPHIM_WINS, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_THAAM, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_YENZYNE, 1, []) + achievement_service.increment.assert_any_call(ach.ACH_SUTHANUS, 1, []) assert len(event_service.mock_calls) == 2 assert len(achievement_service.mock_calls) == 3 @@ -312,7 +308,7 @@ def test_faction_played_seraphim_survived(game_stats_service, player, achievemen def test_faction_played_seraphim_died(game_stats_service, player, achievement_service, event_service): game_stats_service._faction_played(Faction.seraphim, False, [], []) - event_service.record_event.assert_called_once_with(EVENT_SERAPHIM_PLAYS, 1, []) + event_service.record_event.assert_called_once_with(ev.EVENT_SERAPHIM_PLAYS, 1, []) assert len(event_service.mock_calls) == 1 assert len(achievement_service.mock_calls) == 0 @@ -321,7 +317,7 @@ def test_killed_acus_one_and_survived(game_stats_service, achievement_service, e unit_stats['cdr']['kills'] = 1 game_stats_service._killed_acus(unit_stats, True, []) - achievement_service.increment.assert_called_once_with(ACH_DONT_MESS_WITH_ME, 1, []) + achievement_service.increment.assert_called_once_with(ach.ACH_DONT_MESS_WITH_ME, 1, []) assert len(achievement_service.mock_calls) == 1 assert len(event_service.mock_calls) == 0 @@ -330,8 +326,8 @@ def test_killed_acus_three_and_survived(game_stats_service, achievement_service, unit_stats['cdr']['kills'] = 3 game_stats_service._killed_acus(unit_stats, True, []) - achievement_service.increment.assert_called_once_with(ACH_DONT_MESS_WITH_ME, 3, []) - achievement_service.unlock.assert_called_once_with(ACH_HATTRICK, []) + achievement_service.increment.assert_called_once_with(ach.ACH_DONT_MESS_WITH_ME, 3, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_HATTRICK, []) assert len(achievement_service.mock_calls) == 2 assert len(event_service.mock_calls) == 0 @@ -341,7 +337,7 @@ def test_killed_acus_one_and_died(game_stats_service, player, achievement_servic unit_stats['cdr']['lost'] = 1 game_stats_service._killed_acus(unit_stats, False, []) - achievement_service.increment.assert_called_once_with(ACH_DONT_MESS_WITH_ME, 1, []) + achievement_service.increment.assert_called_once_with(ach.ACH_DONT_MESS_WITH_ME, 1, []) assert len(achievement_service.mock_calls) == 1 assert len(event_service.mock_calls) == 0 @@ -354,7 +350,7 @@ def test_built_salvations_one_and_died(game_stats_service, player, achievement_s def test_built_salvations_one_and_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._built_salvations(1, True, []) - achievement_service.unlock.assert_called_once_with(ACH_RAINMAKER, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_RAINMAKER, []) assert len(event_service.mock_calls) == 0 @@ -366,7 +362,7 @@ def test_built_yolona_oss_one_and_died(game_stats_service, player, achievement_s def test_built_yolona_oss_one_and_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._built_yolona_oss(1, True, []) - achievement_service.unlock.assert_called_once_with(ACH_NUCLEAR_WAR, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_NUCLEAR_WAR, []) assert len(event_service.mock_calls) == 0 @@ -378,7 +374,7 @@ def test_built_paragons_one_and_died(game_stats_service, player, achievement_ser def test_built_paragons_one_and_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._built_paragons(1, True, []) - achievement_service.unlock.assert_called_once_with(ACH_SO_MUCH_RESOURCES, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_SO_MUCH_RESOURCES, []) assert len(event_service.mock_calls) == 0 @@ -390,7 +386,7 @@ def test_built_scathis_one_and_died(game_stats_service, player, achievement_serv def test_built_scathis_one_and_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._built_scathis(1, True, []) - achievement_service.unlock.assert_called_once_with(ACH_MAKE_IT_HAIL, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_MAKE_IT_HAIL, []) assert len(event_service.mock_calls) == 0 @@ -402,7 +398,7 @@ def test_built_mavors_one_and_died(game_stats_service, player, achievement_servi def test_built_mavors_one_and_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._built_mavors(1, True, []) - achievement_service.unlock.assert_called_once_with(ACH_I_HAVE_A_CANON, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_I_HAVE_A_CANON, []) assert len(event_service.mock_calls) == 0 @@ -414,7 +410,7 @@ def test_lowest_acu_health_zero_died(game_stats_service, player, achievement_ser def test_lowest_acu_health_499_survived(game_stats_service, player, achievement_service, event_service): game_stats_service._lowest_acu_health(499, True, []) - achievement_service.unlock.assert_called_once_with(ACH_THAT_WAS_CLOSE, []) + achievement_service.unlock.assert_called_once_with(ach.ACH_THAT_WAS_CLOSE, []) assert len(event_service.mock_calls) == 0 @@ -433,8 +429,8 @@ def test_top_score_7_players(game_stats_service, achievement_service): def test_top_score_8_players(game_stats_service, achievement_service): game_stats_service._highscore(True, 8, []) - achievement_service.unlock.assert_any_call(ACH_TOP_SCORE, []) - achievement_service.increment.assert_any_call(ACH_UNBEATABLE, 1, []) + achievement_service.unlock.assert_any_call(ach.ACH_TOP_SCORE, []) + achievement_service.increment.assert_any_call(ach.ACH_UNBEATABLE, 1, []) assert len(achievement_service.mock_calls) == 2 async def test_process_game_stats_abort_processing_if_no_army_result(game_stats_service, game, player, achievement_service, event_service): diff --git a/tests/unit_tests/test_gameconnection.py b/tests/unit_tests/test_gameconnection.py index e1a35e8b5..fccd4a253 100644 --- a/tests/unit_tests/test_gameconnection.py +++ b/tests/unit_tests/test_gameconnection.py @@ -105,13 +105,15 @@ async def test_handle_action_GameState_lobby_calls_ConnectToPeer( game.host = players.hosting game.map_file_path = 'maps/some_map.zip' game.map_folder_name = 'some_map' - game.connections = [players.peer.game_connection] + peer_conn = mock.Mock() + players.peer.game_connection = peer_conn + game.connections = [peer_conn] await game_connection.handle_action('GameState', ['Lobby']) # Give the connection coro time to run await asyncio.sleep(0.1) - game_connection.connect_to_peer.assert_called_with(players.peer.game_connection) + game_connection.connect_to_peer.assert_called_with(peer_conn) async def test_handle_action_GameState_launching_calls_launch( diff --git a/tests/unit_tests/test_ladder.py b/tests/unit_tests/test_ladder.py index cceb6f83f..a80966363 100644 --- a/tests/unit_tests/test_ladder.py +++ b/tests/unit_tests/test_ladder.py @@ -4,16 +4,20 @@ import pytest from server import GameService, LadderService from server.matchmaker import Search -from server.players import Player, PlayerState +from server.players import PlayerState from tests import CoroMock -async def test_start_game(ladder_service: LadderService, game_service: GameService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p2 = mock.create_autospec(Player('Rhiza', player_id=2)) +async def test_start_game(ladder_service: LadderService, game_service: + GameService, player_factory): + p1 = player_factory('Dostya', player_id=1) + p2 = player_factory('Rhiza', player_id=2) + + mock_lc1 = mock.Mock() + mock_lc2 = mock.Mock() + p1.lobby_connection = mock_lc1 + p2.lobby_connection = mock_lc2 - p1.id = 1 - p2.id = 2 game_service.ladder_maps = [(1, 'scmp_007', 'maps/scmp_007.zip')] with mock.patch('server.games.game.Game.await_hosted', CoroMock()): @@ -23,12 +27,16 @@ async def test_start_game(ladder_service: LadderService, game_service: GameServi assert p2.lobby_connection.launch_game.called -async def test_start_game_timeout(ladder_service: LadderService, game_service: GameService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p2 = mock.create_autospec(Player('Rhiza', player_id=2)) +async def test_start_game_timeout(ladder_service: LadderService, game_service: + GameService, player_factory): + p1 = player_factory('Dostya', player_id=1) + p2 = player_factory('Rhiza', player_id=2) + + mock_lc1 = mock.Mock() + mock_lc2 = mock.Mock() + p1.lobby_connection = mock_lc1 + p2.lobby_connection = mock_lc2 - p1.id = 1 - p2.id = 2 game_service.ladder_maps = [(1, 'scmp_007', 'maps/scmp_007.zip')] with mock.patch('server.games.game.Game.sleep', CoroMock()): @@ -41,9 +49,11 @@ async def test_start_game_timeout(ladder_service: LadderService, game_service: G assert p2.lobby_connection.launch_game.called -def test_inform_player(ladder_service: LadderService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p1.ladder_rating = (1500, 500) +def test_inform_player(ladder_service: LadderService, player_factory): + p1 = player_factory('Dostya', player_id=1, ladder_rating=(1500, 500)) + + mock_lc = mock.Mock() + p1.lobby_connection = mock_lc ladder_service.inform_player(p1) @@ -60,11 +70,14 @@ def test_inform_player(ladder_service: LadderService): p1.lobby_connection.sendJSON.assert_called_once() -async def test_start_and_cancel_search(ladder_service: LadderService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p1.ladder_rating = (1500, 500) +async def test_start_and_cancel_search(ladder_service: LadderService, + player_factory): + p1 = player_factory('Dostya', player_id=1, ladder_rating=(1500, 500)) p1.ladder_games = 0 + mock_lc = mock.Mock() + p1.lobby_connection = mock_lc + search = Search([p1]) ladder_service.start_search(p1, search, 'ladder1v1') @@ -80,11 +93,14 @@ async def test_start_and_cancel_search(ladder_service: LadderService): assert search.is_cancelled -async def test_start_search_cancels_previous_search(ladder_service: LadderService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p1.ladder_rating = (1500, 500) +async def test_start_search_cancels_previous_search( + ladder_service: LadderService, player_factory): + p1 = player_factory('Dostya', player_id=1, ladder_rating=(1500, 500)) p1.ladder_games = 0 + mock_lc = mock.Mock() + p1.lobby_connection = mock_lc + search1 = Search([p1]) ladder_service.start_search(p1, search1, 'ladder1v1') @@ -104,11 +120,14 @@ async def test_start_search_cancels_previous_search(ladder_service: LadderServic assert ladder_service.queues['ladder1v1'].queue[search2] -async def test_cancel_all_searches(ladder_service: LadderService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p1.ladder_rating = (1500, 500) +async def test_cancel_all_searches(ladder_service: LadderService, + player_factory): + p1 = player_factory('Dostya', player_id=1, ladder_rating=(1500, 500)) p1.ladder_games = 0 + mock_lc = mock.Mock() + p1.lobby_connection = mock_lc + search = Search([p1]) ladder_service.start_search(p1, search, 'ladder1v1') @@ -125,15 +144,18 @@ async def test_cancel_all_searches(ladder_service: LadderService): assert p1 not in ladder_service.searches['ladder1v1'] -async def test_cancel_twice(ladder_service: LadderService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p1.ladder_rating = (1500, 500) +async def test_cancel_twice(ladder_service: LadderService, player_factory): + p1 = player_factory('Dostya', player_id=1, ladder_rating=(1500, 500)) p1.ladder_games = 0 - p2 = mock.create_autospec(Player('Brackman', player_id=1)) - p2.ladder_rating = (2000, 50) + p2 = player_factory('Brackman', player_id=2, ladder_rating=(2000, 500)) p2.ladder_games = 0 + mock_lc1 = mock.Mock() + mock_lc2 = mock.Mock() + p1.lobby_connection = mock_lc1 + p2.lobby_connection = mock_lc2 + search = Search([p1]) search2 = Search([p2]) @@ -153,15 +175,19 @@ async def test_cancel_twice(ladder_service: LadderService): assert searches == [search2] -async def test_start_game_called_on_match(ladder_service: LadderService): - p1 = mock.create_autospec(Player('Dostya', player_id=1)) - p1.ladder_rating = (2300, 64) +async def test_start_game_called_on_match(ladder_service: LadderService, + player_factory): + p1 = player_factory('Dostya', player_id=1, ladder_rating=(2300, 64)) p1.ladder_games = 0 - p2 = mock.create_autospec(Player('QAI', player_id=4)) - p2.ladder_rating = (2350, 125) + p2 = player_factory('QAI', player_id=2, ladder_rating=(2350, 125)) p2.ladder_games = 0 + mock_lc1 = mock.Mock() + mock_lc2 = mock.Mock() + p1.lobby_connection = mock_lc1 + p2.lobby_connection = mock_lc2 + ladder_service.start_game = CoroMock() ladder_service.inform_player = mock.Mock() diff --git a/tests/unit_tests/test_laddergame.py b/tests/unit_tests/test_laddergame.py index 7e1973935..d44f54a4a 100644 --- a/tests/unit_tests/test_laddergame.py +++ b/tests/unit_tests/test_laddergame.py @@ -4,7 +4,6 @@ from sqlalchemy import text from server.games import LadderGame from server.games.game import GameState, ValidityState -from tests.unit_tests.conftest import add_players from tests.unit_tests.test_game import add_connected_players @@ -63,14 +62,14 @@ async def test_is_winner_on_draw(laddergame, players): assert laddergame.is_winner(players.joining) is False -async def test_rate_game(laddergame: LadderGame, db_engine): +async def test_rate_game(laddergame: LadderGame, db_engine, game_add_players): async with db_engine.acquire() as conn: # TODO remove as soon as we have isolated tests (transactions) await conn.execute("DELETE FROM game_player_stats WHERE gameId = %s", laddergame.id) await conn.execute("DELETE FROM game_stats WHERE id = %s", laddergame.id) laddergame.state = GameState.LOBBY - players = add_players(laddergame, 2) + players = game_add_players(laddergame, 2) laddergame.set_player_option(players[0].id, 'Team', 1) laddergame.set_player_option(players[1].id, 'Team', 2) player_1_old_mean = players[0].ladder_rating[0] @@ -101,14 +100,15 @@ async def test_rate_game(laddergame: LadderGame, db_engine): assert rows[1]['after_deviation'] < rows[0]['deviation'] -async def test_persist_rating_victory(laddergame: LadderGame, db_engine): +async def test_persist_rating_victory(laddergame: LadderGame, db_engine, + game_add_players): async with db_engine.acquire() as conn: # TODO remove as soon as we have isolated tests (transactions) await conn.execute("DELETE FROM game_player_stats WHERE gameId = %s", laddergame.id) await conn.execute("DELETE FROM game_stats WHERE id = %s", laddergame.id) laddergame.state = GameState.LOBBY - players = add_players(laddergame, 2) + players = game_add_players(laddergame, 2) laddergame.set_player_option(players[0].id, 'Team', 1) laddergame.set_player_option(players[1].id, 'Team', 2) diff --git a/tests/unit_tests/test_lobbyconnection.py b/tests/unit_tests/test_lobbyconnection.py index 438514bff..e22c4ae46 100644 --- a/tests/unit_tests/test_lobbyconnection.py +++ b/tests/unit_tests/test_lobbyconnection.py @@ -47,8 +47,8 @@ def test_game_info_invalid(): @pytest.fixture -def mock_player(): - return mock.create_autospec(Player(login='Dummy', player_id=42)) +def mock_player(player_factory): + return player_factory(login='Dummy', player_id=42) @pytest.fixture @@ -126,7 +126,7 @@ def test_command_game_host_creates_game(lobbyconnection, test_game_info, players): lobbyconnection.player = players.hosting - players.hosting.in_game = False + del players.hosting.game lobbyconnection.protocol = mock.Mock() lobbyconnection.command_game_host(test_game_info) expected_call = { @@ -141,10 +141,10 @@ def test_command_game_host_creates_game(lobbyconnection, .assert_called_with(**expected_call) -def test_launch_game(lobbyconnection, game, create_player): +def test_launch_game(lobbyconnection, game, player_factory): old_game_conn = mock.Mock() - lobbyconnection.player = create_player() + lobbyconnection.player = player_factory() lobbyconnection.game_connection = old_game_conn lobbyconnection.sendJSON = mock.Mock() lobbyconnection.launch_game(game) @@ -166,7 +166,7 @@ def test_command_game_host_creates_correct_game( lobbyconnection.game_service = game_service lobbyconnection.launch_game = mock.Mock() - players.hosting.in_game = False + del players.hosting.game lobbyconnection.protocol = mock.Mock() lobbyconnection.command_game_host(test_game_info) args_list = lobbyconnection.launch_game.call_args_list @@ -190,7 +190,7 @@ def test_command_game_join_calls_join_game(mocker, game.id = 42 game_service.games[42] = game lobbyconnection.player = players.hosting - players.hosting.in_game = False + del players.hosting.game test_game_info['uid'] = 42 lobbyconnection.command_game_join(test_game_info) @@ -218,7 +218,7 @@ def test_command_game_join_uid_as_str(mocker, game.id = 42 game_service.games[42] = game lobbyconnection.player = players.hosting - players.hosting.in_game = False + del players.hosting.game test_game_info['uid'] = '42' # Pass in uid as string lobbyconnection.command_game_join(test_game_info) @@ -245,7 +245,7 @@ def test_command_game_join_without_password(lobbyconnection, game.id = 42 game_service.games[42] = game lobbyconnection.player = players.hosting - players.hosting.in_game = False + del players.hosting.game test_game_info['uid'] = 42 del test_game_info['password'] @@ -261,7 +261,7 @@ def test_command_game_join_game_not_found(lobbyconnection, lobbyconnection.sendJSON = mock.Mock() lobbyconnection.game_service = game_service lobbyconnection.player = players.hosting - players.hosting.in_game = False + del players.hosting.game test_game_info['uid'] = 42 lobbyconnection.command_game_join(test_game_info) @@ -717,7 +717,7 @@ async def test_broadcast(lobbyconnection: LobbyConnection, mocker): async def test_game_connection_not_restored_if_no_such_game_exists(lobbyconnection: LobbyConnection, mocker, mock_player): protocol = mocker.patch.object(lobbyconnection, 'protocol') lobbyconnection.player = mock_player - lobbyconnection.player.game_connection = None + del lobbyconnection.player.game_connection lobbyconnection.player.state = PlayerState.IDLE lobbyconnection.command_restore_game_session({'game_id': 123}) @@ -736,7 +736,7 @@ async def test_game_connection_not_restored_if_game_state_prohibits(lobbyconnect game_stats_service, game_state, mock_player, mocker): protocol = mocker.patch.object(lobbyconnection, 'protocol') lobbyconnection.player = mock_player - lobbyconnection.player.game_connection = None + del lobbyconnection.player.game_connection lobbyconnection.player.state = PlayerState.IDLE lobbyconnection.game_service = game_service game = mock.create_autospec(Game(42, game_service, game_stats_service)) @@ -762,7 +762,7 @@ async def test_game_connection_not_restored_if_game_state_prohibits(lobbyconnect async def test_game_connection_restored_if_game_exists(lobbyconnection: LobbyConnection, game_service: GameService, game_stats_service, game_state, mock_player): lobbyconnection.player = mock_player - lobbyconnection.player.game_connection = None + del lobbyconnection.player.game_connection lobbyconnection.player.state = PlayerState.IDLE lobbyconnection.game_service = game_service game = mock.create_autospec(Game(42, game_service, game_stats_service)) diff --git a/tests/unit_tests/test_matchmaker_queue.py b/tests/unit_tests/test_matchmaker_queue.py index 967dbe5fb..fdfa45997 100644 --- a/tests/unit_tests/test_matchmaker_queue.py +++ b/tests/unit_tests/test_matchmaker_queue.py @@ -16,22 +16,22 @@ def matchmaker_queue(game_service): @pytest.fixture -def matchmaker_players(): - return Player('Dostya', player_id=1, ladder_rating=(2300, 64), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Brackman', player_id=2, ladder_rating=(1200, 72), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Zoidberg', player_id=3, ladder_rating=(1300, 175), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('QAI', player_id=4, ladder_rating=(2350, 125), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Rhiza', player_id=5, ladder_rating=(1200, 175), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Newbie', player_id=6, ladder_rating=(1200, 175), ladder_games=(config.NEWBIE_MIN_GAMES - 1)) +def matchmaker_players(player_factory): + return player_factory('Dostya', player_id=1, ladder_rating=(2300, 64), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Brackman', player_id=2, ladder_rating=(1200, 72), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Zoidberg', player_id=3, ladder_rating=(1300, 175), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('QAI', player_id=4, ladder_rating=(2350, 125), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Rhiza', player_id=5, ladder_rating=(1200, 175), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Newbie', player_id=6, ladder_rating=(1200, 175), ladder_games=(config.NEWBIE_MIN_GAMES - 1)) @pytest.fixture -def matchmaker_players_all_match(): - return Player('Dostya', player_id=1, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Brackman', player_id=2, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Zoidberg', player_id=3, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('QAI', player_id=4, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Rhiza', player_id=5, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)) +def matchmaker_players_all_match(player_factory): + return player_factory('Dostya', player_id=1, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Brackman', player_id=2, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Zoidberg', player_id=3, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('QAI', player_id=4, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Rhiza', player_id=5, ladder_rating=(1500, 50), ladder_games=(config.NEWBIE_MIN_GAMES + 1)) def test_newbie_min_games(mocker, loop, matchmaker_players): @@ -160,10 +160,11 @@ async def test_shutdown_matchmaker(matchmaker_queue): assert False -async def test_queue_many(mocker, player_service, matchmaker_queue): - p1, p2, p3 = Player('Dostya', player_id=1, ladder_rating=(2200, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Brackman', player_id=2, ladder_rating=(1500, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Zoidberg', player_id=3, ladder_rating=(1500, 125), ladder_games=(config.NEWBIE_MIN_GAMES + 1)) +async def test_queue_many(mocker, player_service, matchmaker_queue, + player_factory): + p1, p2, p3 = player_factory('Dostya', player_id=1, ladder_rating=(2200, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Brackman', player_id=2, ladder_rating=(1500, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Zoidberg', player_id=3, ladder_rating=(1500, 125), ladder_games=(config.NEWBIE_MIN_GAMES + 1)) player_service.players = {p1.id: p1, p2.id: p2, p3.id: p3} s1 = Search([p1]) @@ -180,10 +181,11 @@ async def test_queue_many(mocker, player_service, matchmaker_queue): assert s3.is_matched -async def test_queue_race(mocker, player_service, matchmaker_queue): - p1, p2, p3 = Player('Dostya', player_id=1, ladder_rating=(2300, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Brackman', player_id=2, ladder_rating=(2200, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ - Player('Zoidberg', player_id=3, ladder_rating=(2300, 125), ladder_games=(config.NEWBIE_MIN_GAMES + 1)) +async def test_queue_race(mocker, player_service, matchmaker_queue, + player_factory): + p1, p2, p3 = player_factory('Dostya', player_id=1, ladder_rating=(2300, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Brackman', player_id=2, ladder_rating=(2200, 150), ladder_games=(config.NEWBIE_MIN_GAMES + 1)), \ + player_factory('Zoidberg', player_id=3, ladder_rating=(2300, 125), ladder_games=(config.NEWBIE_MIN_GAMES + 1)) player_service.players = {p1.id: p1, p2.id: p2, p3.id: p3}