Stardew Valley: Cut tests by 3 minutes (#2375)

* Stardew Valley: Test: unify mods

* Stardew Valley: Test: don't use SVTestBase where setUp is unused

* Stardew Valley: Test: remove duplicate backpack test

* Stardew Valley: Test: remove 2,3,4 heart tests

assume the math is correct with just 2 points on the curve

* Stardew Valley: Test: reduce duplicate test/gen runs

* Stardew Valley: Test: Change 'long' tests to not use TestBase

TestBase' setUp is not being used in the changed TestCases

* Stardew Valley: Test: Use subtests and inheritance for backpacks

* Stardew Valley: Test: add flag to skip some of the extensive tests by default
This commit is contained in:
black-sliver 2023-10-28 00:18:33 +02:00 committed by GitHub
parent c470849cee
commit e3112e5d51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 200 additions and 195 deletions

View File

@ -21,3 +21,11 @@ class ModNames:
ayeisha = "Ayeisha - The Postal Worker (Custom NPC)"
riley = "Custom NPC - Riley"
skull_cavern_elevator = "Skull Cavern Elevator"
all_mods = frozenset({ModNames.deepwoods, ModNames.tractor, ModNames.big_backpack,
ModNames.luck_skill, ModNames.magic, ModNames.socializing_skill, ModNames.archaeology,
ModNames.cooking_skill, ModNames.binning_skill, ModNames.juna,
ModNames.jasper, ModNames.alec, ModNames.yoba, ModNames.eugene,
ModNames.wellwick, ModNames.ginger, ModNames.shiko, ModNames.delores,
ModNames.ayeisha, ModNames.riley, ModNames.skull_cavern_elevator})

View File

@ -5,40 +5,41 @@ from .. import options
class TestBackpackVanilla(SVTestBase):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_vanilla}
def test_no_backpack_in_pool(self):
item_names = {item.name for item in self.multiworld.get_items()}
self.assertNotIn("Progressive Backpack", item_names)
def test_no_backpack(self):
with self.subTest("no items"):
item_names = {item.name for item in self.multiworld.get_items()}
self.assertNotIn("Progressive Backpack", item_names)
def test_no_backpack_locations(self):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertNotIn("Large Pack", location_names)
self.assertNotIn("Deluxe Pack", location_names)
with self.subTest("no locations"):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertNotIn("Large Pack", location_names)
self.assertNotIn("Deluxe Pack", location_names)
class TestBackpackProgressive(SVTestBase):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive}
def test_backpack_is_in_pool_2_times(self):
item_names = [item.name for item in self.multiworld.get_items()]
self.assertEqual(item_names.count("Progressive Backpack"), 2)
def test_backpack(self):
with self.subTest(check="has items"):
item_names = [item.name for item in self.multiworld.get_items()]
self.assertEqual(item_names.count("Progressive Backpack"), 2)
def test_2_backpack_locations(self):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertIn("Large Pack", location_names)
self.assertIn("Deluxe Pack", location_names)
with self.subTest(check="has locations"):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertIn("Large Pack", location_names)
self.assertIn("Deluxe Pack", location_names)
class TestBackpackEarlyProgressive(SVTestBase):
class TestBackpackEarlyProgressive(TestBackpackProgressive):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_early_progressive}
def test_backpack_is_in_pool_2_times(self):
item_names = [item.name for item in self.multiworld.get_items()]
self.assertEqual(item_names.count("Progressive Backpack"), 2)
@property
def run_default_tests(self) -> bool:
# EarlyProgressive is default
return False
def test_2_backpack_locations(self):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertIn("Large Pack", location_names)
self.assertIn("Deluxe Pack", location_names)
def test_backpack(self):
super().test_backpack()
def test_progressive_backpack_is_in_early_pool(self):
self.assertIn("Progressive Backpack", self.multiworld.early_items[1])
with self.subTest(check="is early"):
self.assertIn("Progressive Backpack", self.multiworld.early_items[1])

View File

