docs/Writerside/topics/test.h.md

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

mercurial