Skip to content

Docs: Add documentation on writing and running tests #2348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Archipelago Unit Testing API

This document covers some of the generic tests available using Archipelago's unit testing system, as well as some basic
steps on how to write your own.

## Generic Tests

Some generic tests are run on every World to ensure basic functionality with default options. The basic tests that are
run on every world are found in the [general test directory.](/test/general)

## Defining World Tests

In order to run tests from your World, you will need to create a `test` package within your World package. This can be
done by creating a `test` directory with a file named `__init__.py` inside it inside your world. By convention, a base
for your World tests can be created in this file that you can then import into other modules.

### WorldTestBase

In order to test basic functionality of varying options, as well as to test specific edge cases or that certain
interactions in the World interact as expected, you will want to use the [WorldTestBase.](/test/bases.py) This class
comes with the basics for test setup as well as a few preloaded tests that most worlds might want to check on varying
options combinations.

Example `/test/__init__.py`:

```python
from test.bases import WorldTestBase


class MyGameTestBase(WorldTestBase):
game = "My Game"
```

The basic tests that WorldTestBase comes with, currently, are `test_all_state_can_reach_everything`,
`test_empty_state_can_reach_something`, and `test_fill`. These test that with all collected items everything is
reachable, with no collected items at least something is reachable, and that a valid MultiWorld can be completed with
all steps being called, respectively.

### Writing Tests

Adding runs for the basic tests for a different option combination is as easy as making a new module in the test
package, creating a class that inherits from your game's TestBase, and defining the options in a dict as a field on the
class. The new module should be named `test_<something>.py` and have at least one class inheriting from the base, or
define its own testing methods. Newly defined test methods should follow standard PEP8 snake_case format and also start
with `test_`

Example `/test/test_chest_access.py`:

```python
from . import MyGameTestBase


class TestChestAccess(MyGameTestBase):
options = {
"difficulty": "easy",
"final_boss_hp": 4000,
}

def test_sword_chests(self) -> None:
"""Test locations that require a sword"""
locations = ["Chest1", "Chest2"]
items = [["Sword"]]
# This tests that the provided locations aren't accessible without the provided locations, but can be once
# obtained. This will also check that any locations not provided don't have the same dependency requirement.
# Optionally, passing True to the method will only check the locations provided.
self.assertAccessDependency(locations, items)
```

When tests are run, this class will create a World with the provided options, and run the basic tests, as well as the
new custom test. If you don't want to run tests on a base, `run_default_tests` can be overridden. For more information
on what methods are available to your class, check the [WorldTestBase definition](/test/bases.py).

## Running Tests

In PyCharm, running all tests can be done by right-clicking the root `test` directory and selecting `run tests`. If you
do not have pytest installed, you may get import failures. To solve this, edit the run configuration, and set the
working directory of the run to the Archipelago directory. If you only want to run your World's defined tests, repeat
the steps for the test directory within your World.
6 changes: 4 additions & 2 deletions docs/world api.md
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ TestBase, and can then define options to test in the class body, and run tests i
Example `__init__.py`

```python
from test.test_base import WorldTestBase
from test.bases import WorldTestBase


class MyGameTestBase(WorldTestBase):
Expand All @@ -770,7 +770,7 @@ class MyGameTestBase(WorldTestBase):

Next using the rules defined in the above `set_rules` we can test that the chests have the correct access rules.

Example `testChestAccess.py`
Example `test_chest_access.py`
```python
from . import MyGameTestBase

Expand All @@ -790,3 +790,5 @@ class TestChestAccess(MyGameTestBase):
# this will test that chests 3-5 can't be accessed without any weapon, but can be with just one of them.
self.assertAccessDependency(locations, items)
```

For more information on tests check the [tests doc](tests.md)