@ -1,5 +1,8 @@
import typing
from BaseClasses import ItemClassification, MultiWorld
from . import setup_solo_multiworld, SVTestBase
from . import setup_solo_multiworld, SVTestBase, SVTestCase, allsanity_options_with_mods, \
allsanity_options_without_mods, minimal_locations_maximal_items
from .. import locations, items, location_table, options
from ..data.villagers_data import all_villagers_by_name, all_villagers_by_mod_by_name
from ..items import items_by_group, Group
@ -7,11 +10,11 @@ from ..locations import LocationTags
from ..mods.mod_data import ModNames
def get_real_locations(tester: SVTestBase, multiworld: MultiWorld):
def get_real_locations(tester: typing.Union[SVTestBase, SVTestCase], multiworld: MultiWorld):
return [location for location in multiworld.get_locations(tester.player) if not location.event]
def get_real_location_names(tester: SVTestBase, multiworld: MultiWorld):
def get_real_location_names(tester: typing.Union[SVTestBase, SVTestCase], multiworld: MultiWorld):
return [location.name for location in multiworld.get_locations(tester.player) if not location.event]
@ -115,21 +118,6 @@ class TestNoGingerIslandItemGeneration(SVTestBase):
self.assertTrue(count == 0 or count == 2)
class TestGivenProgressiveBackpack(SVTestBase):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive}
def test_when_generate_world_then_two_progressive_backpack_are_added(self):
self.assertEqual(self.multiworld.itempool.count(self.world.create_item("Progressive Backpack")), 2)
def test_when_generate_world_then_backpack_locations_are_added(self):
created_locations = {location.name for location in self.multiworld.get_locations(1)}
backpacks_exist = [location.name in created_locations
for location in locations.locations_by_tag[LocationTags.BACKPACK]
if location.name != "Premium Pack"]
all_exist = all(backpacks_exist)
self.assertTrue(all_exist)
class TestRemixedMineRewards(SVTestBase):
def test_when_generate_world_then_one_reward_is_added_per_chest(self):
# assert self.world.create_item("Rusty Sword") in self.multiworld.itempool
@ -205,17 +193,17 @@ class TestLocationGeneration(SVTestBase):
self.assertIn(location.name, location_table)
class TestLocationAndItemCount(SVTestBase):
class TestLocationAndItemCount(SVTestCase):
def test_minimal_location_maximal_items_still_valid(self):
min_max_options = self.minimal_locations_maximal_items()
min_max_options = minimal_locations_maximal_items()
multiworld = setup_solo_multiworld(min_max_options)
valid_locations = get_real_locations(self, multiworld)
self.assertGreaterEqual(len(valid_locations), len(multiworld.itempool))
def test_allsanity_without_mods_has_at_least_locations(self):
expected_locations = 994
allsanity_options = self.allsanity_options_without_mods()
allsanity_options = allsanity_options_without_mods()
multiworld = setup_solo_multiworld(allsanity_options)
number_locations = len(get_real_locations(self, multiworld))
self.assertGreaterEqual(number_locations, expected_locations)
@ -228,7 +216,7 @@ class TestLocationAndItemCount(SVTestBase):
def test_allsanity_with_mods_has_at_least_locations(self):
expected_locations = 1246
allsanity_options = self.allsanity_options_with_mods()
allsanity_options = allsanity_options_with_mods()
multiworld = setup_solo_multiworld(allsanity_options)
number_locations = len(get_real_locations(self, multiworld))
self.assertGreaterEqual(number_locations, expected_locations)
@ -245,6 +233,11 @@ class TestFriendsanityNone(SVTestBase):
options.Friendsanity.internal_name: options.Friendsanity.option_none,
}
@property
def run_default_tests(self) -> bool:
# None is default
return False
def test_no_friendsanity_items(self):
for item in self.multiworld.itempool:
self.assertFalse(item.name.endswith(" <3"))
@ -416,6 +409,7 @@ class TestFriendsanityAllNpcsWithMarriage(SVTestBase):
self.assertLessEqual(int(hearts), 10)
""" # Assuming math is correct if we check 2 points
class TestFriendsanityAllNpcsWithMarriageHeartSize2(SVTestBase):
options = {
options.Friendsanity.internal_name: options.Friendsanity.option_all_with_marriage,
@ -528,6 +522,7 @@ class TestFriendsanityAllNpcsWithMarriageHeartSize4(SVTestBase):
self.assertTrue(hearts == 4 or hearts == 8 or hearts == 12 or hearts == 14)
else:
self.assertTrue(hearts == 4 or hearts == 8 or hearts == 10)
"""
class TestFriendsanityAllNpcsWithMarriageHeartSize5(SVTestBase):

View File

@ -6,12 +6,12 @@ import random
from typing import Set
from BaseClasses import ItemClassification, MultiWorld
from . import setup_solo_multiworld, SVTestBase
from . import setup_solo_multiworld, SVTestCase, allsanity_options_without_mods
from .. import ItemData, StardewValleyWorld
from ..items import Group, item_table
class TestItems(SVTestBase):
class TestItems(SVTestCase):
def test_can_create_item_of_resource_pack(self):
item_name = "Resource Pack: 500 Money"
@ -46,7 +46,7 @@ class TestItems(SVTestBase):
def test_correct_number_of_stardrops(self):
seed = random.randrange(sys.maxsize)
allsanity_options = self.allsanity_options_without_mods()
allsanity_options = allsanity_options_without_mods()
multiworld = setup_solo_multiworld(allsanity_options, seed=seed)
stardrop_items = [item for item in multiworld.get_items() if "Stardrop" in item.name]
self.assertEqual(len(stardrop_items), 5)

