diff --git a/worlds/stardew_valley/test/TestBackpack.py b/worlds/stardew_valley/test/TestBackpack.py index 378c90e4..bccafd15 100644 --- a/worlds/stardew_valley/test/TestBackpack.py +++ b/worlds/stardew_valley/test/TestBackpack.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from .. import options diff --git a/worlds/stardew_valley/test/TestBooksanity.py b/worlds/stardew_valley/test/TestBooksanity.py index c25924aa..f1678de0 100644 --- a/worlds/stardew_valley/test/TestBooksanity.py +++ b/worlds/stardew_valley/test/TestBooksanity.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from ..options import ExcludeGingerIsland, Booksanity, Shipsanity from ..strings.book_names import Book, LostBook diff --git a/worlds/stardew_valley/test/TestBundles.py b/worlds/stardew_valley/test/TestBundles.py index 091f39b2..5b70158f 100644 --- a/worlds/stardew_valley/test/TestBundles.py +++ b/worlds/stardew_valley/test/TestBundles.py @@ -1,6 +1,6 @@ import unittest -from . import SVTestBase +from .bases import SVTestBase from .. import BundleRandomization from ..data.bundle_data import all_bundle_items_except_money, quality_crops_items_thematic, quality_foraging_items, quality_fish_items from ..options import BundlePlando @@ -87,4 +87,3 @@ class TestRemixedAnywhereBundles(SVTestBase): for bundle_name in self.fish_bundle_names: with self.subTest(f"{bundle_name}"): self.assertIn(bundle_name, location_names) - diff --git a/worlds/stardew_valley/test/TestCrops.py b/worlds/stardew_valley/test/TestCrops.py index 53048259..bf8f4f71 100644 --- a/worlds/stardew_valley/test/TestCrops.py +++ b/worlds/stardew_valley/test/TestCrops.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from .. import options from ..strings.ap_names.transport_names import Transportation from ..strings.building_names import Building diff --git a/worlds/stardew_valley/test/TestDynamicGoals.py b/worlds/stardew_valley/test/TestDynamicGoals.py index b0e6d6c6..23f453e9 100644 --- a/worlds/stardew_valley/test/TestDynamicGoals.py +++ b/worlds/stardew_valley/test/TestDynamicGoals.py @@ -1,7 +1,7 @@ from typing import List, Tuple -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from .. import options, StardewItem from ..strings.ap_names.ap_weapon_names import APWeapon from ..strings.ap_names.transport_names import Transportation diff --git a/worlds/stardew_valley/test/TestFarmType.py b/worlds/stardew_valley/test/TestFarmType.py index 1bb4404a..2c4fe4ec 100644 --- a/worlds/stardew_valley/test/TestFarmType.py +++ b/worlds/stardew_valley/test/TestFarmType.py @@ -1,7 +1,7 @@ from collections import Counter -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from .. import options @@ -13,7 +13,7 @@ class TestStartInventoryStandardFarm(WorldAssertMixin, SVTestBase): def test_start_inventory_progressive_coops(self): start_items = Counter((i.name for i in self.multiworld.precollected_items[self.player])) items = Counter((i.name for i in self.multiworld.itempool)) - + self.assertIn("Progressive Coop", items) self.assertEqual(items["Progressive Coop"], 3) self.assertNotIn("Progressive Coop", start_items) diff --git a/worlds/stardew_valley/test/TestFill.py b/worlds/stardew_valley/test/TestFill.py index f8565f4f..2205c49c 100644 --- a/worlds/stardew_valley/test/TestFill.py +++ b/worlds/stardew_valley/test/TestFill.py @@ -1,5 +1,5 @@ -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from .options.presets import minimal_locations_maximal_items from .. import options from ..mods.mod_data import ModNames diff --git a/worlds/stardew_valley/test/TestFishsanity.py b/worlds/stardew_valley/test/TestFishsanity.py index c5d87c0f..953255c4 100644 --- a/worlds/stardew_valley/test/TestFishsanity.py +++ b/worlds/stardew_valley/test/TestFishsanity.py @@ -1,8 +1,8 @@ import unittest from typing import ClassVar, Set -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from ..content.feature import fishsanity from ..mods.mod_data import ModNames from ..options import Fishsanity, ExcludeGingerIsland, Mods, SpecialOrderLocations, Goal, QuestLocations diff --git a/worlds/stardew_valley/test/TestFriendsanity.py b/worlds/stardew_valley/test/TestFriendsanity.py index 842c0edd..a346df7d 100644 --- a/worlds/stardew_valley/test/TestFriendsanity.py +++ b/worlds/stardew_valley/test/TestFriendsanity.py @@ -2,7 +2,7 @@ import unittest from collections import Counter from typing import ClassVar, Set -from . import SVTestBase +from .bases import SVTestBase from ..content.feature import friendsanity from ..options import Friendsanity, FriendsanityHeartSize diff --git a/worlds/stardew_valley/test/TestGeneration.py b/worlds/stardew_valley/test/TestGeneration.py index 6d0846f8..1e843ea6 100644 --- a/worlds/stardew_valley/test/TestGeneration.py +++ b/worlds/stardew_valley/test/TestGeneration.py @@ -1,7 +1,7 @@ from typing import List from BaseClasses import ItemClassification, Item -from . import SVTestBase +from .bases import SVTestBase from .. import location_table, options, items from ..items import Group, ItemData, item_data from ..locations import LocationTags diff --git a/worlds/stardew_valley/test/TestItemLink.py b/worlds/stardew_valley/test/TestItemLink.py index f1c83461..c3029b60 100644 --- a/worlds/stardew_valley/test/TestItemLink.py +++ b/worlds/stardew_valley/test/TestItemLink.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from .. import options, item_table, Group max_iterations = 2000 diff --git a/worlds/stardew_valley/test/TestItems.py b/worlds/stardew_valley/test/TestItems.py index 1d6f9689..d4fa9e83 100644 --- a/worlds/stardew_valley/test/TestItems.py +++ b/worlds/stardew_valley/test/TestItems.py @@ -1,5 +1,5 @@ from BaseClasses import MultiWorld, get_seed, ItemClassification -from . import setup_solo_multiworld, SVTestCase, solo_multiworld +from .bases import SVTestCase, solo_multiworld, setup_solo_multiworld from .options.presets import allsanity_no_mods_6_x_x, get_minsanity_options from .. import StardewValleyWorld from ..items import Group, item_table diff --git a/worlds/stardew_valley/test/TestLogic.py b/worlds/stardew_valley/test/TestLogic.py index 7a6b81ea..047e0226 100644 --- a/worlds/stardew_valley/test/TestLogic.py +++ b/worlds/stardew_valley/test/TestLogic.py @@ -3,8 +3,8 @@ import unittest from unittest import TestCase, SkipTest from BaseClasses import MultiWorld -from . import setup_solo_multiworld from .assertion import RuleAssertMixin +from .bases import setup_solo_multiworld from .options.presets import allsanity_mods_6_x_x, minimal_locations_maximal_items from .. import StardewValleyWorld from ..data.bundle_data import all_bundle_items_except_money diff --git a/worlds/stardew_valley/test/TestMultiplePlayers.py b/worlds/stardew_valley/test/TestMultiplePlayers.py index d8db616f..3b571055 100644 --- a/worlds/stardew_valley/test/TestMultiplePlayers.py +++ b/worlds/stardew_valley/test/TestMultiplePlayers.py @@ -1,4 +1,4 @@ -from . import SVTestCase, setup_multiworld +from .bases import SVTestCase, setup_multiworld from .. import True_ from ..options import FestivalLocations, StartingMoney from ..strings.festival_check_names import FestivalCheck diff --git a/worlds/stardew_valley/test/TestNumberLocations.py b/worlds/stardew_valley/test/TestNumberLocations.py index 2ed52808..dd57a5e3 100644 --- a/worlds/stardew_valley/test/TestNumberLocations.py +++ b/worlds/stardew_valley/test/TestNumberLocations.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from .options.presets import default_6_x_x, allsanity_no_mods_6_x_x, allsanity_mods_6_x_x_exclude_disabled, get_minsanity_options, \ minimal_locations_maximal_items, minimal_locations_maximal_items_with_island from .. import location_table diff --git a/worlds/stardew_valley/test/TestOptionFlags.py b/worlds/stardew_valley/test/TestOptionFlags.py index 2833649e..d9301575 100644 --- a/worlds/stardew_valley/test/TestOptionFlags.py +++ b/worlds/stardew_valley/test/TestOptionFlags.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from .. import BuildingProgression from ..options import ToolProgression diff --git a/worlds/stardew_valley/test/TestOptions.py b/worlds/stardew_valley/test/TestOptions.py index 11b0a014..738753fe 100644 --- a/worlds/stardew_valley/test/TestOptions.py +++ b/worlds/stardew_valley/test/TestOptions.py @@ -3,8 +3,8 @@ from typing import ClassVar from BaseClasses import ItemClassification from test.param import classvar_matrix -from . import SVTestCase, solo_multiworld, SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestCase, SVTestBase, solo_multiworld from .options.option_names import all_option_choices from .options.presets import allsanity_no_mods_6_x_x, allsanity_mods_6_x_x from .. import items_by_group, Group diff --git a/worlds/stardew_valley/test/TestOptionsPairs.py b/worlds/stardew_valley/test/TestOptionsPairs.py index d489ab1f..addd748c 100644 --- a/worlds/stardew_valley/test/TestOptionsPairs.py +++ b/worlds/stardew_valley/test/TestOptionsPairs.py @@ -1,5 +1,5 @@ -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from .. import options diff --git a/worlds/stardew_valley/test/TestRandomWorlds.py b/worlds/stardew_valley/test/TestRandomWorlds.py index 550ae14b..0c4ad6ae 100644 --- a/worlds/stardew_valley/test/TestRandomWorlds.py +++ b/worlds/stardew_valley/test/TestRandomWorlds.py @@ -2,8 +2,8 @@ from typing import ClassVar from BaseClasses import MultiWorld, get_seed from test.param import classvar_matrix -from . import SVTestCase, skip_long_tests, solo_multiworld from .assertion import GoalAssertMixin, OptionAssertMixin, WorldAssertMixin +from .bases import skip_long_tests, SVTestCase, solo_multiworld from .options.option_names import generate_random_world_options diff --git a/worlds/stardew_valley/test/TestRegions.py b/worlds/stardew_valley/test/TestRegions.py index bd1b6729..07e3094f 100644 --- a/worlds/stardew_valley/test/TestRegions.py +++ b/worlds/stardew_valley/test/TestRegions.py @@ -3,7 +3,7 @@ import unittest from typing import Set from BaseClasses import get_seed -from . import SVTestCase +from .bases import SVTestCase from .options.utils import fill_dataclass_with_default from .. import create_content from ..options import EntranceRandomization, ExcludeGingerIsland, SkillProgression diff --git a/worlds/stardew_valley/test/TestStartInventory.py b/worlds/stardew_valley/test/TestStartInventory.py index dc44a1bb..43ee0e13 100644 --- a/worlds/stardew_valley/test/TestStartInventory.py +++ b/worlds/stardew_valley/test/TestStartInventory.py @@ -1,5 +1,5 @@ -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from .. import options diff --git a/worlds/stardew_valley/test/TestTraps.py b/worlds/stardew_valley/test/TestTraps.py index 9df07a6d..130674a3 100644 --- a/worlds/stardew_valley/test/TestTraps.py +++ b/worlds/stardew_valley/test/TestTraps.py @@ -1,7 +1,7 @@ import unittest -from . import SVTestBase from .assertion import WorldAssertMixin +from .bases import SVTestBase from .. import options, items_by_group, Group from ..options import TrapDistribution @@ -119,4 +119,3 @@ class TestDistributionIsRespectedAllTraps(WorldAssertMixin, SVTestBase): self.assertLess(num_bark, num_debris - threshold_difference) self.assertGreater(num_meow, num_time_flies + threshold_difference) self.assertGreater(num_meow, num_debris + threshold_difference) - diff --git a/worlds/stardew_valley/test/TestWalnutsanity.py b/worlds/stardew_valley/test/TestWalnutsanity.py index 5cc2f79e..e3411edd 100644 --- a/worlds/stardew_valley/test/TestWalnutsanity.py +++ b/worlds/stardew_valley/test/TestWalnutsanity.py @@ -1,4 +1,4 @@ -from . import SVTestBase +from .bases import SVTestBase from ..options import ExcludeGingerIsland, Walnutsanity, ToolProgression, SkillProgression from ..strings.ap_names.ap_option_names import WalnutsanityOptionName diff --git a/worlds/stardew_valley/test/__init__.py b/worlds/stardew_valley/test/__init__.py index 6a8011a3..e69de29b 100644 --- a/worlds/stardew_valley/test/__init__.py +++ b/worlds/stardew_valley/test/__init__.py @@ -1,308 +0,0 @@ -import itertools -import logging -import os -import threading -import unittest -from contextlib import contextmanager -from typing import Dict, ClassVar, Iterable, Tuple, Optional, List, Union, Any - -from BaseClasses import MultiWorld, CollectionState, get_seed, Location, Item -from test.bases import WorldTestBase -from test.general import gen_steps, setup_solo_multiworld as setup_base_solo_multiworld -from worlds.AutoWorld import call_all -from .assertion import RuleAssertMixin -from .options.utils import fill_namespace_with_default, parse_class_option_keys, fill_dataclass_with_default -from .. import StardewValleyWorld, StardewItem, StardewRule -from ..logic.time_logic import MONTH_COEFFICIENT -from ..options import StardewValleyOption, options - -logger = logging.getLogger(__name__) - -DEFAULT_TEST_SEED = get_seed() -logger.info(f"Default Test Seed: {DEFAULT_TEST_SEED}") - - -def skip_default_tests() -> bool: - return not bool(os.environ.get("base", False)) - - -def skip_long_tests() -> bool: - return not bool(os.environ.get("long", False)) - - -class SVTestCase(unittest.TestCase): - skip_default_tests: bool = skip_default_tests() - """Set False to not skip the base fill tests""" - skip_long_tests: bool = skip_long_tests() - """Set False to run tests that take long""" - - @contextmanager - def solo_world_sub_test(self, msg: Optional[str] = None, - /, - world_options: Optional[Dict[Union[str, StardewValleyOption], Any]] = None, - *, - seed=DEFAULT_TEST_SEED, - world_caching=True, - **kwargs) -> Tuple[MultiWorld, StardewValleyWorld]: - if msg is not None: - msg += " " - else: - msg = "" - msg += f"[Seed = {seed}]" - - with self.subTest(msg, **kwargs): - with solo_multiworld(world_options, seed=seed, world_caching=world_caching) as (multiworld, world): - yield multiworld, world - - -class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase): - game = "Stardew Valley" - world: StardewValleyWorld - player: ClassVar[int] = 1 - - seed = DEFAULT_TEST_SEED - - @classmethod - def setUpClass(cls) -> None: - if cls is SVTestBase: - raise unittest.SkipTest("No running tests on SVTestBase import.") - - super().setUpClass() - - def world_setup(self, *args, **kwargs): - self.options = parse_class_option_keys(self.options) - - self.multiworld = setup_solo_multiworld(self.options, seed=self.seed) - self.multiworld.lock.acquire() - world = self.multiworld.worlds[self.player] - - self.original_state = self.multiworld.state.copy() - self.original_itempool = self.multiworld.itempool.copy() - self.unfilled_locations = self.multiworld.get_unfilled_locations(1) - if self.constructed: - self.world = world # noqa - - def tearDown(self) -> None: - self.multiworld.state = self.original_state - self.multiworld.itempool = self.original_itempool - for location in self.unfilled_locations: - location.item = None - - self.multiworld.lock.release() - - @property - def run_default_tests(self) -> bool: - if self.skip_default_tests: - return False - return super().run_default_tests - - def collect_months(self, months: int) -> None: - real_total_prog_items = self.world.total_progression_items - percent = months * MONTH_COEFFICIENT - self.collect("Stardrop", real_total_prog_items * 100 // percent) - self.world.total_progression_items = real_total_prog_items - - def collect_lots_of_money(self, percent: float = 0.25): - self.collect("Shipping Bin") - real_total_prog_items = self.world.total_progression_items - required_prog_items = int(round(real_total_prog_items * percent)) - self.collect("Stardrop", required_prog_items) - - def collect_all_the_money(self): - self.collect_lots_of_money(0.95) - - def collect_everything(self): - non_event_items = [item for item in self.multiworld.get_items() if item.code] - for item in non_event_items: - self.multiworld.state.collect(item) - - def collect_all_except(self, item_to_not_collect: str): - non_event_items = [item for item in self.multiworld.get_items() if item.code] - for item in non_event_items: - if item.name != item_to_not_collect: - self.multiworld.state.collect(item) - - def get_real_locations(self) -> List[Location]: - return [location for location in self.multiworld.get_locations(self.player) if location.address is not None] - - def get_real_location_names(self) -> List[str]: - return [location.name for location in self.get_real_locations()] - - def collect(self, item: Union[str, Item, Iterable[Item]], count: int = 1) -> Union[None, Item, List[Item]]: - assert count > 0 - - if not isinstance(item, str): - super().collect(item) - return - - if count == 1: - item = self.create_item(item) - self.multiworld.state.collect(item) - return item - - items = [] - for i in range(count): - item = self.create_item(item) - self.multiworld.state.collect(item) - items.append(item) - - return items - - def create_item(self, item: str) -> StardewItem: - return self.world.create_item(item) - - def get_all_created_items(self) -> list[str]: - return [item.name for item in itertools.chain(self.multiworld.get_items(), self.multiworld.precollected_items[self.player])] - - def remove_one_by_name(self, item: str) -> None: - self.remove(self.create_item(item)) - - def reset_collection_state(self) -> None: - self.multiworld.state = self.original_state.copy() - - def assert_rule_true(self, rule: StardewRule, state: CollectionState | None = None) -> None: - if state is None: - state = self.multiworld.state - super().assert_rule_true(rule, state) - - def assert_rule_false(self, rule: StardewRule, state: CollectionState | None = None) -> None: - if state is None: - state = self.multiworld.state - super().assert_rule_false(rule, state) - - def assert_can_reach_location(self, location: Location | str, state: CollectionState | None = None) -> None: - if state is None: - state = self.multiworld.state - super().assert_can_reach_location(location, state) - - def assert_cannot_reach_location(self, location: Location | str, state: CollectionState | None = None) -> None: - if state is None: - state = self.multiworld.state - super().assert_cannot_reach_location(location, state) - - -pre_generated_worlds = {} - - -@contextmanager -def solo_multiworld(world_options: Optional[Dict[Union[str, StardewValleyOption], Any]] = None, - *, - seed=DEFAULT_TEST_SEED, - world_caching=True) -> Tuple[MultiWorld, StardewValleyWorld]: - if not world_caching: - multiworld = setup_solo_multiworld(world_options, seed, _cache={}) - yield multiworld, multiworld.worlds[1] - else: - multiworld = setup_solo_multiworld(world_options, seed) - try: - multiworld.lock.acquire() - world = multiworld.worlds[1] - - original_state = multiworld.state.copy() - original_itempool = multiworld.itempool.copy() - unfilled_locations = multiworld.get_unfilled_locations(1) - - yield multiworld, world - - multiworld.state = original_state - multiworld.itempool = original_itempool - for location in unfilled_locations: - location.item = None - finally: - multiworld.lock.release() - - -# Mostly a copy of test.general.setup_solo_multiworld, I just don't want to change the core. -def setup_solo_multiworld(test_options: Optional[Dict[Union[str, StardewValleyOption], str]] = None, - seed=DEFAULT_TEST_SEED, - _cache: Dict[frozenset, MultiWorld] = {}, # noqa - _steps=gen_steps) -> MultiWorld: - test_options = parse_class_option_keys(test_options) - - # Yes I reuse the worlds generated between tests, its speeds the execution by a couple seconds - # If the simple dict caching ends up taking too much memory, we could replace it with some kind of lru cache. - should_cache = should_cache_world(test_options) - if should_cache: - frozen_options = make_hashable(test_options, seed) - cached_multi_world = search_world_cache(_cache, frozen_options) - if cached_multi_world: - print(f"Using cached solo multi world [Seed = {cached_multi_world.seed}] [Cache size = {len(_cache)}]") - return cached_multi_world - - multiworld = setup_base_solo_multiworld(StardewValleyWorld, (), seed=seed) - # print(f"Seed: {multiworld.seed}") # Uncomment to print the seed for every test - - args = fill_namespace_with_default(test_options) - multiworld.set_options(args) - - if "start_inventory" in test_options: - for item, amount in test_options["start_inventory"].items(): - for _ in range(amount): - multiworld.push_precollected(multiworld.create_item(item, 1)) - - for step in _steps: - call_all(multiworld, step) - - if should_cache: - add_to_world_cache(_cache, frozen_options, multiworld) # noqa - - # Lock is needed for multi-threading tests - setattr(multiworld, "lock", threading.Lock()) - - return multiworld - - -def should_cache_world(test_options): - if "start_inventory" in test_options: - return False - - trap_distribution_key = "trap_distribution" - if trap_distribution_key not in test_options: - return True - - trap_distribution = test_options[trap_distribution_key] - for key in trap_distribution: - if trap_distribution[key] != options.TrapDistribution.default_weight: - return False - - return True - - - -def make_hashable(test_options, seed): - return frozenset(test_options.items()).union({("seed", seed)}) - - -def search_world_cache(cache: Dict[frozenset, MultiWorld], frozen_options: frozenset) -> Optional[MultiWorld]: - try: - return cache[frozen_options] - except KeyError: - for cached_options, multi_world in cache.items(): - if frozen_options.issubset(cached_options): - return multi_world - return None - - -def add_to_world_cache(cache: Dict[frozenset, MultiWorld], frozen_options: frozenset, multi_world: MultiWorld) -> None: - # We could complete the key with all the default options, but that does not seem to improve performances. - cache[frozen_options] = multi_world - - -def setup_multiworld(test_options: Iterable[Dict[str, int]] = None, seed=None) -> MultiWorld: # noqa - if test_options is None: - test_options = [] - - multiworld = MultiWorld(len(test_options)) - multiworld.player_name = {} - multiworld.set_seed(seed) - multiworld.state = CollectionState(multiworld) - for i in range(1, len(test_options) + 1): - multiworld.game[i] = StardewValleyWorld.game - multiworld.player_name.update({i: f"Tester{i}"}) - args = fill_namespace_with_default(test_options) - multiworld.set_options(args) - - for step in gen_steps: - call_all(multiworld, step) - - return multiworld diff --git a/worlds/stardew_valley/test/bases.py b/worlds/stardew_valley/test/bases.py new file mode 100644 index 00000000..64ada395 --- /dev/null +++ b/worlds/stardew_valley/test/bases.py @@ -0,0 +1,306 @@ +import itertools +import logging +import os +import threading +import typing +import unittest +from contextlib import contextmanager +from typing import Optional, Dict, Union, Any, List, Iterable + +from BaseClasses import get_seed, MultiWorld, Location, Item, CollectionState +from test.bases import WorldTestBase +from test.general import gen_steps, setup_solo_multiworld as setup_base_solo_multiworld +from worlds.AutoWorld import call_all +from .assertion import RuleAssertMixin +from .options.utils import parse_class_option_keys, fill_namespace_with_default +from .. import StardewValleyWorld, StardewItem, StardewRule +from ..logic.time_logic import MONTH_COEFFICIENT +from ..options import StardewValleyOption, options + +logger = logging.getLogger(__name__) +DEFAULT_TEST_SEED = get_seed() +logger.info(f"Default Test Seed: {DEFAULT_TEST_SEED}") + + +def skip_default_tests() -> bool: + return not bool(os.environ.get("base", False)) + + +def skip_long_tests() -> bool: + return not bool(os.environ.get("long", False)) + + +class SVTestCase(unittest.TestCase): + skip_default_tests: bool = skip_default_tests() + """Set False to not skip the base fill tests""" + skip_long_tests: bool = skip_long_tests() + """Set False to run tests that take long""" + + @contextmanager + def solo_world_sub_test(self, msg: str | None = None, + /, + world_options: dict[str | type[StardewValleyOption], Any] | None = None, + *, + seed=DEFAULT_TEST_SEED, + world_caching=True, + **kwargs) -> Iterable[tuple[MultiWorld, StardewValleyWorld]]: + if msg is not None: + msg += " " + else: + msg = "" + msg += f"[Seed = {seed}]" + + with self.subTest(msg, **kwargs): + with solo_multiworld(world_options, seed=seed, world_caching=world_caching) as (multiworld, world): + yield multiworld, world + + +class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase): + game = "Stardew Valley" + world: StardewValleyWorld + + seed = DEFAULT_TEST_SEED + + @classmethod + def setUpClass(cls) -> None: + if cls is SVTestBase: + raise unittest.SkipTest("No running tests on SVTestBase import.") + + super().setUpClass() + + def world_setup(self, *args, **kwargs): + self.options = parse_class_option_keys(self.options) + + self.multiworld = setup_solo_multiworld(self.options, seed=self.seed) + self.multiworld.lock.acquire() + world = self.multiworld.worlds[self.player] + + self.original_state = self.multiworld.state.copy() + self.original_itempool = self.multiworld.itempool.copy() + self.unfilled_locations = self.multiworld.get_unfilled_locations(1) + if self.constructed: + self.world = world # noqa + + def tearDown(self) -> None: + self.multiworld.state = self.original_state + self.multiworld.itempool = self.original_itempool + for location in self.unfilled_locations: + location.item = None + + self.multiworld.lock.release() + + @property + def run_default_tests(self) -> bool: + if self.skip_default_tests: + return False + return super().run_default_tests + + def collect_months(self, months: int) -> None: + real_total_prog_items = self.world.total_progression_items + percent = months * MONTH_COEFFICIENT + self.collect("Stardrop", real_total_prog_items * 100 // percent) + self.world.total_progression_items = real_total_prog_items + + def collect_lots_of_money(self, percent: float = 0.25): + self.collect("Shipping Bin") + real_total_prog_items = self.world.total_progression_items + required_prog_items = int(round(real_total_prog_items * percent)) + self.collect("Stardrop", required_prog_items) + + def collect_all_the_money(self): + self.collect_lots_of_money(0.95) + + def collect_everything(self): + non_event_items = [item for item in self.multiworld.get_items() if item.code] + for item in non_event_items: + self.multiworld.state.collect(item) + + def collect_all_except(self, item_to_not_collect: str): + non_event_items = [item for item in self.multiworld.get_items() if item.code] + for item in non_event_items: + if item.name != item_to_not_collect: + self.multiworld.state.collect(item) + + def get_real_locations(self) -> List[Location]: + return [location for location in self.multiworld.get_locations(self.player) if location.address is not None] + + def get_real_location_names(self) -> List[str]: + return [location.name for location in self.get_real_locations()] + + def collect(self, item: Union[str, Item, Iterable[Item]], count: int = 1) -> Union[None, Item, List[Item]]: + assert count > 0 + + if not isinstance(item, str): + super().collect(item) + return + + if count == 1: + item = self.create_item(item) + self.multiworld.state.collect(item) + return item + + items = [] + for i in range(count): + item = self.create_item(item) + self.multiworld.state.collect(item) + items.append(item) + + return items + + def create_item(self, item: str) -> StardewItem: + return self.world.create_item(item) + + def get_all_created_items(self) -> list[str]: + return [item.name for item in itertools.chain(self.multiworld.get_items(), self.multiworld.precollected_items[self.player])] + + def remove_one_by_name(self, item: str) -> None: + self.remove(self.create_item(item)) + + def reset_collection_state(self) -> None: + self.multiworld.state = self.original_state.copy() + + def assert_rule_true(self, rule: StardewRule, state: CollectionState | None = None) -> None: + if state is None: + state = self.multiworld.state + super().assert_rule_true(rule, state) + + def assert_rule_false(self, rule: StardewRule, state: CollectionState | None = None) -> None: + if state is None: + state = self.multiworld.state + super().assert_rule_false(rule, state) + + def assert_can_reach_location(self, location: Location | str, state: CollectionState | None = None) -> None: + if state is None: + state = self.multiworld.state + super().assert_can_reach_location(location, state) + + def assert_cannot_reach_location(self, location: Location | str, state: CollectionState | None = None) -> None: + if state is None: + state = self.multiworld.state + super().assert_cannot_reach_location(location, state) + + +pre_generated_worlds = {} + + +@contextmanager +def solo_multiworld(world_options: dict[str | type[StardewValleyOption], Any] | None = None, + *, + seed=DEFAULT_TEST_SEED, + world_caching=True) -> Iterable[tuple[MultiWorld, StardewValleyWorld]]: + if not world_caching: + multiworld = setup_solo_multiworld(world_options, seed, _cache={}) + yield multiworld, typing.cast(StardewValleyWorld, multiworld.worlds[1]) + else: + multiworld = setup_solo_multiworld(world_options, seed) + try: + multiworld.lock.acquire() + world = multiworld.worlds[1] + + original_state = multiworld.state.copy() + original_itempool = multiworld.itempool.copy() + unfilled_locations = multiworld.get_unfilled_locations(1) + + yield multiworld, typing.cast(StardewValleyWorld, world) + + multiworld.state = original_state + multiworld.itempool = original_itempool + for location in unfilled_locations: + location.item = None + finally: + multiworld.lock.release() + + +# Mostly a copy of test.general.setup_solo_multiworld, I just don't want to change the core. +def setup_solo_multiworld(test_options: Optional[Dict[Union[str, StardewValleyOption], str]] = None, + seed=DEFAULT_TEST_SEED, + _cache: Dict[frozenset, MultiWorld] = {}, # noqa + _steps=gen_steps) -> MultiWorld: + test_options = parse_class_option_keys(test_options) + + # Yes I reuse the worlds generated between tests, its speeds the execution by a couple seconds + # If the simple dict caching ends up taking too much memory, we could replace it with some kind of lru cache. + should_cache = should_cache_world(test_options) + if should_cache: + frozen_options = make_hashable(test_options, seed) + cached_multi_world = search_world_cache(_cache, frozen_options) + if cached_multi_world: + print(f"Using cached solo multi world [Seed = {cached_multi_world.seed}] [Cache size = {len(_cache)}]") + return cached_multi_world + + multiworld = setup_base_solo_multiworld(StardewValleyWorld, (), seed=seed) + # print(f"Seed: {multiworld.seed}") # Uncomment to print the seed for every test + + args = fill_namespace_with_default(test_options) + multiworld.set_options(args) + + if "start_inventory" in test_options: + for item, amount in test_options["start_inventory"].items(): + for _ in range(amount): + multiworld.push_precollected(multiworld.create_item(item, 1)) + + for step in _steps: + call_all(multiworld, step) + + if should_cache: + add_to_world_cache(_cache, frozen_options, multiworld) # noqa + + # Lock is needed for multi-threading tests + setattr(multiworld, "lock", threading.Lock()) + + return multiworld + + +def should_cache_world(test_options): + if "start_inventory" in test_options: + return False + + trap_distribution_key = "trap_distribution" + if trap_distribution_key not in test_options: + return True + + trap_distribution = test_options[trap_distribution_key] + for key in trap_distribution: + if trap_distribution[key] != options.TrapDistribution.default_weight: + return False + + return True + + +def make_hashable(test_options, seed): + return frozenset(test_options.items()).union({("seed", seed)}) + + +def search_world_cache(cache: Dict[frozenset, MultiWorld], frozen_options: frozenset) -> Optional[MultiWorld]: + try: + return cache[frozen_options] + except KeyError: + for cached_options, multi_world in cache.items(): + if frozen_options.issubset(cached_options): + return multi_world + return None + + +def add_to_world_cache(cache: Dict[frozenset, MultiWorld], frozen_options: frozenset, multi_world: MultiWorld) -> None: + # We could complete the key with all the default options, but that does not seem to improve performances. + cache[frozen_options] = multi_world + + +def setup_multiworld(test_options: Iterable[Dict[str, int]] = None, seed=None) -> MultiWorld: # noqa + if test_options is None: + test_options = [] + + multiworld = MultiWorld(len(test_options)) + multiworld.player_name = {} + multiworld.set_seed(seed) + multiworld.state = CollectionState(multiworld) + for i in range(1, len(test_options) + 1): + multiworld.game[i] = StardewValleyWorld.game + multiworld.player_name.update({i: f"Tester{i}"}) + args = fill_namespace_with_default(test_options) + multiworld.set_options(args) + + for step in gen_steps: + call_all(multiworld, step) + + return multiworld diff --git a/worlds/stardew_valley/test/content/TestGingerIsland.py b/worlds/stardew_valley/test/content/TestGingerIsland.py index 7e7f866d..c1f16b48 100644 --- a/worlds/stardew_valley/test/content/TestGingerIsland.py +++ b/worlds/stardew_valley/test/content/TestGingerIsland.py @@ -1,5 +1,5 @@ from . import SVContentPackTestBase -from .. import SVTestBase +from ..bases import SVTestBase from ... import options from ...content import content_packs from ...data.artisan import MachineSource diff --git a/worlds/stardew_valley/test/content/mods/TestSVE.py b/worlds/stardew_valley/test/content/mods/TestSVE.py index 4065498d..7cd0a822 100644 --- a/worlds/stardew_valley/test/content/mods/TestSVE.py +++ b/worlds/stardew_valley/test/content/mods/TestSVE.py @@ -1,5 +1,5 @@ from .. import SVContentPackTestBase -from ... import SVTestBase +from ...bases import SVTestBase from .... import options from ....content import content_packs from ....mods.mod_data import ModNames diff --git a/worlds/stardew_valley/test/long/TestModsLong.py b/worlds/stardew_valley/test/long/TestModsLong.py index bc5e8bff..d14af8bc 100644 --- a/worlds/stardew_valley/test/long/TestModsLong.py +++ b/worlds/stardew_valley/test/long/TestModsLong.py @@ -4,8 +4,8 @@ from typing import ClassVar from BaseClasses import get_seed from test.param import classvar_matrix -from .. import SVTestCase, solo_multiworld, skip_long_tests from ..assertion import WorldAssertMixin, ModAssertMixin +from ..bases import skip_long_tests, SVTestCase, solo_multiworld from ..options.option_names import all_option_choices from ... import options from ...mods.mod_data import ModNames diff --git a/worlds/stardew_valley/test/long/TestOptionsLong.py b/worlds/stardew_valley/test/long/TestOptionsLong.py index db467964..3c9690e2 100644 --- a/worlds/stardew_valley/test/long/TestOptionsLong.py +++ b/worlds/stardew_valley/test/long/TestOptionsLong.py @@ -4,8 +4,8 @@ from typing import ClassVar from BaseClasses import get_seed from test.param import classvar_matrix -from .. import SVTestCase, solo_multiworld, skip_long_tests from ..assertion.world_assert import WorldAssertMixin +from ..bases import skip_long_tests, SVTestCase, solo_multiworld from ..options.option_names import all_option_choices from ... import options diff --git a/worlds/stardew_valley/test/long/TestPreRolledRandomness.py b/worlds/stardew_valley/test/long/TestPreRolledRandomness.py index 3b6f818e..3d3e0da1 100644 --- a/worlds/stardew_valley/test/long/TestPreRolledRandomness.py +++ b/worlds/stardew_valley/test/long/TestPreRolledRandomness.py @@ -3,8 +3,8 @@ from typing import ClassVar from BaseClasses import get_seed from test.param import classvar_matrix -from .. import SVTestCase, solo_multiworld, skip_long_tests from ..assertion import WorldAssertMixin +from ..bases import skip_long_tests, SVTestCase, solo_multiworld from ... import options if skip_long_tests(): diff --git a/worlds/stardew_valley/test/mods/TestBiggerBackpack.py b/worlds/stardew_valley/test/mods/TestBiggerBackpack.py index f6d31297..8ec2e539 100644 --- a/worlds/stardew_valley/test/mods/TestBiggerBackpack.py +++ b/worlds/stardew_valley/test/mods/TestBiggerBackpack.py @@ -1,4 +1,4 @@ -from .. import SVTestBase +from ..bases import SVTestBase from ...mods.mod_data import ModNames from ...options import Mods, BackpackProgression diff --git a/worlds/stardew_valley/test/mods/TestMods.py b/worlds/stardew_valley/test/mods/TestMods.py index bd5d7d62..be6ce710 100644 --- a/worlds/stardew_valley/test/mods/TestMods.py +++ b/worlds/stardew_valley/test/mods/TestMods.py @@ -3,9 +3,9 @@ from typing import ClassVar from BaseClasses import get_seed from test.param import classvar_matrix -from .. import SVTestBase, SVTestCase, solo_multiworld from ..TestGeneration import get_all_permanent_progression_items from ..assertion import ModAssertMixin, WorldAssertMixin +from ..bases import SVTestCase, SVTestBase, solo_multiworld from ..options.presets import allsanity_mods_6_x_x from ..options.utils import fill_dataclass_with_default from ... import options, Group, create_content diff --git a/worlds/stardew_valley/test/mods/TestModsFill.py b/worlds/stardew_valley/test/mods/TestModsFill.py index a140f5ab..334a4ff9 100644 --- a/worlds/stardew_valley/test/mods/TestModsFill.py +++ b/worlds/stardew_valley/test/mods/TestModsFill.py @@ -1,4 +1,4 @@ -from .. import SVTestBase +from ..bases import SVTestBase from ... import options diff --git a/worlds/stardew_valley/test/mods/TestSVE.py b/worlds/stardew_valley/test/mods/TestSVE.py index ca63dcb3..a6b6f6a3 100644 --- a/worlds/stardew_valley/test/mods/TestSVE.py +++ b/worlds/stardew_valley/test/mods/TestSVE.py @@ -1,4 +1,4 @@ -from .. import SVTestBase +from ..bases import SVTestBase from ... import options from ...mods.mod_data import ModNames from ...strings.ap_names.mods.mod_items import SVEQuestItem diff --git a/worlds/stardew_valley/test/options/TestPresets.py b/worlds/stardew_valley/test/options/TestPresets.py index 5d9e8953..5c1cee4a 100644 --- a/worlds/stardew_valley/test/options/TestPresets.py +++ b/worlds/stardew_valley/test/options/TestPresets.py @@ -1,5 +1,5 @@ from Options import PerGameCommonOptions, OptionSet, OptionDict -from .. import SVTestCase +from ..bases import SVTestCase from ...options import StardewValleyOptions, TrapItems from ...options.presets import sv_options_presets diff --git a/worlds/stardew_valley/test/performance/TestPerformance.py b/worlds/stardew_valley/test/performance/TestPerformance.py index ca63ee5e..2951e6d0 100644 --- a/worlds/stardew_valley/test/performance/TestPerformance.py +++ b/worlds/stardew_valley/test/performance/TestPerformance.py @@ -8,7 +8,7 @@ from typing import List from BaseClasses import get_seed from Fill import distribute_items_restrictive, balance_multiworld_progression from worlds import AutoWorld -from .. import SVTestCase, setup_multiworld +from ..bases import SVTestCase, setup_multiworld from ..options.presets import default_6_x_x, allsanity_no_mods_6_x_x, allsanity_mods_6_x_x, minimal_locations_maximal_items assert default_6_x_x diff --git a/worlds/stardew_valley/test/rules/TestArcades.py b/worlds/stardew_valley/test/rules/TestArcades.py index 5fdf7df1..407f2999 100644 --- a/worlds/stardew_valley/test/rules/TestArcades.py +++ b/worlds/stardew_valley/test/rules/TestArcades.py @@ -1,5 +1,5 @@ +from ..bases import SVTestBase from ... import options -from ...test import SVTestBase class TestArcadeMachinesLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestBooks.py b/worlds/stardew_valley/test/rules/TestBooks.py index 4cd84a77..eb26b274 100644 --- a/worlds/stardew_valley/test/rules/TestBooks.py +++ b/worlds/stardew_valley/test/rules/TestBooks.py @@ -1,5 +1,5 @@ +from ..bases import SVTestBase from ... import options -from ...test import SVTestBase class TestBooksLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestBuildings.py b/worlds/stardew_valley/test/rules/TestBuildings.py index 8eeb9d29..0b1f41d2 100644 --- a/worlds/stardew_valley/test/rules/TestBuildings.py +++ b/worlds/stardew_valley/test/rules/TestBuildings.py @@ -1,5 +1,5 @@ +from ..bases import SVTestBase from ...options import BuildingProgression, FarmType -from ...test import SVTestBase class TestBuildingLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestBundles.py b/worlds/stardew_valley/test/rules/TestBundles.py index 918cb8ab..357269a2 100644 --- a/worlds/stardew_valley/test/rules/TestBundles.py +++ b/worlds/stardew_valley/test/rules/TestBundles.py @@ -1,7 +1,7 @@ +from ..bases import SVTestBase from ... import options from ...options import BundleRandomization from ...strings.bundle_names import BundleName -from ...test import SVTestBase class TestBundlesLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestCookingRecipes.py b/worlds/stardew_valley/test/rules/TestCookingRecipes.py index b3aafdb6..b468a72d 100644 --- a/worlds/stardew_valley/test/rules/TestCookingRecipes.py +++ b/worlds/stardew_valley/test/rules/TestCookingRecipes.py @@ -1,6 +1,6 @@ +from ..bases import SVTestBase from ... import options from ...options import BuildingProgression, ExcludeGingerIsland, Chefsanity -from ...test import SVTestBase class TestRecipeLearnLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestCraftingRecipes.py b/worlds/stardew_valley/test/rules/TestCraftingRecipes.py index 94d6bc14..f875dc53 100644 --- a/worlds/stardew_valley/test/rules/TestCraftingRecipes.py +++ b/worlds/stardew_valley/test/rules/TestCraftingRecipes.py @@ -1,7 +1,7 @@ +from ..bases import SVTestBase from ... import options from ...data.craftable_data import all_crafting_recipes_by_name from ...options import BuildingProgression, ExcludeGingerIsland, Craftsanity, SeasonRandomization -from ...test import SVTestBase class TestCraftsanityLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestDonations.py b/worlds/stardew_valley/test/rules/TestDonations.py index d50f87d3..2cddcad3 100644 --- a/worlds/stardew_valley/test/rules/TestDonations.py +++ b/worlds/stardew_valley/test/rules/TestDonations.py @@ -1,8 +1,8 @@ +from ..bases import SVTestBase from ... import options from ...locations import locations_by_tag, LocationTags, location_table from ...strings.entrance_names import Entrance from ...strings.region_names import Region -from ...test import SVTestBase class TestDonationLogicAll(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestFishing.py b/worlds/stardew_valley/test/rules/TestFishing.py index 6a6a4bb3..36495923 100644 --- a/worlds/stardew_valley/test/rules/TestFishing.py +++ b/worlds/stardew_valley/test/rules/TestFishing.py @@ -1,6 +1,6 @@ +from ..bases import SVTestBase from ...options import SeasonRandomization, Fishsanity, ExcludeGingerIsland, SkillProgression, ToolProgression, ElevatorProgression, SpecialOrderLocations from ...strings.fish_names import Fish -from ...test import SVTestBase class TestNeedRegionToCatchFish(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestFriendship.py b/worlds/stardew_valley/test/rules/TestFriendship.py index 9cd3127a..dc593558 100644 --- a/worlds/stardew_valley/test/rules/TestFriendship.py +++ b/worlds/stardew_valley/test/rules/TestFriendship.py @@ -1,5 +1,5 @@ +from ..bases import SVTestBase from ...options import SeasonRandomization, Friendsanity, FriendsanityHeartSize -from ...test import SVTestBase class TestFriendsanityDatingRules(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestMuseum.py b/worlds/stardew_valley/test/rules/TestMuseum.py index 35dad8f4..231bbafe 100644 --- a/worlds/stardew_valley/test/rules/TestMuseum.py +++ b/worlds/stardew_valley/test/rules/TestMuseum.py @@ -1,7 +1,7 @@ from collections import Counter +from ..bases import SVTestBase from ...options import Museumsanity -from .. import SVTestBase class TestMuseumMilestones(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestShipping.py b/worlds/stardew_valley/test/rules/TestShipping.py index fc61ae8e..c1f29d93 100644 --- a/worlds/stardew_valley/test/rules/TestShipping.py +++ b/worlds/stardew_valley/test/rules/TestShipping.py @@ -1,6 +1,6 @@ +from ..bases import SVTestBase from ...locations import LocationTags, location_table from ...options import BuildingProgression, Shipsanity -from ...test import SVTestBase class TestShipsanityNone(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestSkills.py b/worlds/stardew_valley/test/rules/TestSkills.py index a5957488..fd513a1b 100644 --- a/worlds/stardew_valley/test/rules/TestSkills.py +++ b/worlds/stardew_valley/test/rules/TestSkills.py @@ -1,7 +1,7 @@ +from ..bases import SVTestBase from ... import HasProgressionPercent, StardewLogic from ...options import ToolProgression, SkillProgression, Mods from ...strings.skill_names import all_skills, all_vanilla_skills, Skill -from ...test import SVTestBase class TestSkillProgressionVanilla(SVTestBase): diff --git a/worlds/stardew_valley/test/rules/TestStateRules.py b/worlds/stardew_valley/test/rules/TestStateRules.py index db56e822..57573c7f 100644 --- a/worlds/stardew_valley/test/rules/TestStateRules.py +++ b/worlds/stardew_valley/test/rules/TestStateRules.py @@ -1,4 +1,4 @@ -from .. import SVTestBase +from ..bases import SVTestBase from ..options.presets import allsanity_mods_6_x_x from ...stardew_rule import HasProgressionPercent diff --git a/worlds/stardew_valley/test/rules/TestTools.py b/worlds/stardew_valley/test/rules/TestTools.py index bda29e3d..54b9ec8f 100644 --- a/worlds/stardew_valley/test/rules/TestTools.py +++ b/worlds/stardew_valley/test/rules/TestTools.py @@ -1,6 +1,6 @@ from collections import Counter -from .. import SVTestBase +from ..bases import SVTestBase from ... import options from ...options import ToolProgression, SeasonRandomization from ...strings.entrance_names import Entrance diff --git a/worlds/stardew_valley/test/rules/TestWeapons.py b/worlds/stardew_valley/test/rules/TestWeapons.py index 383f26e8..e95e706d 100644 --- a/worlds/stardew_valley/test/rules/TestWeapons.py +++ b/worlds/stardew_valley/test/rules/TestWeapons.py @@ -1,6 +1,6 @@ +from ..bases import SVTestBase from ... import options from ...options import ToolProgression -from ...test import SVTestBase class TestWeaponsLogic(SVTestBase): diff --git a/worlds/stardew_valley/test/script/benchmark_locations.py b/worlds/stardew_valley/test/script/benchmark_locations.py index 04553e39..3dcfc4db 100644 --- a/worlds/stardew_valley/test/script/benchmark_locations.py +++ b/worlds/stardew_valley/test/script/benchmark_locations.py @@ -15,8 +15,9 @@ import typing from BaseClasses import CollectionState, Location from Utils import init_logging -from worlds.stardew_valley.stardew_rule.rule_explain import explain -from ... import test +from ..bases import setup_solo_multiworld +from ..options import presets +from ...stardew_rule.rule_explain import explain def run_locations_benchmark(): @@ -56,12 +57,12 @@ def run_locations_benchmark(): parser.add_argument('--state', help="Define the state in which the location will be benchmarked.", type=str, default=None) args = parser.parse_args() options_set = args.options - options = getattr(test, options_set)() + options = getattr(presets, options_set)() seed = args.seed location = args.location state = args.state - multiworld = test.setup_solo_multiworld(options, seed) + multiworld = setup_solo_multiworld(options, seed) gc.collect() if location: diff --git a/worlds/stardew_valley/test/stability/StabilityOutputScript.py b/worlds/stardew_valley/test/stability/StabilityOutputScript.py index 9b4b608d..29fd9030 100644 --- a/worlds/stardew_valley/test/stability/StabilityOutputScript.py +++ b/worlds/stardew_valley/test/stability/StabilityOutputScript.py @@ -1,7 +1,7 @@ import argparse import json -from .. import setup_solo_multiworld +from ..bases import setup_solo_multiworld from ..options.presets import allsanity_mods_6_x_x_exclude_disabled from ...options import FarmType, EntranceRandomization diff --git a/worlds/stardew_valley/test/stability/TestStability.py b/worlds/stardew_valley/test/stability/TestStability.py index b4d0f30e..f3dfb9fd 100644 --- a/worlds/stardew_valley/test/stability/TestStability.py +++ b/worlds/stardew_valley/test/stability/TestStability.py @@ -5,7 +5,7 @@ import sys import unittest from BaseClasses import get_seed -from .. import SVTestCase +from ..bases import SVTestCase # at 0x102ca98a0> lambda_regex = re.compile(r"^ at (.*)>$") diff --git a/worlds/stardew_valley/test/stability/TestUniversalTracker.py b/worlds/stardew_valley/test/stability/TestUniversalTracker.py index 7590635a..301abfff 100644 --- a/worlds/stardew_valley/test/stability/TestUniversalTracker.py +++ b/worlds/stardew_valley/test/stability/TestUniversalTracker.py @@ -1,9 +1,11 @@ import unittest from unittest.mock import Mock -from .. import SVTestBase, fill_namespace_with_default, skip_long_tests +from ..bases import skip_long_tests, SVTestBase from ..options.presets import allsanity_mods_6_x_x -from ... import STARDEW_VALLEY, FarmType, BundleRandomization, EntranceRandomization +from ..options.utils import fill_namespace_with_default +from ... import STARDEW_VALLEY +from ...options import FarmType, BundleRandomization, EntranceRandomization @unittest.skipIf(skip_long_tests(), "Long tests disabled")