From dab0ec7b588e8a92f75859d9232d0372a9e369b6 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 15 Feb 2025 18:10:00 +0100 Subject: [PATCH] Clean up the Unit testing doc --- docs/source/Coding/Unit-Testing.md | 76 +++++++++--------------------- 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/docs/source/Coding/Unit-Testing.md b/docs/source/Coding/Unit-Testing.md index 1ff629ffbb..7213d5934b 100644 --- a/docs/source/Coding/Unit-Testing.md +++ b/docs/source/Coding/Unit-Testing.md @@ -5,63 +5,45 @@ A typical unit test set calls some function or method with a given input, looks at the result and makes sure that this result looks as expected. Rather than having lots of stand-alone test programs, Evennia makes use of a central *test runner*. This is a program that gathers all available tests all over the Evennia source code (called *test suites*) and runs them all in one go. Errors and tracebacks are reported. By default Evennia only tests itself. But you can also add your own tests to your game code and have Evennia run those for you. - ## Running the Evennia test suite To run the full Evennia test suite, go to your game folder and issue the command evennia test evennia -This will run all the evennia tests using the default settings. You could also run only a subset of -all tests by specifying a subpackage of the library: +This will run all the evennia tests using the default settings. You could also run only a subset of all tests by specifying a subpackage of the library: evennia test evennia.commands.default -A temporary database will be instantiated to manage the tests. If everything works out you will see -how many tests were run and how long it took. If something went wrong you will get error messages. -If you contribute to Evennia, this is a useful sanity check to see you haven't introduced an -unexpected bug. +A temporary database will be instantiated to manage the tests. If everything works out you will see how many tests were run and how long it took. If something went wrong you will get error messages. If you contribute to Evennia, this is a useful sanity check to see you haven't introduced an unexpected bug. ## Running custom game-dir unit tests -If you have implemented your own tests for your game you can run them from your game dir -with +If you have implemented your own tests for your game you can run them from your game dir with evennia test --settings settings.py . -The period (`.`) means to run all tests found in the current directory and all subdirectories. You -could also specify, say, `typeclasses` or `world` if you wanted to just run tests in those subdirs. +The period (`.`) means to run all tests found in the current directory and all subdirectories. You could also specify, say, `typeclasses` or `world` if you wanted to just run tests in those subdirs. -An important thing to note is that those tests will all be run using the _default Evennia settings_. -To run the tests with your own settings file you must use the `--settings` option: +An important thing to note is that those tests will all be run using the _default Evennia settings_. To run the tests with your own settings file you must use the `--settings` option: evennia test --settings settings.py . -The `--settings` option of Evennia takes a file name in the `mygame/server/conf` folder. It is -normally used to swap settings files for testing and development. In combination with `test`, it -forces Evennia to use this settings file over the default one. +The `--settings` option of Evennia takes a file name in the `mygame/server/conf` folder. It is normally used to swap settings files for testing and development. In combination with `test`, it forces Evennia to use this settings file over the default one. You can also test specific things by giving their path evennia test --settings settings.py world.tests.YourTest - ## Writing new unit tests -Evennia's test suite makes use of Django unit test system, which in turn relies on Python's -*unittest* module. +Evennia's test suite makes use of Django unit test system, which in turn relies on Python's *unittest* module. -To make the test runner find the tests, they must be put in a module named `test*.py` (so `test.py`, -`tests.py` etc). Such a test module will be found wherever it is in the package. It can be a good -idea to look at some of Evennia's `tests.py` modules to see how they look. +To make the test runner find the tests, they must be put in a module named `test*.py` (so `test.py`, `tests.py` etc). Such a test module will be found wherever it is in the package. It can be a good idea to look at some of Evennia's `tests.py` modules to see how they look. -Inside the module you need to put a class inheriting (at any distance) from `unittest.TestCase`. Each -method on that class that starts with `test_` will be run separately as a unit test. There -are two special, optional methods `setUp` and `tearDown` that will (if you define them) run before -_every_ test. This can be useful for setting up and deleting things. +Inside the module you need to put a class inheriting (at any distance) from `unittest.TestCase`. Each method on that class that starts with `test_` will be run separately as a unit test. There are two special, optional methods `setUp` and `tearDown` that will (if you define them) run before and after _every_ test. This can be useful for creating, configuring and cleaning up things that every test in the class needs. -To actually test things, you use special `assert...` methods on the class. Most common on is -`assertEqual`, which makes sure a result is what you expect it to be. +To actually test things, you use special `assert...` methods on the class. Most common on is `assertEqual`, which makes sure a result is what you expect it to be. Here's an example of the principle. Let's assume you put this in `mygame/world/tests.py` and want to test a function in `mygame/world/myfunctions.py` @@ -120,11 +102,11 @@ You might also want to read the [Python documentation for the unittest module](h ### Using the Evennia testing classes -Evennia offers many custom testing classes that helps with testing Evennia features. -They are all found in [evennia.utils.test_resources](evennia.utils.test_resources). Note that -these classes implement the `setUp` and `tearDown` already, so if you want to add stuff in them -yourself you should remember to use e.g. `super().setUp()` in your code. +Evennia offers many custom testing classes that helps with testing Evennia features. They are all found in [evennia.utils.test_resources](evennia.utils.test_resources). +```{important} +Note that these base classes implement the `setUp` and `tearDown` already, so if you want to add stuff in them yourself you should remember to use e.g. `super().setUp()` in your code. +``` #### Classes for testing your game dir These all use whatever setting you pass to them and works well for testing code in your game dir. @@ -147,10 +129,7 @@ These all use whatever setting you pass to them and works well for testing code without a timing component. - `.session` - A fake [Session](evennia.server.serversession.ServerSession) that mimics a player connecting to the game. It is used by `.account1` and has a sessid of 1. -- `EvenniaCommandTest` - has the same environment like `EvenniaTest` but also adds a special - [.call()](evennia.utils.test_resources.EvenniaCommandTestMixin.call) method specifically for - testing Evennia [Commands](../Components/Commands.md). It allows you to compare what the command _actually_ - returns to the player with what you expect. Read the `call` api doc for more info. +- `EvenniaCommandTest` - has the same environment like `EvenniaTest` but also adds a special [.call()](evennia.utils.test_resources.EvenniaCommandTestMixin.call) method specifically for testing Evennia [Commands](../Components/Commands.md). It allows you to compare what the command _actually_ returns to the player with what you expect. Read the `call` api doc for more info. - `EvenniaTestCase` - This is identical to the regular Python `TestCase` class, it's just there for naming symmetry with `BaseEvenniaTestCase` below. @@ -193,17 +172,12 @@ class TestSet(EvenniaCommandTest): "You see: Obj(#4), Obj2(#5), Char2(#7)") ``` -When using `.call`, you don't need to specify the entire string; you can just give the beginning -of it and if it matches, that's enough. Use `\n` to denote line breaks and (this is a special for -the `.call` helper), `||` to indicate multiple uses of `.msg()` in the Command. The `.call` helper -has a lot of arguments for mimicing different ways of calling a Command, so make sure to -[read the API docs for .call()](evennia.utils.test_resources.EvenniaCommandTestMixin.call). +When using `.call`, you don't need to specify the entire string; you can just give the beginning of it and if it matches, that's enough. Use `\n` to denote line breaks and (this is a special for the `.call` helper), `||` to indicate multiple uses of `.msg()` in the Command. The `.call` helper has a lot of arguments for mimicing different ways of calling a Command, so make sure to [read the API docs for .call()](evennia.utils.test_resources.EvenniaCommandTestMixin.call). #### Classes for testing Evennia core These are used for testing Evennia itself. They provide the same resources as the classes -above but enforce Evennias default settings found in `evennia/settings_default.py`, ignoring -any settings changes in your game dir. +above but enforce Evennias default settings found in `evennia/settings_default.py`, ignoring any settings changes in your game dir. - `BaseEvenniaTest` - all the default objects above but with enforced default settings - `BaseEvenniaCommandTest` - for testing Commands, but with enforced default settings @@ -216,19 +190,12 @@ be useful if you want to mix your own testing classes: - `EvenniaCommandMixin` - A class mixin that adds the `.call()` Command-tester helper. If you want to help out writing unittests for Evennia, take a look at Evennia's [coveralls.io -page](https://coveralls.io/github/evennia/evennia). There you see which modules have any form of -test coverage and which does not. All help is appreciated! +page](https://coveralls.io/github/evennia/evennia). There you see which modules have any form of test coverage and which does not. All help is appreciated! ### Unit testing contribs with custom models -A special case is if you were to create a contribution to go to the `evennia/contrib` folder that -uses its [own database models](../Concepts/Models.md). The problem with this is that Evennia (and Django) will -only recognize models in `settings.INSTALLED_APPS`. If a user wants to use your contrib, they will -be required to add your models to their settings file. But since contribs are optional you cannot -add the model to Evennia's central `settings_default.py` file - this would always create your -optional models regardless of if the user wants them. But at the same time a contribution is a part -of the Evennia distribution and its unit tests should be run with all other Evennia tests using -`evennia test evennia`. +A special case is if you were to create a contribution to go to the `evennia/contrib` folder that uses its [own database models](../Concepts/Models.md). The problem with this is that Evennia (and Django) will +only recognize models in `settings.INSTALLED_APPS`. If a user wants to use your contrib, they will be required to add your models to their settings file. But since contribs are optional you cannot add the model to Evennia's central `settings_default.py` file - this would always create your optional models regardless of if the user wants them. But at the same time a contribution is a part of the Evennia distribution and its unit tests should be run with all other Evennia tests using `evennia test evennia`. The way to do this is to only temporarily add your models to the `INSTALLED_APPS` directory when the test runs. here is an example of how to do it. @@ -284,8 +251,7 @@ class TestMyModel(BaseEvenniaTest): ### A note on making the test runner faster -If you have custom models with a large number of migrations, creating the test database can take a very long time. If you don't require migrations to run for your tests, you can disable them with the -django-test-without-migrations package. To install it, simply: +If you have custom models with a large number of migrations, creating the test database can take a very long time. If you don't require migrations to run for your tests, you can disable them with the django-test-without-migrations package. To install it, simply: ``` $ pip install django-test-without-migrations