Tests: datapackage and more multiworld renaming (#1454)
* Tests: add a test that created items and locations exist in the datapackage * move FF validation to `assert_generate` and remove test exclusion * test created location addresses are correct * make the assertion proper and more verbose * make item count test ~~a bit faster~~ a lot nicer * 120 blaze it * name test multiworld setup better and fix another over 120 line in FFR
This commit is contained in:
parent
f078750b72
commit
8af7908cd0
|
@ -1,24 +1,24 @@
|
||||||
import unittest
|
import unittest
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
|
|
||||||
from . import setup_default_world
|
from . import setup_solo_multiworld
|
||||||
|
|
||||||
|
|
||||||
class TestImplemented(unittest.TestCase):
|
class TestImplemented(unittest.TestCase):
|
||||||
def testCompletionCondition(self):
|
def testCompletionCondition(self):
|
||||||
"""Ensure a completion condition is set that has requirements."""
|
"""Ensure a completion condition is set that has requirements."""
|
||||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
if not world_type.hidden and game_name not in {"ArchipIDLE", "Final Fantasy", "Sudoku"}:
|
if not world_type.hidden and game_name not in {"ArchipIDLE", "Sudoku"}:
|
||||||
with self.subTest(game_name):
|
with self.subTest(game_name):
|
||||||
multiworld = setup_default_world(world_type)
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
self.assertFalse(multiworld.completion_condition[1](multiworld.state))
|
self.assertFalse(multiworld.completion_condition[1](multiworld.state))
|
||||||
|
|
||||||
def testEntranceParents(self):
|
def testEntranceParents(self):
|
||||||
"""Tests that the parents of created Entrances match the exiting Region."""
|
"""Tests that the parents of created Entrances match the exiting Region."""
|
||||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
if not world_type.hidden and game_name not in {"Final Fantasy"}:
|
if not world_type.hidden:
|
||||||
with self.subTest(game_name):
|
with self.subTest(game_name):
|
||||||
multiworld = setup_default_world(world_type)
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
for region in multiworld.regions:
|
for region in multiworld.regions:
|
||||||
for exit in region.exits:
|
for exit in region.exits:
|
||||||
self.assertEqual(exit.parent_region, region)
|
self.assertEqual(exit.parent_region, region)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import unittest
|
import unittest
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
from . import setup_default_world
|
from . import setup_solo_multiworld
|
||||||
|
|
||||||
|
|
||||||
class TestBase(unittest.TestCase):
|
class TestBase(unittest.TestCase):
|
||||||
|
@ -43,14 +43,18 @@ class TestBase(unittest.TestCase):
|
||||||
|
|
||||||
def testItemCountGreaterEqualLocations(self):
|
def testItemCountGreaterEqualLocations(self):
|
||||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
|
|
||||||
if game_name in {"Final Fantasy"}:
|
|
||||||
continue
|
|
||||||
with self.subTest("Game", game=game_name):
|
with self.subTest("Game", game=game_name):
|
||||||
world = setup_default_world(world_type)
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
location_count = sum(0 if location.event or location.item else 1 for location in world.get_locations())
|
|
||||||
self.assertGreaterEqual(
|
self.assertGreaterEqual(
|
||||||
len(world.itempool),
|
len(multiworld.itempool),
|
||||||
location_count,
|
len(multiworld.get_unfilled_locations()),
|
||||||
f"{game_name} Item count MUST meet or exceede the number of locations",
|
f"{game_name} Item count MUST meet or exceed the number of locations",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def testItemsInDatapackage(self):
|
||||||
|
"""Test that any created items in the itempool are in the datapackage"""
|
||||||
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
|
with self.subTest("Game", game=game_name):
|
||||||
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
|
for item in multiworld.itempool:
|
||||||
|
self.assertIn(item.name, world_type.item_name_to_id)
|
||||||
|
|
|
@ -1,16 +1,25 @@
|
||||||
import unittest
|
import unittest
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
from . import setup_default_world
|
from . import setup_solo_multiworld
|
||||||
|
|
||||||
|
|
||||||
class TestBase(unittest.TestCase):
|
class TestBase(unittest.TestCase):
|
||||||
def testCreateDuplicateLocations(self):
|
def testCreateDuplicateLocations(self):
|
||||||
|
"""Tests that no two Locations share a name."""
|
||||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
if game_name in {"Final Fantasy"}:
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
continue
|
|
||||||
multiworld = setup_default_world(world_type)
|
|
||||||
locations = Counter(multiworld.get_locations())
|
locations = Counter(multiworld.get_locations())
|
||||||
if locations:
|
if locations:
|
||||||
self.assertLessEqual(locations.most_common(1)[0][1], 1,
|
self.assertLessEqual(locations.most_common(1)[0][1], 1,
|
||||||
f"{world_type.game} has duplicate of location {locations.most_common(1)}")
|
f"{world_type.game} has duplicate of location {locations.most_common(1)}")
|
||||||
|
|
||||||
|
def testLocationsInDatapackage(self):
|
||||||
|
"""Tests that created locations not filled before fill starts exist in the datapackage."""
|
||||||
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
|
with self.subTest("Game", game_name=game_name):
|
||||||
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
|
locations = multiworld.get_unfilled_locations() # do unfilled locations to avoid Events
|
||||||
|
for location in locations:
|
||||||
|
self.assertIn(location.name, world_type.location_name_to_id)
|
||||||
|
self.assertEqual(location.address, world_type.location_name_to_id[location.name])
|
||||||
|
|
|
@ -3,7 +3,7 @@ import unittest
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
|
|
||||||
from . import setup_default_world
|
from . import setup_solo_multiworld
|
||||||
|
|
||||||
|
|
||||||
class TestBase(unittest.TestCase):
|
class TestBase(unittest.TestCase):
|
||||||
|
@ -12,9 +12,9 @@ class TestBase(unittest.TestCase):
|
||||||
def testAllStateCanReachEverything(self):
|
def testAllStateCanReachEverything(self):
|
||||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
# Final Fantasy logic is controlled by finalfantasyrandomizer.com
|
# Final Fantasy logic is controlled by finalfantasyrandomizer.com
|
||||||
if game_name not in {"Ori and the Blind Forest", "Final Fantasy"}: # TODO: fix Ori Logic
|
if game_name not in {"Ori and the Blind Forest"}: # TODO: fix Ori Logic
|
||||||
with self.subTest("Game", game=game_name):
|
with self.subTest("Game", game=game_name):
|
||||||
world = setup_default_world(world_type)
|
world = setup_solo_multiworld(world_type)
|
||||||
excluded = world.exclude_locations[1].value
|
excluded = world.exclude_locations[1].value
|
||||||
state = world.get_all_state(False)
|
state = world.get_all_state(False)
|
||||||
for location in world.get_locations():
|
for location in world.get_locations():
|
||||||
|
@ -28,9 +28,9 @@ class TestBase(unittest.TestCase):
|
||||||
def testEmptyStateCanReachSomething(self):
|
def testEmptyStateCanReachSomething(self):
|
||||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||||
# Final Fantasy logic is controlled by finalfantasyrandomizer.com
|
# Final Fantasy logic is controlled by finalfantasyrandomizer.com
|
||||||
if game_name not in {"Archipelago", "Final Fantasy", "Sudoku"}:
|
if game_name not in {"Archipelago", "Sudoku"}:
|
||||||
with self.subTest("Game", game=game_name):
|
with self.subTest("Game", game=game_name):
|
||||||
world = setup_default_world(world_type)
|
world = setup_solo_multiworld(world_type)
|
||||||
state = CollectionState(world)
|
state = CollectionState(world)
|
||||||
locations = set()
|
locations = set()
|
||||||
for location in world.get_locations():
|
for location in world.get_locations():
|
||||||
|
|
|
@ -6,7 +6,7 @@ from worlds.AutoWorld import call_all
|
||||||
gen_steps = ["generate_early", "create_regions", "create_items", "set_rules", "generate_basic", "pre_fill"]
|
gen_steps = ["generate_early", "create_regions", "create_items", "set_rules", "generate_basic", "pre_fill"]
|
||||||
|
|
||||||
|
|
||||||
def setup_default_world(world_type) -> MultiWorld:
|
def setup_solo_multiworld(world_type) -> MultiWorld:
|
||||||
multiworld = MultiWorld(1)
|
multiworld = MultiWorld(1)
|
||||||
multiworld.game[1] = world_type.game
|
multiworld.game[1] = world_type.game
|
||||||
multiworld.player_name = {1: "Tester"}
|
multiworld.player_name = {1: "Tester"}
|
||||||
|
|
|
@ -45,8 +45,14 @@ class FF1World(World):
|
||||||
self.locked_items = []
|
self.locked_items = []
|
||||||
self.locked_locations = []
|
self.locked_locations = []
|
||||||
|
|
||||||
def generate_early(self):
|
@classmethod
|
||||||
return
|
def stage_assert_generate(cls, multiworld: MultiWorld) -> None:
|
||||||
|
# Fail generation if there are no items in the pool
|
||||||
|
for player in multiworld.get_game_players(cls.game):
|
||||||
|
options = get_options(multiworld, 'items', player)
|
||||||
|
assert options,\
|
||||||
|
f"FFR settings submitted with no key items ({multiworld.get_player_name(player)}). Please ensure you " \
|
||||||
|
f"generated the settings using finalfantasyrandomizer.com AND enabled the AP flag"
|
||||||
|
|
||||||
def create_regions(self):
|
def create_regions(self):
|
||||||
locations = get_options(self.multiworld, 'locations', self.player)
|
locations = get_options(self.multiworld, 'locations', self.player)
|
||||||
|
@ -65,8 +71,8 @@ class FF1World(World):
|
||||||
terminated_event.access_rule = goal_rule_and_shards
|
terminated_event.access_rule = goal_rule_and_shards
|
||||||
if "MARK" in items.keys():
|
if "MARK" in items.keys():
|
||||||
# Fail generation for Noverworld and provide link to old FFR website
|
# Fail generation for Noverworld and provide link to old FFR website
|
||||||
raise Exception("FFR Noverworld seeds must be generated on an older version of FFR. Please ensure you generated the settings using "
|
raise Exception("FFR Noverworld seeds must be generated on an older version of FFR. Please ensure you "
|
||||||
"4-4-0.finalfantasyrandomizer.com")
|
"generated the settings using 4-4-0.finalfantasyrandomizer.com")
|
||||||
menu_region.locations.append(terminated_event)
|
menu_region.locations.append(terminated_event)
|
||||||
self.multiworld.regions += [menu_region]
|
self.multiworld.regions += [menu_region]
|
||||||
|
|
||||||
|
@ -85,10 +91,6 @@ class FF1World(World):
|
||||||
if possible_early_items:
|
if possible_early_items:
|
||||||
progression_item = self.multiworld.random.choice(possible_early_items)
|
progression_item = self.multiworld.random.choice(possible_early_items)
|
||||||
self._place_locked_item_in_sphere0(progression_item)
|
self._place_locked_item_in_sphere0(progression_item)
|
||||||
else:
|
|
||||||
# Fail generation if there are no items in the pool
|
|
||||||
raise Exception("FFR settings submitted with no key items. Please ensure you generated the settings using "
|
|
||||||
"finalfantasyrandomizer.com AND enabled the AP flag")
|
|
||||||
|
|
||||||
items = [self.create_item(name) for name, data in items.items() for x in range(data['count']) if name not in
|
items = [self.create_item(name) for name, data in items.items() for x in range(data['count']) if name not in
|
||||||
self.locked_items]
|
self.locked_items]
|
||||||
|
|
Loading…
Reference in New Issue