|
| 1 | +# Archipelago Unit Testing API |
| 2 | + |
| 3 | +This document covers some of the generic tests available using Archipelago's unit testing system, as well as some basic |
| 4 | +steps on how to write your own. |
| 5 | + |
| 6 | +## Generic Tests |
| 7 | + |
| 8 | +Some generic tests are run on every World to ensure basic functionality with default options. These basic tests can be |
| 9 | +found in the [general test directory](/test/general). |
| 10 | + |
| 11 | +## Defining World Tests |
| 12 | + |
| 13 | +In order to run tests from your world, you will need to create a `test` package within your world package. This can be |
| 14 | +done by creating a `test` directory with a file named `__init__.py` inside it inside your world. By convention, a base |
| 15 | +for your world tests can be created in this file that you can then import into other modules. |
| 16 | + |
| 17 | +### WorldTestBase |
| 18 | + |
| 19 | +In order to test basic functionality of varying options, as well as to test specific edge cases or that certain |
| 20 | +interactions in the world interact as expected, you will want to use the [WorldTestBase](/test/bases.py). This class |
| 21 | +comes with the basics for test setup as well as a few preloaded tests that most worlds might want to check on varying |
| 22 | +options combinations. |
| 23 | + |
| 24 | +Example `/worlds/<my_game>/test/__init__.py`: |
| 25 | + |
| 26 | +```python |
| 27 | +from test.bases import WorldTestBase |
| 28 | + |
| 29 | + |
| 30 | +class MyGameTestBase(WorldTestBase): |
| 31 | + game = "My Game" |
| 32 | +``` |
| 33 | + |
| 34 | +The basic tests that WorldTestBase comes with include `test_all_state_can_reach_everything`, |
| 35 | +`test_empty_state_can_reach_something`, and `test_fill`. These test that with all collected items everything is |
| 36 | +reachable, with no collected items at least something is reachable, and that a valid multiworld can be completed with |
| 37 | +all steps being called, respectively. |
| 38 | + |
| 39 | +### Writing Tests |
| 40 | + |
| 41 | +#### Using WorldTestBase |
| 42 | + |
| 43 | +Adding runs for the basic tests for a different option combination is as easy as making a new module in the test |
| 44 | +package, creating a class that inherits from your game's TestBase, and defining the options in a dict as a field on the |
| 45 | +class. The new module should be named `test_<something>.py` and have at least one class inheriting from the base, or |
| 46 | +define its own testing methods. Newly defined test methods should follow standard PEP8 snake_case format and also start |
| 47 | +with `test_`. |
| 48 | + |
| 49 | +Example `/worlds/<my_game>/test/test_chest_access.py`: |
| 50 | + |
| 51 | +```python |
| 52 | +from . import MyGameTestBase |
| 53 | + |
| 54 | + |
| 55 | +class TestChestAccess(MyGameTestBase): |
| 56 | + options = { |
| 57 | + "difficulty": "easy", |
| 58 | + "final_boss_hp": 4000, |
| 59 | + } |
| 60 | + |
| 61 | + def test_sword_chests(self) -> None: |
| 62 | + """Test locations that require a sword""" |
| 63 | + locations = ["Chest1", "Chest2"] |
| 64 | + items = [["Sword"]] |
| 65 | + # This tests that the provided locations aren't accessible without the provided items, but can be accessed once |
| 66 | + # the items are obtained. |
| 67 | + # This will also check that any locations not provided don't have the same dependency requirement. |
| 68 | + # Optionally, passing only_check_listed=True to the method will only check the locations provided. |
| 69 | + self.assertAccessDependency(locations, items) |
| 70 | +``` |
| 71 | + |
| 72 | +When tests are run, this class will create a multiworld with a single player having the provided options, and run the |
| 73 | +generic tests, as well as the new custom test. Each test method definition will create its own separate solo multiworld |
| 74 | +that will be cleaned up after. If you don't want to run the generic tests on a base, `run_default_tests` can be |
| 75 | +overridden. For more information on what methods are available to your class, check the |
| 76 | +[WorldTestBase definition](/test/bases.py#L104). |
| 77 | + |
| 78 | +#### Alternatives to WorldTestBase |
| 79 | + |
| 80 | +Unit tests can also be created using [TestBase](/test/bases.py#L14) or |
| 81 | +[unittest.TestCase](https://docs.python.org/3/library/unittest.html#unittest.TestCase) depending on your use case. These |
| 82 | +may be useful for generating a multiworld under very specific constraints without using the generic world setup, or for |
| 83 | +testing portions of your code that can be tested without relying on a multiworld to be created first. |
| 84 | + |
| 85 | +## Running Tests |
| 86 | + |
| 87 | +In PyCharm, running all tests can be done by right-clicking the root `test` directory and selecting `run Python tests`. |
| 88 | +If you do not have pytest installed, you may get import failures. To solve this, edit the run configuration, and set the |
| 89 | +working directory of the run to the Archipelago directory. If you only want to run your world's defined tests, repeat |
| 90 | +the steps for the test directory within your world. |
0 commit comments