Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / testing / README.md
1 # Test unit generation and execution for Nit.
2
3 In Nit, unit testing can be achieved in two ways:
4
5 * using `DocUnits` in code comments
6 * using `TestSuites` with test unit files
7
8 DocUnits are executable pieces of code found in the documentation of modules,
9 classes and properties.
10 They are used for documentation purpose, they should be kept simple and illustrative.
11 More advanced unit testing can be done using TestSuites.
12
13 TestSuites are test files coupled to a tested module.
14 They contain a list of test methods called TestCase.
15
16 ## Working with `DocUnits`
17
18 With DocUnits, executable code can be placed in comments of modules, classes and properties.
19 The execution can be verified using `assert`
20
21 Example with a class:
22
23         module foo
24
25         #    var foo = new Foo
26         #    assert foo.bar == 10
27         class Foo
28                 var bar = 10
29         end
30
31 Everything used in the test must be declared.
32 To test a method you have to instanciate its class:
33
34         module foo
35
36         #    var foo = new Foo
37         #    assert foo.bar == 10
38         class Foo
39                 #    var foo = new Foo
40                 #    assert foo.baz(1, 2) == 3
41                 fun baz(a, b: Int): Int do return a + b
42         end
43
44 `nitunit` is used to test Nit files:
45
46 ~~~sh
47         $ nitunit foo.nit
48 ~~~
49
50 ## Working with `TestSuites`
51
52 TestSuites are Nit files that define a set of TestCase for a particular module.
53
54 The test suite module must be declared using the `test` annotation.
55 The structure of a test suite is the following:
56
57 ~~~nitish
58 # test suite for module `foo`
59 module test_foo is test
60
61 import foo # can be intrude to test private things
62
63 class TestFoo
64         test
65
66         # test case for `foo::Foo::baz`
67         fun baz is test do
68                 var subject = new Foo
69                 assert subject.baz(1, 2) == 3
70         end
71 end
72 ~~~
73
74 Test suite can be executed using the same `nitunit` command:
75
76 ~~~sh
77         $ nitunit foo.nit
78 ~~~
79
80 To be started automatically with nitunit, the module must be called `test_`
81 followed by the name of the module to test.
82 So for the module `foo.nit` the test suite will be called `test_foo.nit`.
83 Otherwise, you can use the `-t` option to specify the test suite module name:
84
85 ~~~sh
86         $ nitunit foo.nit -t my_test_suite.nit
87 ~~~
88
89 `nitunit` will execute a test for each method annotated with `test` in a class also annotated with `test`
90 so multiple tests can be executed for a single method:
91
92 ~~~nitish
93 class TestFoo
94         test
95
96         fun baz_1 is test do
97                 var subject = new Foo
98                 assert subject.baz(1, 2) == 3
99         end
100
101         fun baz_2 is test do
102                 var subject = new Foo
103                 assert subject.baz(1, -2) == -1
104         end
105 end
106 ~~~
107
108 `TestSuites` also provide methods to configure the test run:
109
110 `before` and `after` annotations can be added to methods that must be called before/after each test case.
111 They can be used to factorize repetitive tasks:
112
113 ~~~nitish
114 class TestFoo
115         test
116
117         var subject: Foo is noinit
118
119         # Method executed before each test
120         fun set_up is before do
121                 subject = new Foo
122         end
123
124         fun baz_1 is test do
125                 assert subject.baz(1, 2) == 3
126         end
127
128         fun baz_2 is test do
129                 assert subject.baz(1, -2) == -1
130         end
131 end
132 ~~~
133
134 When using custom test attributes, a empty init must be declared to allow automatic test running.
135
136 At class level, `before_all` and `after_all` annotations can be set on methods that must be called before/after all the test cases in the class:
137
138 ~~~nitish
139 class TestFoo
140         test
141
142         var subject: Foo is noinit
143
144         # Method executed before all tests in the class
145         fun set_up is before_all do
146                 subject = new Foo
147         end
148
149         fun baz_1 is test do
150                 assert subject.baz(1, 2) == 3
151         end
152
153         fun baz_2 is test do
154                 assert subject.baz(1, -2) == -1
155         end
156 end
157 ~~~
158
159 `before_all` and `after_all` annotations can also be set on methods that must be called before/after each test suite when declared at top level:
160
161 ~~~nitish
162 module test_bdd_connector
163
164 import bdd_connector
165
166 # Testing the bdd_connector
167 class TestConnector
168         test
169         # test cases using a server
170 end
171
172 # Method executed before testing the module
173 fun setup_db is before_all do
174         # start server before all test cases
175 end
176
177 # Method executed after testing the module
178 fun teardown_db is after_all do
179         # stop server after all test cases
180 end
181 ~~~
182
183 When dealing with multiple test suites, niunit allows you to import other test suites to factorize your tests:
184
185 ~~~nitish
186 module test_bdd_users
187
188 import test_bdd_connector
189
190 # Testing the user table
191 class TestUsersTable
192         test
193         # test cases using the db server from `test_bdd_connector`
194 end
195
196 fun setup_table is before_all do
197         # create user table
198 end
199
200 fun teardown_table is after_all do
201         # drop user table
202 end
203 ~~~
204
205 Methods with `before*` and `after*` annotations are linearized and called in different ways.
206
207 * `before*` methods are called from the least specific to the most specific
208 * `after*` methods are called from the most specific to the least specific
209
210 In the previous example, the execution order would be:
211
212 1. `test_bdd_connector::setup_db`
213 2. `test_bdd_users::setup_table`
214 3. `all test cases from test_bdd_users`
215 4. `test_bdd_users::teardown_table`
216 5. `test_bdd_connector::teardown_db`
217
218 ## Generating test suites
219
220 Write test suites for big modules can be a pepetitive and boring task...
221 To make it easier, `nitunit` can generate test skeletons for Nit modules:
222
223 ~~~sh
224         $ nitunit --gen-suite foo.nit
225 ~~~
226
227 This will generate the test suite `test_foo` containing test case stubs for all public
228 methods found in `foo.nit`.
229
230 Useful options with `--gen-suite`:
231
232 * `--private`: also generate tests for protected and private methods
233 * `--force`: force generation of the skeleton (existing test suite will be overwritten)