View File

@ -1,10 +1,11 @@
import itertools
import unittest
from random import random
from typing import Dict
from BaseClasses import ItemClassification, MultiWorld
from Options import SpecialRange
from . import setup_solo_multiworld, SVTestBase
from . import setup_solo_multiworld, SVTestBase, SVTestCase, allsanity_options_without_mods, allsanity_options_with_mods
from .. import StardewItem, items_by_group, Group, StardewValleyWorld
from ..locations import locations_by_tag, LocationTags, location_table
from ..options import ExcludeGingerIsland, ToolProgression, Goal, SeasonRandomization, TrapItems, SpecialOrderLocations, ArcadeMachineLocations
@ -17,21 +18,21 @@ SEASONS = {Season.spring, Season.summer, Season.fall, Season.winter}
TOOLS = {"Hoe", "Pickaxe", "Axe", "Watering Can", "Trash Can", "Fishing Rod"}
def assert_can_win(tester: SVTestBase, multiworld: MultiWorld):
def assert_can_win(tester: unittest.TestCase, multiworld: MultiWorld):
for item in multiworld.get_items():
multiworld.state.collect(item)
tester.assertTrue(multiworld.find_item("Victory", 1).can_reach(multiworld.state))
def basic_checks(tester: SVTestBase, multiworld: MultiWorld):
def basic_checks(tester: unittest.TestCase, multiworld: MultiWorld):
tester.assertIn(StardewItem("Victory", ItemClassification.progression, None, 1), multiworld.get_items())
assert_can_win(tester, multiworld)
non_event_locations = [location for location in multiworld.get_locations() if not location.event]
tester.assertEqual(len(multiworld.itempool), len(non_event_locations))
def check_no_ginger_island(tester: SVTestBase, multiworld: MultiWorld):
def check_no_ginger_island(tester: unittest.TestCase, multiworld: MultiWorld):
ginger_island_items = [item_data.name for item_data in items_by_group[Group.GINGER_ISLAND]]
ginger_island_locations = [location_data.name for location_data in locations_by_tag[LocationTags.GINGER_ISLAND]]
for item in multiworld.get_items():
@ -48,9 +49,9 @@ def get_option_choices(option) -> Dict[str, int]:
return {}
class TestGenerateDynamicOptions(SVTestBase):
class TestGenerateDynamicOptions(SVTestCase):
def test_given_special_range_when_generate_then_basic_checks(self):
options = self.world.options_dataclass.type_hints
options = StardewValleyWorld.options_dataclass.type_hints
for option_name, option in options.items():
if not isinstance(option, SpecialRange):
continue
@ -62,7 +63,7 @@ class TestGenerateDynamicOptions(SVTestBase):
def test_given_choice_when_generate_then_basic_checks(self):
seed = int(random() * pow(10, 18) - 1)
options = self.world.options_dataclass.type_hints
options = StardewValleyWorld.options_dataclass.type_hints
for option_name, option in options.items():
if not option.options:
continue
@ -73,7 +74,7 @@ class TestGenerateDynamicOptions(SVTestBase):
basic_checks(self, multiworld)
class TestGoal(SVTestBase):
class TestGoal(SVTestCase):
def test_given_goal_when_generate_then_victory_is_in_correct_location(self):
for goal, location in [("community_center", GoalName.community_center),
("grandpa_evaluation", GoalName.grandpa_evaluation),
@ -90,7 +91,7 @@ class TestGoal(SVTestBase):
self.assertEqual(victory.name, location)
class TestSeasonRandomization(SVTestBase):
class TestSeasonRandomization(SVTestCase):
def test_given_disabled_when_generate_then_all_seasons_are_precollected(self):
world_options = {SeasonRandomization.internal_name: SeasonRandomization.option_disabled}
multi_world = setup_solo_multiworld(world_options)
@ -114,7 +115,7 @@ class TestSeasonRandomization(SVTestBase):
self.assertEqual(items.count(Season.progressive), 3)
class TestToolProgression(SVTestBase):
class TestToolProgression(SVTestCase):
def test_given_vanilla_when_generate_then_no_tool_in_pool(self):
world_options = {ToolProgression.internal_name: ToolProgression.option_vanilla}
multi_world = setup_solo_multiworld(world_options)
@ -147,9 +148,9 @@ class TestToolProgression(SVTestBase):
self.assertIn("Purchase Iridium Rod", locations)
class TestGenerateAllOptionsWithExcludeGingerIsland(SVTestBase):
class TestGenerateAllOptionsWithExcludeGingerIsland(SVTestCase):
def test_given_special_range_when_generate_exclude_ginger_island(self):
options = self.world.options_dataclass.type_hints
options = StardewValleyWorld.options_dataclass.type_hints
for option_name, option in options.items():
if not isinstance(option, SpecialRange) or option_name == ExcludeGingerIsland.internal_name:
continue
@ -162,7 +163,7 @@ class TestGenerateAllOptionsWithExcludeGingerIsland(SVTestBase):
def test_given_choice_when_generate_exclude_ginger_island(self):
seed = int(random() * pow(10, 18) - 1)
options = self.world.options_dataclass.type_hints
options = StardewValleyWorld.options_dataclass.type_hints
for option_name, option in options.items():
if not option.options or option_name == ExcludeGingerIsland.internal_name:
continue
@ -191,9 +192,9 @@ class TestGenerateAllOptionsWithExcludeGingerIsland(SVTestBase):
basic_checks(self, multiworld)
class TestTraps(SVTestBase):
class TestTraps(SVTestCase):
def test_given_no_traps_when_generate_then_no_trap_in_pool(self):
world_options = self.allsanity_options_without_mods()
world_options = allsanity_options_without_mods()
world_options.update({TrapItems.internal_name: TrapItems.option_no_traps})
multi_world = setup_solo_multiworld(world_options)
@ -209,7 +210,7 @@ class TestTraps(SVTestBase):
for value in trap_option.options:
if value == "no_traps":
continue
world_options = self.allsanity_options_with_mods()
world_options = allsanity_options_with_mods()
world_options.update({TrapItems.internal_name: trap_option.options[value]})
multi_world = setup_solo_multiworld(world_options)
trap_items = [item_data.name for item_data in items_by_group[Group.TRAP] if Group.DEPRECATED not in item_data.groups and item_data.mod_name is None]
@ -219,7 +220,7 @@ class TestTraps(SVTestBase):
self.assertIn(item, multiworld_items)
class TestSpecialOrders(SVTestBase):
class TestSpecialOrders(SVTestCase):
def test_given_disabled_then_no_order_in_pool(self):
world_options = {SpecialOrderLocations.internal_name: SpecialOrderLocations.option_disabled}
multi_world = setup_solo_multiworld(world_options)

View File

@ -2,7 +2,7 @@ import random
import sys
import unittest
from . import SVTestBase, setup_solo_multiworld
from . import SVTestCase, setup_solo_multiworld
from .. import options, StardewValleyWorld, StardewValleyOptions
from ..options import EntranceRandomization, ExcludeGingerIsland
from ..regions import vanilla_regions, vanilla_connections, randomize_connections, RandomizationFlag
@ -88,7 +88,7 @@ class TestEntranceRando(unittest.TestCase):
f"Connections are duplicated in randomization. Seed = {seed}")
class TestEntranceClassifications(SVTestBase):
class TestEntranceClassifications(SVTestCase):
def test_non_progression_are_all_accessible_with_empty_inventory(self):
for option, flag in [(options.EntranceRandomization.option_pelican_town, RandomizationFlag.PELICAN_TOWN),

View File

@ -1,8 +1,10 @@
import os
import unittest
from argparse import Namespace
from typing import Dict, FrozenSet, Tuple, Any, ClassVar
from BaseClasses import MultiWorld
from Utils import cache_argsless
from test.TestBase import WorldTestBase
from test.general import gen_steps, setup_solo_multiworld as setup_base_solo_multiworld
from .. import StardewValleyWorld
@ -13,11 +15,17 @@ from ..options import Cropsanity, SkillProgression, SpecialOrderLocations, Frien
BundleRandomization, BundlePrice, FestivalLocations, FriendsanityHeartSize, ExcludeGingerIsland, TrapItems, Goal, Mods
class SVTestBase(WorldTestBase):
class SVTestCase(unittest.TestCase):
player: ClassVar[int] = 1
"""Set to False to not skip some 'extra' tests"""
skip_extra_tests: bool = True
"""Set to False to run tests that take long"""
skip_long_tests: bool = True
class SVTestBase(WorldTestBase, SVTestCase):
game = "Stardew Valley"
world: StardewValleyWorld
player: ClassVar[int] = 1
skip_long_tests: bool = True
def world_setup(self, *args, **kwargs):
super().world_setup(*args, **kwargs)
@ -34,66 +42,73 @@ class SVTestBase(WorldTestBase):
should_run_default_tests = is_not_stardew_test and super().run_default_tests
return should_run_default_tests
def minimal_locations_maximal_items(self):
min_max_options = {
SeasonRandomization.internal_name: SeasonRandomization.option_randomized,
Cropsanity.internal_name: Cropsanity.option_shuffled,
BackpackProgression.internal_name: BackpackProgression.option_vanilla,
ToolProgression.internal_name: ToolProgression.option_vanilla,
SkillProgression.internal_name: SkillProgression.option_vanilla,
BuildingProgression.internal_name: BuildingProgression.option_vanilla,
ElevatorProgression.internal_name: ElevatorProgression.option_vanilla,
ArcadeMachineLocations.internal_name: ArcadeMachineLocations.option_disabled,
SpecialOrderLocations.internal_name: SpecialOrderLocations.option_disabled,
HelpWantedLocations.internal_name: 0,
Fishsanity.internal_name: Fishsanity.option_none,
Museumsanity.internal_name: Museumsanity.option_none,
Friendsanity.internal_name: Friendsanity.option_none,
NumberOfMovementBuffs.internal_name: 12,
NumberOfLuckBuffs.internal_name: 12,
}
return min_max_options
def allsanity_options_without_mods(self):
allsanity = {
Goal.internal_name: Goal.option_perfection,
BundleRandomization.internal_name: BundleRandomization.option_shuffled,
BundlePrice.internal_name: BundlePrice.option_expensive,
SeasonRandomization.internal_name: SeasonRandomization.option_randomized,
Cropsanity.internal_name: Cropsanity.option_shuffled,
BackpackProgression.internal_name: BackpackProgression.option_progressive,
ToolProgression.internal_name: ToolProgression.option_progressive,
SkillProgression.internal_name: SkillProgression.option_progressive,
BuildingProgression.internal_name: BuildingProgression.option_progressive,
FestivalLocations.internal_name: FestivalLocations.option_hard,
ElevatorProgression.internal_name: ElevatorProgression.option_progressive,
ArcadeMachineLocations.internal_name: ArcadeMachineLocations.option_full_shuffling,
SpecialOrderLocations.internal_name: SpecialOrderLocations.option_board_qi,
HelpWantedLocations.internal_name: 56,
Fishsanity.internal_name: Fishsanity.option_all,
Museumsanity.internal_name: Museumsanity.option_all,
Friendsanity.internal_name: Friendsanity.option_all_with_marriage,
FriendsanityHeartSize.internal_name: 1,
NumberOfMovementBuffs.internal_name: 12,
NumberOfLuckBuffs.internal_name: 12,
ExcludeGingerIsland.internal_name: ExcludeGingerIsland.option_false,
TrapItems.internal_name: TrapItems.option_nightmare,
}
return allsanity
@cache_argsless
def minimal_locations_maximal_items():
min_max_options = {
SeasonRandomization.internal_name: SeasonRandomization.option_randomized,
Cropsanity.internal_name: Cropsanity.option_shuffled,
BackpackProgression.internal_name: BackpackProgression.option_vanilla,
ToolProgression.internal_name: ToolProgression.option_vanilla,
SkillProgression.internal_name: SkillProgression.option_vanilla,
BuildingProgression.internal_name: BuildingProgression.option_vanilla,
ElevatorProgression.internal_name: ElevatorProgression.option_vanilla,
ArcadeMachineLocations.internal_name: ArcadeMachineLocations.option_disabled,
SpecialOrderLocations.internal_name: SpecialOrderLocations.option_disabled,
HelpWantedLocations.internal_name: 0,
Fishsanity.internal_name: Fishsanity.option_none,
Museumsanity.internal_name: Museumsanity.option_none,
Friendsanity.internal_name: Friendsanity.option_none,
NumberOfMovementBuffs.internal_name: 12,
NumberOfLuckBuffs.internal_name: 12,
}
return min_max_options
@cache_argsless
def allsanity_options_without_mods():
allsanity = {
Goal.internal_name: Goal.option_perfection,
BundleRandomization.internal_name: BundleRandomization.option_shuffled,
BundlePrice.internal_name: BundlePrice.option_expensive,
SeasonRandomization.internal_name: SeasonRandomization.option_randomized,
Cropsanity.internal_name: Cropsanity.option_shuffled,
BackpackProgression.internal_name: BackpackProgression.option_progressive,
ToolProgression.internal_name: ToolProgression.option_progressive,
SkillProgression.internal_name: SkillProgression.option_progressive,
BuildingProgression.internal_name: BuildingProgression.option_progressive,
FestivalLocations.internal_name: FestivalLocations.option_hard,
ElevatorProgression.internal_name: ElevatorProgression.option_progressive,
ArcadeMachineLocations.internal_name: ArcadeMachineLocations.option_full_shuffling,
SpecialOrderLocations.internal_name: SpecialOrderLocations.option_board_qi,
HelpWantedLocations.internal_name: 56,
Fishsanity.internal_name: Fishsanity.option_all,
Museumsanity.internal_name: Museumsanity.option_all,
Friendsanity.internal_name: Friendsanity.option_all_with_marriage,
FriendsanityHeartSize.internal_name: 1,
NumberOfMovementBuffs.internal_name: 12,
NumberOfLuckBuffs.internal_name: 12,
ExcludeGingerIsland.internal_name: ExcludeGingerIsland.option_false,
TrapItems.internal_name: TrapItems.option_nightmare,
}
return allsanity
@cache_argsless
def allsanity_options_with_mods():
allsanity = {}
allsanity.update(allsanity_options_without_mods())
all_mods = (
ModNames.deepwoods, ModNames.tractor, ModNames.big_backpack,
ModNames.luck_skill, ModNames.magic, ModNames.socializing_skill, ModNames.archaeology,
ModNames.cooking_skill, ModNames.binning_skill, ModNames.juna,
ModNames.jasper, ModNames.alec, ModNames.yoba, ModNames.eugene,
ModNames.wellwick, ModNames.ginger, ModNames.shiko, ModNames.delores,
ModNames.ayeisha, ModNames.riley, ModNames.skull_cavern_elevator
)
allsanity.update({Mods.internal_name: all_mods})
return allsanity
def allsanity_options_with_mods(self):
allsanity = {}
allsanity.update(self.allsanity_options_without_mods())
all_mods = (
ModNames.deepwoods, ModNames.tractor, ModNames.big_backpack,
ModNames.luck_skill, ModNames.magic, ModNames.socializing_skill, ModNames.archaeology,
ModNames.cooking_skill, ModNames.binning_skill, ModNames.juna,
ModNames.jasper, ModNames.alec, ModNames.yoba, ModNames.eugene,
ModNames.wellwick, ModNames.ginger, ModNames.shiko, ModNames.delores,
ModNames.ayeisha, ModNames.riley, ModNames.skull_cavern_elevator
)
allsanity.update({Mods.internal_name: all_mods})
return allsanity
pre_generated_worlds = {}

View File

@ -1,8 +1,8 @@
import unittest
from typing import List
from BaseClasses import MultiWorld, ItemClassification
from ... import StardewItem
from .. import SVTestBase
def get_all_item_names(multiworld: MultiWorld) -> List[str]:
@ -13,21 +13,21 @@ def get_all_location_names(multiworld: MultiWorld) -> List[str]:
return [location.name for location in multiworld.get_locations() if not location.event]
def assert_victory_exists(tester: SVTestBase, multiworld: MultiWorld):
def assert_victory_exists(tester: unittest.TestCase, multiworld: MultiWorld):
tester.assertIn(StardewItem("Victory", ItemClassification.progression, None, 1), multiworld.get_items())
def collect_all_then_assert_can_win(tester: SVTestBase, multiworld: MultiWorld):
def collect_all_then_assert_can_win(tester: unittest.TestCase, multiworld: MultiWorld):
for item in multiworld.get_items():
multiworld.state.collect(item)
tester.assertTrue(multiworld.find_item("Victory", 1).can_reach(multiworld.state))
def assert_can_win(tester: SVTestBase, multiworld: MultiWorld):
def assert_can_win(tester: unittest.TestCase, multiworld: MultiWorld):
assert_victory_exists(tester, multiworld)
collect_all_then_assert_can_win(tester, multiworld)
def assert_same_number_items_locations(tester: SVTestBase, multiworld: MultiWorld):
def assert_same_number_items_locations(tester: unittest.TestCase, multiworld: MultiWorld):
non_event_locations = [location for location in multiworld.get_locations() if not location.event]
tester.assertEqual(len(multiworld.itempool), len(non_event_locations))

View File

@ -1,23 +1,17 @@
import unittest
from typing import List, Union
from BaseClasses import MultiWorld
from worlds.stardew_valley.mods.mod_data import ModNames
from worlds.stardew_valley.mods.mod_data import all_mods
from worlds.stardew_valley.test import setup_solo_multiworld
from worlds.stardew_valley.test.TestOptions import basic_checks, SVTestBase
from worlds.stardew_valley.test.TestOptions import basic_checks, SVTestCase
from worlds.stardew_valley.items import item_table
from worlds.stardew_valley.locations import location_table
from worlds.stardew_valley.options import Mods
from .option_names import options_to_include
all_mods = frozenset({ModNames.deepwoods, ModNames.tractor, ModNames.big_backpack,
ModNames.luck_skill, ModNames.magic, ModNames.socializing_skill, ModNames.archaeology,
ModNames.cooking_skill, ModNames.binning_skill, ModNames.juna,
ModNames.jasper, ModNames.alec, ModNames.yoba, ModNames.eugene,
ModNames.wellwick, ModNames.ginger, ModNames.shiko, ModNames.delores,
ModNames.ayeisha, ModNames.riley, ModNames.skull_cavern_elevator})
def check_stray_mod_items(chosen_mods: Union[List[str], str], tester: SVTestBase, multiworld: MultiWorld):
def check_stray_mod_items(chosen_mods: Union[List[str], str], tester: unittest.TestCase, multiworld: MultiWorld):
if isinstance(chosen_mods, str):
chosen_mods = [chosen_mods]
for multiworld_item in multiworld.get_items():
@ -30,7 +24,7 @@ def check_stray_mod_items(chosen_mods: Union[List[str], str], tester: SVTestBase
tester.assertTrue(location.mod_name is None or location.mod_name in chosen_mods)
class TestGenerateModsOptions(SVTestBase):
class TestGenerateModsOptions(SVTestCase):
def test_given_mod_pairs_when_generate_then_basic_checks(self):
if self.skip_long_tests:

View File

@ -1,13 +1,14 @@
import unittest
from typing import Dict
from BaseClasses import MultiWorld
from Options import SpecialRange
from .option_names import options_to_include
from worlds.stardew_valley.test.checks.world_checks import assert_can_win, assert_same_number_items_locations
from .. import setup_solo_multiworld, SVTestBase
from .. import setup_solo_multiworld, SVTestCase
def basic_checks(tester: SVTestBase, multiworld: MultiWorld):
def basic_checks(tester: unittest.TestCase, multiworld: MultiWorld):
assert_can_win(tester, multiworld)
assert_same_number_items_locations(tester, multiworld)
@ -20,7 +21,7 @@ def get_option_choices(option) -> Dict[str, int]:
return {}
class TestGenerateDynamicOptions(SVTestBase):
class TestGenerateDynamicOptions(SVTestCase):
def test_given_option_pair_when_generate_then_basic_checks(self):
if self.skip_long_tests:
return

View File

@ -4,7 +4,7 @@ import random
from BaseClasses import MultiWorld
from Options import SpecialRange, Range
from .option_names import options_to_include
from .. import setup_solo_multiworld, SVTestBase
from .. import setup_solo_multiworld, SVTestCase
from ..checks.goal_checks import assert_perfection_world_is_valid, assert_goal_world_is_valid
from ..checks.option_checks import assert_can_reach_island_if_should, assert_cropsanity_same_number_items_and_locations, \
assert_festivals_give_access_to_deluxe_scarecrow
@ -72,14 +72,14 @@ def generate_many_worlds(number_worlds: int, start_index: int) -> Dict[int, Mult
return multiworlds
def check_every_multiworld_is_valid(tester: SVTestBase, multiworlds: Dict[int, MultiWorld]):
def check_every_multiworld_is_valid(tester: SVTestCase, multiworlds: Dict[int, MultiWorld]):
for multiworld_id in multiworlds:
multiworld = multiworlds[multiworld_id]
with tester.subTest(f"Checking validity of world {multiworld_id}"):
check_multiworld_is_valid(tester, multiworld_id, multiworld)
def check_multiworld_is_valid(tester: SVTestBase, multiworld_id: int, multiworld: MultiWorld):
def check_multiworld_is_valid(tester: SVTestCase, multiworld_id: int, multiworld: MultiWorld):
assert_victory_exists(tester, multiworld)
assert_same_number_items_locations(tester, multiworld)
assert_goal_world_is_valid(tester, multiworld)
@ -88,7 +88,7 @@ def check_multiworld_is_valid(tester: SVTestBase, multiworld_id: int, multiworld
assert_festivals_give_access_to_deluxe_scarecrow(tester, multiworld)
class TestGenerateManyWorlds(SVTestBase):
class TestGenerateManyWorlds(SVTestCase):
def test_generate_many_worlds_then_check_results(self):
if self.skip_long_tests:
return

View File

@ -7,45 +7,40 @@ class TestBiggerBackpackVanilla(SVTestBase):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_vanilla,
options.Mods.internal_name: ModNames.big_backpack}
def test_no_backpack_in_pool(self):
item_names = {item.name for item in self.multiworld.get_items()}
self.assertNotIn("Progressive Backpack", item_names)
def test_no_backpack(self):
with self.subTest(check="no items"):
item_names = {item.name for item in self.multiworld.get_items()}
self.assertNotIn("Progressive Backpack", item_names)
def test_no_backpack_locations(self):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertNotIn("Large Pack", location_names)
self.assertNotIn("Deluxe Pack", location_names)
self.assertNotIn("Premium Pack", location_names)
with self.subTest(check="no locations"):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertNotIn("Large Pack", location_names)
self.assertNotIn("Deluxe Pack", location_names)
self.assertNotIn("Premium Pack", location_names)
class TestBiggerBackpackProgressive(SVTestBase):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive,
options.Mods.internal_name: ModNames.big_backpack}
def test_backpack_is_in_pool_3_times(self):
item_names = [item.name for item in self.multiworld.get_items()]
self.assertEqual(item_names.count("Progressive Backpack"), 3)
def test_backpack(self):
with self.subTest(check="has items"):
item_names = [item.name for item in self.multiworld.get_items()]
self.assertEqual(item_names.count("Progressive Backpack"), 3)
def test_3_backpack_locations(self):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertIn("Large Pack", location_names)
self.assertIn("Deluxe Pack", location_names)
self.assertIn("Premium Pack", location_names)
with self.subTest(check="has locations"):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertIn("Large Pack", location_names)
self.assertIn("Deluxe Pack", location_names)
self.assertIn("Premium Pack", location_names)
class TestBiggerBackpackEarlyProgressive(SVTestBase):
class TestBiggerBackpackEarlyProgressive(TestBiggerBackpackProgressive):
options = {options.BackpackProgression.internal_name: options.BackpackProgression.option_early_progressive,
options.Mods.internal_name: ModNames.big_backpack}
def test_backpack_is_in_pool_3_times(self):
item_names = [item.name for item in self.multiworld.get_items()]
self.assertEqual(item_names.count("Progressive Backpack"), 3)
def test_backpack(self):
super().test_backpack()
def test_3_backpack_locations(self):
location_names = {location.name for location in self.multiworld.get_locations()}
self.assertIn("Large Pack", location_names)
self.assertIn("Deluxe Pack", location_names)
self.assertIn("Premium Pack", location_names)
def test_progressive_backpack_is_in_early_pool(self):
self.assertIn("Progressive Backpack", self.multiworld.early_items[1])
with self.subTest(check="is early"):
self.assertIn("Progressive Backpack", self.multiworld.early_items[1])

View File

@ -4,24 +4,17 @@ import random
import sys
from BaseClasses import MultiWorld
from ...mods.mod_data import ModNames
from .. import setup_solo_multiworld
from ..TestOptions import basic_checks, SVTestBase
from ...mods.mod_data import all_mods
from .. import setup_solo_multiworld, SVTestBase, SVTestCase, allsanity_options_without_mods
from ..TestOptions import basic_checks
from ... import items, Group, ItemClassification
from ...regions import RandomizationFlag, create_final_connections, randomize_connections, create_final_regions
from ...items import item_table, items_by_group
from ...locations import location_table
from ...options import Mods, EntranceRandomization, Friendsanity, SeasonRandomization, SpecialOrderLocations, ExcludeGingerIsland, TrapItems
all_mods = frozenset({ModNames.deepwoods, ModNames.tractor, ModNames.big_backpack,
ModNames.luck_skill, ModNames.magic, ModNames.socializing_skill, ModNames.archaeology,
ModNames.cooking_skill, ModNames.binning_skill, ModNames.juna,
ModNames.jasper, ModNames.alec, ModNames.yoba, ModNames.eugene,
ModNames.wellwick, ModNames.ginger, ModNames.shiko, ModNames.delores,
ModNames.ayeisha, ModNames.riley, ModNames.skull_cavern_elevator})
def check_stray_mod_items(chosen_mods: Union[List[str], str], tester: SVTestBase, multiworld: MultiWorld):
def check_stray_mod_items(chosen_mods: Union[List[str], str], tester: unittest.TestCase, multiworld: MultiWorld):
if isinstance(chosen_mods, str):
chosen_mods = [chosen_mods]
for multiworld_item in multiworld.get_items():
@ -34,7 +27,7 @@ def check_stray_mod_items(chosen_mods: Union[List[str], str], tester: SVTestBase
tester.assertTrue(location.mod_name is None or location.mod_name in chosen_mods)
class TestGenerateModsOptions(SVTestBase):
class TestGenerateModsOptions(SVTestCase):
def test_given_single_mods_when_generate_then_basic_checks(self):
for mod in all_mods:
@ -50,6 +43,8 @@ class TestGenerateModsOptions(SVTestBase):
multiworld = setup_solo_multiworld({EntranceRandomization.internal_name: option, Mods: mod})
basic_checks(self, multiworld)
check_stray_mod_items(mod, self, multiworld)
if self.skip_extra_tests:
return # assume the rest will work as well
class TestBaseItemGeneration(SVTestBase):
@ -103,7 +98,7 @@ class TestNoGingerIslandModItemGeneration(SVTestBase):
self.assertIn(progression_item.name, all_created_items)
class TestModEntranceRando(unittest.TestCase):
class TestModEntranceRando(SVTestCase):
def test_mod_entrance_randomization(self):
@ -137,12 +132,12 @@ class TestModEntranceRando(unittest.TestCase):
f"Connections are duplicated in randomization. Seed = {seed}")
class TestModTraps(SVTestBase):
class TestModTraps(SVTestCase):
def test_given_traps_when_generate_then_all_traps_in_pool(self):
for value in TrapItems.options:
if value == "no_traps":
continue
world_options = self.allsanity_options_without_mods()
world_options = allsanity_options_without_mods()
world_options.update({TrapItems.internal_name: TrapItems.options[value], Mods: "Magic"})
multi_world = setup_solo_multiworld(world_options)
trap_items = [item_data.name for item_data in items_by_group[Group.TRAP] if Group.DEPRECATED not in item_data.groups]