Tests: assign the world to WorldTestBase, and a default player field (#2385)
* Tests: assign the World to WorldTestBase and add a player field (because I like typing self.player far more than random 1's all over the place) * more accurate docstring for world and multiworld * use self.player within the class
This commit is contained in:
parent
9805bf92e4
commit
3869a25944
|
@ -7,7 +7,7 @@ from argparse import Namespace
|
||||||
from Generate import get_seed_name
|
from Generate import get_seed_name
|
||||||
from test.general import gen_steps
|
from test.general import gen_steps
|
||||||
from worlds import AutoWorld
|
from worlds import AutoWorld
|
||||||
from worlds.AutoWorld import call_all
|
from worlds.AutoWorld import World, call_all
|
||||||
|
|
||||||
from BaseClasses import Location, MultiWorld, CollectionState, ItemClassification, Item
|
from BaseClasses import Location, MultiWorld, CollectionState, ItemClassification, Item
|
||||||
from worlds.alttp.Items import ItemFactory
|
from worlds.alttp.Items import ItemFactory
|
||||||
|
@ -105,9 +105,15 @@ class TestBase(unittest.TestCase):
|
||||||
|
|
||||||
class WorldTestBase(unittest.TestCase):
|
class WorldTestBase(unittest.TestCase):
|
||||||
options: typing.Dict[str, typing.Any] = {}
|
options: typing.Dict[str, typing.Any] = {}
|
||||||
|
"""Define options that should be used when setting up this TestBase."""
|
||||||
multiworld: MultiWorld
|
multiworld: MultiWorld
|
||||||
|
"""The constructed MultiWorld instance after setup."""
|
||||||
|
world: World
|
||||||
|
"""The constructed World instance after setup."""
|
||||||
|
player: typing.ClassVar[int] = 1
|
||||||
|
|
||||||
game: typing.ClassVar[str] # define game name in subclass, example "Secret of Evermore"
|
game: typing.ClassVar[str]
|
||||||
|
"""Define game name in subclass, example "Secret of Evermore"."""
|
||||||
auto_construct: typing.ClassVar[bool] = True
|
auto_construct: typing.ClassVar[bool] = True
|
||||||
""" automatically set up a world for each test in this class """
|
""" automatically set up a world for each test in this class """
|
||||||
memory_leak_tested: typing.ClassVar[bool] = False
|
memory_leak_tested: typing.ClassVar[bool] = False
|
||||||
|
@ -150,8 +156,8 @@ class WorldTestBase(unittest.TestCase):
|
||||||
if not hasattr(self, "game"):
|
if not hasattr(self, "game"):
|
||||||
raise NotImplementedError("didn't define game name")
|
raise NotImplementedError("didn't define game name")
|
||||||
self.multiworld = MultiWorld(1)
|
self.multiworld = MultiWorld(1)
|
||||||
self.multiworld.game[1] = self.game
|
self.multiworld.game[self.player] = self.game
|
||||||
self.multiworld.player_name = {1: "Tester"}
|
self.multiworld.player_name = {self.player: "Tester"}
|
||||||
self.multiworld.set_seed(seed)
|
self.multiworld.set_seed(seed)
|
||||||
self.multiworld.state = CollectionState(self.multiworld)
|
self.multiworld.state = CollectionState(self.multiworld)
|
||||||
random.seed(self.multiworld.seed)
|
random.seed(self.multiworld.seed)
|
||||||
|
@ -159,9 +165,10 @@ class WorldTestBase(unittest.TestCase):
|
||||||
args = Namespace()
|
args = Namespace()
|
||||||
for name, option in AutoWorld.AutoWorldRegister.world_types[self.game].options_dataclass.type_hints.items():
|
for name, option in AutoWorld.AutoWorldRegister.world_types[self.game].options_dataclass.type_hints.items():
|
||||||
setattr(args, name, {
|
setattr(args, name, {
|
||||||
1: option.from_any(self.options.get(name, getattr(option, "default")))
|
1: option.from_any(self.options.get(name, option.default))
|
||||||
})
|
})
|
||||||
self.multiworld.set_options(args)
|
self.multiworld.set_options(args)
|
||||||
|
self.world = self.multiworld.worlds[self.player]
|
||||||
for step in gen_steps:
|
for step in gen_steps:
|
||||||
call_all(self.multiworld, step)
|
call_all(self.multiworld, step)
|
||||||
|
|
||||||
|
@ -220,19 +227,19 @@ class WorldTestBase(unittest.TestCase):
|
||||||
|
|
||||||
def can_reach_location(self, location: str) -> bool:
|
def can_reach_location(self, location: str) -> bool:
|
||||||
"""Determines if the current state can reach the provided location name"""
|
"""Determines if the current state can reach the provided location name"""
|
||||||
return self.multiworld.state.can_reach(location, "Location", 1)
|
return self.multiworld.state.can_reach(location, "Location", self.player)
|
||||||
|
|
||||||
def can_reach_entrance(self, entrance: str) -> bool:
|
def can_reach_entrance(self, entrance: str) -> bool:
|
||||||
"""Determines if the current state can reach the provided entrance name"""
|
"""Determines if the current state can reach the provided entrance name"""
|
||||||
return self.multiworld.state.can_reach(entrance, "Entrance", 1)
|
return self.multiworld.state.can_reach(entrance, "Entrance", self.player)
|
||||||
|
|
||||||
def can_reach_region(self, region: str) -> bool:
|
def can_reach_region(self, region: str) -> bool:
|
||||||
"""Determines if the current state can reach the provided region name"""
|
"""Determines if the current state can reach the provided region name"""
|
||||||
return self.multiworld.state.can_reach(region, "Region", 1)
|
return self.multiworld.state.can_reach(region, "Region", self.player)
|
||||||
|
|
||||||
def count(self, item_name: str) -> int:
|
def count(self, item_name: str) -> int:
|
||||||
"""Returns the amount of an item currently in state"""
|
"""Returns the amount of an item currently in state"""
|
||||||
return self.multiworld.state.count(item_name, 1)
|
return self.multiworld.state.count(item_name, self.player)
|
||||||
|
|
||||||
def assertAccessDependency(self,
|
def assertAccessDependency(self,
|
||||||
locations: typing.List[str],
|
locations: typing.List[str],
|
||||||
|
@ -246,10 +253,11 @@ class WorldTestBase(unittest.TestCase):
|
||||||
self.collect_all_but(all_items, state)
|
self.collect_all_but(all_items, state)
|
||||||
if only_check_listed:
|
if only_check_listed:
|
||||||
for location in locations:
|
for location in locations:
|
||||||
self.assertFalse(state.can_reach(location, "Location", 1), f"{location} is reachable without {all_items}")
|
self.assertFalse(state.can_reach(location, "Location", self.player),
|
||||||
|
f"{location} is reachable without {all_items}")
|
||||||
else:
|
else:
|
||||||
for location in self.multiworld.get_locations():
|
for location in self.multiworld.get_locations():
|
||||||
loc_reachable = state.can_reach(location, "Location", 1)
|
loc_reachable = state.can_reach(location, "Location", self.player)
|
||||||
self.assertEqual(loc_reachable, location.name not in locations,
|
self.assertEqual(loc_reachable, location.name not in locations,
|
||||||
f"{location.name} is reachable without {all_items}" if loc_reachable
|
f"{location.name} is reachable without {all_items}" if loc_reachable
|
||||||
else f"{location.name} is not reachable without {all_items}")
|
else f"{location.name} is not reachable without {all_items}")
|
||||||
|
@ -258,7 +266,7 @@ class WorldTestBase(unittest.TestCase):
|
||||||
for item in items:
|
for item in items:
|
||||||
state.collect(item)
|
state.collect(item)
|
||||||
for location in locations:
|
for location in locations:
|
||||||
self.assertTrue(state.can_reach(location, "Location", 1),
|
self.assertTrue(state.can_reach(location, "Location", self.player),
|
||||||
f"{location} not reachable with {item_names}")
|
f"{location} not reachable with {item_names}")
|
||||||
for item in items:
|
for item in items:
|
||||||
state.remove(item)
|
state.remove(item)
|
||||||
|
@ -285,7 +293,7 @@ class WorldTestBase(unittest.TestCase):
|
||||||
if not (self.run_default_tests and self.constructed):
|
if not (self.run_default_tests and self.constructed):
|
||||||
return
|
return
|
||||||
with self.subTest("Game", game=self.game):
|
with self.subTest("Game", game=self.game):
|
||||||
excluded = self.multiworld.worlds[1].options.exclude_locations.value
|
excluded = self.multiworld.worlds[self.player].options.exclude_locations.value
|
||||||
state = self.multiworld.get_all_state(False)
|
state = self.multiworld.get_all_state(False)
|
||||||
for location in self.multiworld.get_locations():
|
for location in self.multiworld.get_locations():
|
||||||
if location.name not in excluded:
|
if location.name not in excluded:
|
||||||
|
@ -302,7 +310,7 @@ class WorldTestBase(unittest.TestCase):
|
||||||
return
|
return
|
||||||
with self.subTest("Game", game=self.game):
|
with self.subTest("Game", game=self.game):
|
||||||
state = CollectionState(self.multiworld)
|
state = CollectionState(self.multiworld)
|
||||||
locations = self.multiworld.get_reachable_locations(state, 1)
|
locations = self.multiworld.get_reachable_locations(state, self.player)
|
||||||
self.assertGreater(len(locations), 0,
|
self.assertGreater(len(locations), 0,
|
||||||
"Need to be able to reach at least one location to get started.")
|
"Need to be able to reach at least one location to get started.")
|
||||||
|
|
||||||
|
@ -328,7 +336,7 @@ class WorldTestBase(unittest.TestCase):
|
||||||
for location in sphere:
|
for location in sphere:
|
||||||
if location.item:
|
if location.item:
|
||||||
state.collect(location.item, True, location)
|
state.collect(location.item, True, location)
|
||||||
return self.multiworld.has_beaten_game(state, 1)
|
return self.multiworld.has_beaten_game(state, self.player)
|
||||||
|
|
||||||
with self.subTest("Game", game=self.game, seed=self.multiworld.seed):
|
with self.subTest("Game", game=self.game, seed=self.multiworld.seed):
|
||||||
distribute_items_restrictive(self.multiworld)
|
distribute_items_restrictive(self.multiworld)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from test.TestBase import WorldTestBase
|
from test.TestBase import WorldTestBase
|
||||||
|
from .. import MessengerWorld
|
||||||
|
|
||||||
|
|
||||||
class MessengerTestBase(WorldTestBase):
|
class MessengerTestBase(WorldTestBase):
|
||||||
game = "The Messenger"
|
game = "The Messenger"
|
||||||
player: int = 1
|
world: MessengerWorld
|
||||||
|
|
|
@ -12,5 +12,5 @@ class LocationsTest(MessengerTestBase):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def test_locations_exist(self) -> None:
|
def test_locations_exist(self) -> None:
|
||||||
for location in self.multiworld.worlds[1].location_name_to_id:
|
for location in self.world.location_name_to_id:
|
||||||
self.assertIsInstance(self.multiworld.get_location(location, self.player), MessengerLocation)
|
self.assertIsInstance(self.multiworld.get_location(location, self.player), MessengerLocation)
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ShopCostTest(MessengerTestBase):
|
||||||
self.assertFalse(self.can_reach_location(loc))
|
self.assertFalse(self.can_reach_location(loc))
|
||||||
|
|
||||||
def test_shop_prices(self) -> None:
|
def test_shop_prices(self) -> None:
|
||||||
prices: Dict[str, int] = self.multiworld.worlds[self.player].shop_prices
|
prices: Dict[str, int] = self.world.shop_prices
|
||||||
for loc, price in prices.items():
|
for loc, price in prices.items():
|
||||||
with self.subTest("prices", loc=loc):
|
with self.subTest("prices", loc=loc):
|
||||||
self.assertLessEqual(price, self.multiworld.get_location(f"The Shop - {loc}", self.player).cost)
|
self.assertLessEqual(price, self.multiworld.get_location(f"The Shop - {loc}", self.player).cost)
|
||||||
|
@ -51,7 +51,7 @@ class ShopCostMinTest(ShopCostTest):
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_shop_rules(self) -> None:
|
def test_shop_rules(self) -> None:
|
||||||
if self.multiworld.worlds[self.player].total_shards:
|
if self.world.total_shards:
|
||||||
super().test_shop_rules()
|
super().test_shop_rules()
|
||||||
else:
|
else:
|
||||||
for loc in SHOP_ITEMS:
|
for loc in SHOP_ITEMS:
|
||||||
|
@ -85,7 +85,7 @@ class PlandoTest(MessengerTestBase):
|
||||||
with self.subTest("has cost", loc=loc):
|
with self.subTest("has cost", loc=loc):
|
||||||
self.assertFalse(self.can_reach_location(loc))
|
self.assertFalse(self.can_reach_location(loc))
|
||||||
|
|
||||||
prices = self.multiworld.worlds[self.player].shop_prices
|
prices = self.world.shop_prices
|
||||||
for loc, price in prices.items():
|
for loc, price in prices.items():
|
||||||
with self.subTest("prices", loc=loc):
|
with self.subTest("prices", loc=loc):
|
||||||
if loc == "Karuta Plates":
|
if loc == "Karuta Plates":
|
||||||
|
@ -98,7 +98,7 @@ class PlandoTest(MessengerTestBase):
|
||||||
self.assertTrue(loc.replace("The Shop - ", "") in SHOP_ITEMS)
|
self.assertTrue(loc.replace("The Shop - ", "") in SHOP_ITEMS)
|
||||||
self.assertEqual(len(prices), len(SHOP_ITEMS))
|
self.assertEqual(len(prices), len(SHOP_ITEMS))
|
||||||
|
|
||||||
figures = self.multiworld.worlds[self.player].figurine_prices
|
figures = self.world.figurine_prices
|
||||||
for loc, price in figures.items():
|
for loc, price in figures.items():
|
||||||
with self.subTest("figure prices", loc=loc):
|
with self.subTest("figure prices", loc=loc):
|
||||||
if loc == "Barmath'azel Figurine":
|
if loc == "Barmath'azel Figurine":
|
||||||
|
|
|
@ -41,8 +41,8 @@ class HalfSealsRequired(MessengerTestBase):
|
||||||
def test_seals_amount(self) -> None:
|
def test_seals_amount(self) -> None:
|
||||||
"""Should have 45 power seals in the item pool and half that required"""
|
"""Should have 45 power seals in the item pool and half that required"""
|
||||||
self.assertEqual(self.multiworld.total_seals[self.player], 45)
|
self.assertEqual(self.multiworld.total_seals[self.player], 45)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 45)
|
self.assertEqual(self.world.total_seals, 45)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].required_seals, 22)
|
self.assertEqual(self.world.required_seals, 22)
|
||||||
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
|
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
|
||||||
required_seals = [seal for seal in total_seals
|
required_seals = [seal for seal in total_seals
|
||||||
if seal.classification == ItemClassification.progression_skip_balancing]
|
if seal.classification == ItemClassification.progression_skip_balancing]
|
||||||
|
@ -60,8 +60,8 @@ class ThirtyThirtySeals(MessengerTestBase):
|
||||||
def test_seals_amount(self) -> None:
|
def test_seals_amount(self) -> None:
|
||||||
"""Should have 30 power seals in the pool and 33 percent of that required."""
|
"""Should have 30 power seals in the pool and 33 percent of that required."""
|
||||||
self.assertEqual(self.multiworld.total_seals[self.player], 30)
|
self.assertEqual(self.multiworld.total_seals[self.player], 30)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 30)
|
self.assertEqual(self.world.total_seals, 30)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].required_seals, 10)
|
self.assertEqual(self.world.required_seals, 10)
|
||||||
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
|
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
|
||||||
required_seals = [seal for seal in total_seals
|
required_seals = [seal for seal in total_seals
|
||||||
if seal.classification == ItemClassification.progression_skip_balancing]
|
if seal.classification == ItemClassification.progression_skip_balancing]
|
||||||
|
@ -78,7 +78,7 @@ class MaxSealsNoShards(MessengerTestBase):
|
||||||
def test_seals_amount(self) -> None:
|
def test_seals_amount(self) -> None:
|
||||||
"""Should set total seals to 70 since shards aren't shuffled."""
|
"""Should set total seals to 70 since shards aren't shuffled."""
|
||||||
self.assertEqual(self.multiworld.total_seals[self.player], 85)
|
self.assertEqual(self.multiworld.total_seals[self.player], 85)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 70)
|
self.assertEqual(self.world.total_seals, 70)
|
||||||
|
|
||||||
|
|
||||||
class MaxSealsWithShards(MessengerTestBase):
|
class MaxSealsWithShards(MessengerTestBase):
|
||||||
|
@ -91,8 +91,8 @@ class MaxSealsWithShards(MessengerTestBase):
|
||||||
def test_seals_amount(self) -> None:
|
def test_seals_amount(self) -> None:
|
||||||
"""Should have 85 seals in the pool with all required and be a valid seed."""
|
"""Should have 85 seals in the pool with all required and be a valid seed."""
|
||||||
self.assertEqual(self.multiworld.total_seals[self.player], 85)
|
self.assertEqual(self.multiworld.total_seals[self.player], 85)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].total_seals, 85)
|
self.assertEqual(self.world.total_seals, 85)
|
||||||
self.assertEqual(self.multiworld.worlds[self.player].required_seals, 85)
|
self.assertEqual(self.world.required_seals, 85)
|
||||||
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
|
total_seals = [seal for seal in self.multiworld.itempool if seal.name == "Power Seal"]
|
||||||
required_seals = [seal for seal in total_seals
|
required_seals = [seal for seal in total_seals
|
||||||
if seal.classification == ItemClassification.progression_skip_balancing]
|
if seal.classification == ItemClassification.progression_skip_balancing]
|
||||||
|
|
Loading…
Reference in New Issue