Tests: test that the game is beatable for WorldTestBases (#1495)
* Tests: test that the game is beatable for WorldTestBases * update docstring * don't test the bases with default options for real this time * invert the property so worlds can use it easier * setup check should be or * test class needs to always be constructed * skip default tests before multiworld setup * check if the calling method is in the base's __dict__ * shorter property and functional setup skipping * shorter property and functional setup skipping
This commit is contained in:
		
							parent
							
								
									805f33c39e
								
							
						
					
					
						commit
						21fb16291d
					
				|  | @ -112,7 +112,11 @@ class WorldTestBase(unittest.TestCase): | ||||||
|             self.world_setup() |             self.world_setup() | ||||||
| 
 | 
 | ||||||
|     def world_setup(self, seed: typing.Optional[int] = None) -> None: |     def world_setup(self, seed: typing.Optional[int] = None) -> None: | ||||||
|         if type(self) is WorldTestBase: |         if type(self) is WorldTestBase or \ | ||||||
|  |                 (hasattr(WorldTestBase, self._testMethodName) | ||||||
|  |                  and not self.run_default_tests and | ||||||
|  |                  getattr(self, self._testMethodName).__code__ is | ||||||
|  |                  getattr(WorldTestBase, self._testMethodName, None).__code__): | ||||||
|             return  # setUp gets called for tests defined in the base class. We skip world_setup here. |             return  # setUp gets called for tests defined in the base class. We skip world_setup here. | ||||||
|         if not hasattr(self, "game"): |         if not hasattr(self, "game"): | ||||||
|             raise NotImplementedError("didn't define game name") |             raise NotImplementedError("didn't define game name") | ||||||
|  | @ -208,16 +212,20 @@ class WorldTestBase(unittest.TestCase): | ||||||
| 
 | 
 | ||||||
|     # following tests are automatically run |     # following tests are automatically run | ||||||
|     @property |     @property | ||||||
|     def skip_default_tests(self) -> bool: |     def run_default_tests(self) -> bool: | ||||||
|         """Not possible or identical to the base test that's always being run already""" |         """Not possible or identical to the base test that's always being run already""" | ||||||
|         constructed = hasattr(self, "game") and hasattr(self, "multiworld") |         return (self.options | ||||||
|         return not constructed or (not self.options |                 or self.setUp.__code__ is not WorldTestBase.setUp.__code__ | ||||||
|                                    and self.setUp is WorldTestBase.setUp |                 or self.world_setup.__code__ is not WorldTestBase.world_setup.__code__) | ||||||
|                                    and self.world_setup is WorldTestBase.world_setup) | 
 | ||||||
|  |     @property | ||||||
|  |     def constructed(self) -> bool: | ||||||
|  |         """A multiworld has been constructed by this point""" | ||||||
|  |         return hasattr(self, "game") and hasattr(self, "multiworld") | ||||||
| 
 | 
 | ||||||
|     def testAllStateCanReachEverything(self): |     def testAllStateCanReachEverything(self): | ||||||
|         """Ensure all state can reach everything with the defined options""" |         """Ensure all state can reach everything and complete the game with the defined options""" | ||||||
|         if self.skip_default_tests: |         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.exclude_locations[1].value |             excluded = self.multiworld.exclude_locations[1].value | ||||||
|  | @ -226,10 +234,13 @@ class WorldTestBase(unittest.TestCase): | ||||||
|                 if location.name not in excluded: |                 if location.name not in excluded: | ||||||
|                     with self.subTest("Location should be reached", location=location): |                     with self.subTest("Location should be reached", location=location): | ||||||
|                         self.assertTrue(location.can_reach(state), f"{location.name} unreachable") |                         self.assertTrue(location.can_reach(state), f"{location.name} unreachable") | ||||||
|  |             with self.subTest("Beatable"): | ||||||
|  |                 self.multiworld.state = state | ||||||
|  |                 self.assertBeatable(True) | ||||||
| 
 | 
 | ||||||
|     def testEmptyStateCanReachSomething(self): |     def testEmptyStateCanReachSomething(self): | ||||||
|         """Ensure empty state can reach at least one location with the defined options""" |         """Ensure empty state can reach at least one location with the defined options""" | ||||||
|         if self.skip_default_tests: |         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): | ||||||
|             state = CollectionState(self.multiworld) |             state = CollectionState(self.multiworld) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue