# Test Framework
UCX brings its own testing framework, which can also be used by your applications.
A test new suite is created by `cx_test_suite_new()`.
An arbitrary number of test cases can be registered with `cx_test_register()`.
```C
#include <cx/test.h>
CxTestSuite *suite = cx_test_suite_new("My Suite");
cx_test_register(suite, test_foo);
cx_test_register(suite, test_bar);
cx_test_register(suite, test_baz);
```
A test case needs to be defined with the `CX_TEST` macro.
The general structure of a test case is 1) setup code, 2) the actual test, 3) tear down code.
In UCX this is realized by the `CX_TEST_DO` macro with which you can define a scope for the actual test.
Whenever a test assertion fails, the scope is exited and the tear-down code is executed.
<tabs>
<tab title="Test">
<code-block lang="C"><![CDATA[
CX_TEST(test_foo) {
struct mystruct *x = malloc(sizeof(*x));
x->d = 42;
CX_TEST_DO {
int y = foo(x);
// auto-generated failure message
CX_TEST_ASSERT(y == 42);
// alternatively: custom failure message
CX_TEST_ASSERTM(y == 42,
"foo does not return correct value");
}
free(x);
}
]]></code-block>
</tab>
<tab title="Implementation">
<code-block lang="C"><![CDATA[
struct mystruct {
int d;
};
int foo(struct mystruct *s) {
return s->d;
}
]]></code-block>
</tab>
</tabs>
Once you have registered all test cases, you can run the test suite with `cx_test_run()`
or one of the convenience macros.
<tabs>
<tab title="stdout">
<code-block lang="C">
cx_test_run_stdout(suite);
</code-block>
</tab>
<tab title="FILE*">
<code-block lang="C">
FILE *f = fopen("test-result.txt", "w");
cx_test_run_f(suite, f);
fclose(f);
</code-block>
</tab>
<tab title="Other">
<code-block lang="C">
// for example: UCX buffer
CxBuffer buf;
cxBufferInit(&buf, NULL, 1024, NULL, 0);
cx_test_run(suite, &buf, cxBufferWriteFunc);
// do something with the buffer
cxBufferDestroy(&buf);
</code-block>
</tab>
</tabs>
Finally, clean up all resources consumed by the test suite.
```C
cx_test_suite_free(suite);
```
## Test Subroutines
For parameterized testing you can define and call test subroutines.
It is _not_ possible to call arbitrary functions and use the `CX_TEST_ASSERT` macro.
Instead, you define a callable test subroutine with `CX_TEST_SUBROUTINE` and call it with `CX_TEST_CALL_SUBROUTINE`.
The following example illustrates this with an adaption of the above test case.
```c
CX_TEST_SUBROUTINE(test_foo_params, struct mystruct *x, int d) {
x->d = d;
CX_TEST_ASSERT(foo(x) == d);
}
CX_TEST(test_foo) {
struct mystruct *x = malloc(sizeof(*x));
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_foo_params, x, 42);
CX_TEST_CALL_SUBROUTINE(test_foo_params, x, -42);
CX_TEST_CALL_SUBROUTINE(test_foo_params, x, 1337);
}
free(x);
}
```
> Any test function, test case or test subroutine is a normal C function.
> As such you can decide to make them `static` when you do not want external linkage.
> For example, you can define the test as `static CX_TEST(test_foo)` instead of `CX_TEST(test_foo)`.
<seealso>
<category ref="apidoc">
<a href="https://ucx.sourceforge.io/api/test_8h.html">test.h</a>
</category>
</seealso>