| |
1 # Test Framework |
| |
2 |
| |
3 UCX brings its own testing framework, which can also be used by your applications. |
| |
4 |
| |
5 A test new suite is created by `cx_test_suite_new()`. |
| |
6 An arbitrary number of test cases can be registered with `cx_test_register()`. |
| |
7 |
| |
8 ```C |
| |
9 #include <cx/test.h> |
| |
10 |
| |
11 CxTestSuite *suite = cx_test_suite_new("My Suite"); |
| |
12 |
| |
13 cx_test_register(suite, test_foo); |
| |
14 cx_test_register(suite, test_bar); |
| |
15 cx_test_register(suite, test_baz); |
| |
16 ``` |
| |
17 |
| |
18 A test case needs to be defined with the `CX_TEST` macro. |
| |
19 The general structure of a test case is 1) setup code, 2) the actual test, 3) tear down code. |
| |
20 In UCX this is realized by the `CX_TEST_DO` macro with which you can define a scope for the actual test. |
| |
21 Whenever a test assertion fails, the scope is exited and the tear down code is executed. |
| |
22 |
| |
23 <tabs> |
| |
24 <tab title="Test"> |
| |
25 <code-block lang="C"> |
| |
26 CX_TEST(test_foo) { |
| |
27 struct mystruct *x = malloc(sizeof(*x)); |
| |
28 x->d = 42; |
| |
29 CX_TEST_DO { |
| |
30 int y = foo(x); |
| |
31 |
| |
32 // auto-generated failure message |
| |
33 CX_TEST_ASSERT(y == 42); |
| |
34 |
| |
35 // alternatively: custom failure message |
| |
36 CX_TEST_ASSERTM(y == 42, |
| |
37 "foo does not return correct value"); |
| |
38 } |
| |
39 free(x); |
| |
40 } |
| |
41 </code-block> |
| |
42 </tab> |
| |
43 <tab title="Implementation"> |
| |
44 <code-block lang="C"> |
| |
45 struct mystruct { |
| |
46 int d; |
| |
47 }; |
| |
48 |
| |
49 int foo(struct mystruct *s) { |
| |
50 return s->d; |
| |
51 } |
| |
52 </code-block> |
| |
53 </tab> |
| |
54 </tabs> |
| |
55 |
| |
56 Once you have registered all test cases, you can run the test suite with `cx_test_run()` |
| |
57 or one of the convenience macros. |
| |
58 |
| |
59 <tabs> |
| |
60 <tab title="stdout"> |
| |
61 <code-block lang="C"> |
| |
62 cx_test_run_stdout(suite); |
| |
63 </code-block> |
| |
64 </tab> |
| |
65 <tab title="FILE*"> |
| |
66 <code-block lang="C"> |
| |
67 FILE *f = fopen("test-result.txt", "w"); |
| |
68 cx_test_run_f(suite, f); |
| |
69 fclose(f); |
| |
70 </code-block> |
| |
71 </tab> |
| |
72 <tab title="Other"> |
| |
73 <code-block lang="C"> |
| |
74 // for example: UCX buffer |
| |
75 CxBuffer buf; |
| |
76 cxBufferInit(&buf, NULL, 1024, NULL, 0); |
| |
77 cx_test_run(suite, &buf, cxBufferWriteFunc); |
| |
78 // do something with the buffer |
| |
79 cxBufferDestroy(&buf); |
| |
80 </code-block> |
| |
81 </tab> |
| |
82 </tabs> |
| |
83 Finally, clean up all resources consumed by the test suite. |
| |
84 |
| |
85 ```C |
| |
86 cx_test_suite_free(suite); |
| |
87 ``` |
| |
88 |
| |
89 ## Test Subroutines |
| |
90 |
| |
91 For parameterized testing you can define and call test subroutines. |
| |
92 It is _not_ possible to call arbitrary functions and use the `CX_TEST_ASSERT` macro. |
| |
93 Instead, you define a callable test subroutine with `CX_TEST_SUBROUTINE` and call it with `CX_TEST_CALL_SUBROUTINE`. |
| |
94 The following example illustrates this with an adaption of the above test case. |
| |
95 |
| |
96 <code-block lang="C"> |
| |
97 CX_TEST_SUBROUTINE(test_foo_params, struct mystruct *x, int d) { |
| |
98 x->d = d; |
| |
99 CX_TEST_ASSERT(foo(x) == d); |
| |
100 } |
| |
101 |
| |
102 CX_TEST(test_foo) { |
| |
103 struct mystruct *x = malloc(sizeof(*x)); |
| |
104 CX_TEST_DO { |
| |
105 CX_TEST_CALL_SUBROUTINE(test_foo_params, x, 42); |
| |
106 CX_TEST_CALL_SUBROUTINE(test_foo_params, x, -42); |
| |
107 CX_TEST_CALL_SUBROUTINE(test_foo_params, x, 1337); |
| |
108 } |
| |
109 free(x); |
| |
110 } |
| |
111 </code-block> |
| |
112 |
| |
113 > Any test function, test case or test subroutine, is a normal C function. |
| |
114 > As such you can decide to make them `static` when you do not want external linkage. |
| |
115 > For example, just define the test as `static CX_TEST(test_foo)` instead of `CX_TEST(test_foo)`. |
| |
116 |
| |
117 <seealso> |
| |
118 <category ref="apidoc"> |
| |
119 <a href="https://ucx.sourceforge.io/api/test_8h.html">test.h</a> |
| |
120 </category> |
| |
121 </seealso> |