mirror of
https://github.com/tbamud/tbamud.git
synced 2026-04-30 04:41:51 +02:00
docs: add unit test documentation to README.md and doc/testing.md
Agent-Logs-Url: https://github.com/tbamud/tbamud/sessions/dd8af74a-9ecb-485b-851a-96b38b3cfc79 Co-authored-by: welcor <357770+welcor@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
13c6f6291c
commit
2e0668d4f8
31
README.md
31
README.md
@@ -1,3 +1,34 @@
|
|||||||
Files for tbaMUD.
|
Files for tbaMUD.
|
||||||
|
|
||||||
|
## Unit Tests
|
||||||
|
|
||||||
|
tbaMUD ships with a C unit-test suite located in the `tests/` directory.
|
||||||
|
The suite uses the [Unity](https://github.com/ThrowTheSwitch/Unity) test
|
||||||
|
framework (vendored under `tests/vendor/unity/`).
|
||||||
|
|
||||||
|
### Quick start
|
||||||
|
|
||||||
|
```
|
||||||
|
./configure
|
||||||
|
cd tests && make test
|
||||||
|
```
|
||||||
|
|
||||||
|
`make test` builds each test binary, runs it, and writes JUnit XML results to
|
||||||
|
`tests/test-results/`. A summary is printed to the terminal:
|
||||||
|
|
||||||
|
```
|
||||||
|
[PASS] test_utils
|
||||||
|
[PASS] test_random
|
||||||
|
[PASS] test_interpreter
|
||||||
|
[PASS] test_class
|
||||||
|
```
|
||||||
|
|
||||||
|
### CI
|
||||||
|
|
||||||
|
The GitHub Actions workflow (`.github/workflows/build.yml`) runs `make test`
|
||||||
|
on every push and pull request against `master` and publishes a formatted
|
||||||
|
report via the `dorny/test-reporter` action.
|
||||||
|
|
||||||
|
See [doc/testing.md](doc/testing.md) for full details on adding new tests and
|
||||||
|
understanding the test infrastructure.
|
||||||
|
|
||||||
|
|||||||
150
doc/testing.md
Normal file
150
doc/testing.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# tbaMUD Unit Testing
|
||||||
|
|
||||||
|
_Updated 2026-04_
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
tbaMUD has a C unit-test suite built on the
|
||||||
|
[Unity](https://github.com/ThrowTheSwitch/Unity) framework. Tests live in the
|
||||||
|
`tests/` directory alongside the vendored Unity source.
|
||||||
|
|
||||||
|
```
|
||||||
|
tests/
|
||||||
|
Makefile.in – Autoconf template; processed by configure
|
||||||
|
test_stubs.c – Weak-symbol stubs that satisfy mud headers
|
||||||
|
unity_to_junit.py – Converts Unity output to JUnit XML
|
||||||
|
test_class.c – Tests for src/class.c
|
||||||
|
test_interpreter.c – Tests for src/interpreter.c
|
||||||
|
test_random.c – Tests for src/random.c
|
||||||
|
test_utils.c – Tests for src/utils.c
|
||||||
|
vendor/unity/ – Vendored Unity test framework
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
| Requirement | Notes |
|
||||||
|
|---|---|
|
||||||
|
| C compiler (gcc or clang) | Same compiler used to build the mud |
|
||||||
|
| GNU make | Any POSIX-compatible make works |
|
||||||
|
| Python 3 | Required only for JUnit XML conversion (`unity_to_junit.py`) |
|
||||||
|
| autoconf / configure | Already needed to build the mud |
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Run `./configure` from the repository root first (only needed once):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./configure
|
||||||
|
```
|
||||||
|
|
||||||
|
Then build and run all tests from the `tests/` directory:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd tests
|
||||||
|
make test
|
||||||
|
```
|
||||||
|
|
||||||
|
`make test` performs the following steps for each test binary:
|
||||||
|
|
||||||
|
1. Compiles the test binary (if not already up to date).
|
||||||
|
2. Runs the binary and captures stdout/stderr to `test-results/<name>.out`.
|
||||||
|
3. Measures wall-clock elapsed time.
|
||||||
|
4. Converts the Unity output to JUnit XML via `unity_to_junit.py`, writing
|
||||||
|
`test-results/<name>.xml`.
|
||||||
|
5. Prints `[PASS] <name>` or `[FAIL] <name>` and exits non-zero if any
|
||||||
|
binary failed.
|
||||||
|
|
||||||
|
To build the test binaries without running them:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd tests
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
To remove all test binaries and result files:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd tests
|
||||||
|
make clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test suites
|
||||||
|
|
||||||
|
| Binary | Source under test | Test file |
|
||||||
|
|---|---|---|
|
||||||
|
| `test_utils` | `src/utils.c`, `src/random.c` | `test_utils.c` |
|
||||||
|
| `test_random` | `src/random.c`, `rand_number`/`dice` in `src/utils.c` | `test_random.c` |
|
||||||
|
| `test_interpreter` | `src/interpreter.c` | `test_interpreter.c` |
|
||||||
|
| `test_class` | `src/class.c` | `test_class.c` |
|
||||||
|
|
||||||
|
## Writing a new test
|
||||||
|
|
||||||
|
### Adding a test case to an existing suite
|
||||||
|
|
||||||
|
1. Open the relevant `test_<name>.c` file.
|
||||||
|
2. Write a function with the signature `void test_my_feature(void)`.
|
||||||
|
3. Use Unity assertion macros such as `TEST_ASSERT_EQUAL_INT`,
|
||||||
|
`TEST_ASSERT_NULL`, `TEST_ASSERT_TRUE`, etc.
|
||||||
|
4. Register the function in the `main()` block:
|
||||||
|
```c
|
||||||
|
RUN_TEST(test_my_feature);
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```c
|
||||||
|
void test_str_cmp_equal_strings(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, str_cmp("hello", "hello"));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating a new test suite
|
||||||
|
|
||||||
|
1. Create `tests/test_<module>.c`. Copy the boilerplate from an existing
|
||||||
|
suite: include `unity.h`, define `setUp`/`tearDown` (may be empty), write
|
||||||
|
test functions, and provide a `main()` that calls `UNITY_BEGIN()`,
|
||||||
|
`RUN_TEST(...)` for each function, and `return UNITY_END();`.
|
||||||
|
|
||||||
|
2. Add the binary to `tests/Makefile.in`:
|
||||||
|
- Add the name to the `TESTS` variable.
|
||||||
|
- Add a build rule:
|
||||||
|
```make
|
||||||
|
test_<module>: $(UNITY_SRC) $(STUBS_SRC) $(UTILS_SRC) \
|
||||||
|
$(SRCDIR)/<module>.c test_<module>.c
|
||||||
|
$(COMPILE) -o $@ $^ $(LIBS)
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Re-run `./configure` from the repository root to regenerate
|
||||||
|
`tests/Makefile` from the updated `tests/Makefile.in`.
|
||||||
|
|
||||||
|
### Stubs
|
||||||
|
|
||||||
|
Many mud source files reference global variables and functions that are only
|
||||||
|
meaningful at runtime (e.g. `descriptor_list`, `log()`). `test_stubs.c`
|
||||||
|
provides zero-initialised definitions and `__attribute__((weak))` stub
|
||||||
|
implementations for these symbols so that test binaries link without pulling
|
||||||
|
in the full mud.
|
||||||
|
|
||||||
|
If a new test requires a function not yet stubbed, add a weak stub to
|
||||||
|
`test_stubs.c`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
__attribute__((weak)) void my_function(void) { /* no-op */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
## JUnit XML output and CI
|
||||||
|
|
||||||
|
`unity_to_junit.py` reads Unity's line-oriented output on stdin and writes a
|
||||||
|
JUnit-compatible XML file. It accepts an optional third argument with the
|
||||||
|
elapsed wall-clock time in seconds (provided by the `make test` target):
|
||||||
|
|
||||||
|
```
|
||||||
|
usage: unity_to_junit.py <suite_name> <output.xml> [elapsed_seconds]
|
||||||
|
```
|
||||||
|
|
||||||
|
The GitHub Actions workflow (`.github/workflows/build.yml`) runs `make test`
|
||||||
|
on every push and pull request against `master`. After the tests finish the
|
||||||
|
`dorny/test-reporter` action reads `tests/test-results/*.xml` and publishes a
|
||||||
|
formatted report as a GitHub Check with pass/fail counts and per-suite
|
||||||
|
execution times.
|
||||||
Reference in New Issue
Block a user