1 #!/usr/bin/env dub
2 /+ dub.sdl:
3 name "example"
4 dependency "d-unit" version=">=0.8.0"
5 +/
6 
7 //          Copyright Juan Manuel Cabo 2012.
8 //          Copyright Mario Kröplin 2017.
9 // Distributed under the Boost Software License, Version 1.0.
10 //    (See accompanying file LICENSE_1_0.txt or copy at
11 //          http://www.boost.org/LICENSE_1_0.txt)
12 
13 module example;
14 
15 import dunit;
16 import core.thread;
17 import core.time;
18 import std.range;
19 import std.stdio;
20 import std.system : os;
21 
22 /**
23  * This example demonstrates the reporting of test failures.
24  */
25 class Test
26 {
27     mixin UnitTest;
28 
29     @Test
30     public void assertEqualsFailure() @safe pure
31     {
32         string expected = "bar";
33         string actual = "baz";
34 
35         assertEquals(expected, actual);
36     }
37 
38     @Test
39     public void assertAssocArrayEqualsFailure() pure
40     {
41         string[int] expected = [1: "foo", 2: "bar"];
42         string[int] actual = [1: "foo", 2: "baz"];
43 
44         assertArrayEquals(expected, actual);
45     }
46 
47     @Test
48     public void assertRangeEqualsFailure() @safe pure
49     {
50         int[] expected = [0, 1, 1, 2];
51         auto actual = iota(0, 3);
52 
53         assertRangeEquals(expected, actual);
54     }
55 
56     @Test
57     public void assertAllFailure() @safe
58     {
59         assertAll(
60             assertLessThan(6 * 7, 42),
61             assertGreaterThan(6 * 7, 42),
62         );
63     }
64 }
65 
66 /**
67  * This example demonstrates the order in which the fixture functions run.
68  * The functions 'setUp' and 'tearDown' run before and after each test.
69  * The functions 'setUpAll' and 'tearDownAll' run once before and after
70  * all tests in the class.
71  */
72 class TestFixture
73 {
74     mixin UnitTest;
75 
76     public this()
77     {
78         debug writeln("@this()");
79     }
80 
81     @BeforeAll
82     public static void setUpAll()
83     {
84         debug writeln("@BeforeAll");
85     }
86 
87     @AfterAll
88     public static void tearDownAll()
89     {
90         debug writeln("@AfterAll");
91     }
92 
93     @BeforeEach
94     public void setUp()
95     {
96         debug writeln("@BeforeEach");
97     }
98 
99     @AfterEach
100     public void tearDown()
101     {
102         debug writeln("@AfterEach");
103     }
104 
105     @Test
106     public void test1() @safe pure
107     {
108         debug writeln("@test1()");
109     }
110 
111     @Test
112     public void test2() @safe pure
113     {
114         debug writeln("@test2()");
115     }
116 }
117 
118 /**
119  * This example demonstrates how to reuse tests and a test fixture.
120  */
121 class TestReuse : TestFixture
122 {
123     mixin UnitTest;
124 
125     @BeforeEach
126     public override void setUp()
127     {
128         debug writeln("@BeforeEach override");
129     }
130 }
131 
132 /**
133  * This example demonstrates various things to know about the test framework.
134  */
135 class TestingThisAndThat
136 {
137     mixin UnitTest;
138 
139     // test function can have default arguments
140     @Test
141     public void testResult(bool actual = true) @safe pure
142     {
143         assertTrue(actual);
144     }
145 
146     // test function can even be private
147     // tagged test functions can be selected to be included or excluded
148     @Test
149     @Tag("fast")
150     @Tag("smoke")
151     private void success() @safe pure
152     {
153         testResult(true);
154     }
155 
156     // disabled test function
157     @Test
158     @Disabled("not ready yet")
159     public void failure() @safe pure
160     {
161         testResult(false);
162     }
163 
164     // disabled, because condition is true
165     @Test
166     @DisabledIf(() => true, "disabled by condition")
167     public void disabledByCondition() @safe pure
168     {
169         testResult(false);
170     }
171 
172     // not disabled, because condition is false
173     @Test
174     @DisabledIf(() => false, "disabled by condition")
175     public void notDisabledByCondition() @safe pure
176     {
177         testResult(true);
178     }
179 
180     // not disabled, because condition is true
181     @Test
182     @EnabledIf(() => true, "not enabled by condition")
183     public void enabledByCondition() @safe pure
184     {
185         testResult(true);
186     }
187 
188     // disabled, because condition is false
189     @Test
190     @EnabledIf(() => false, "not enabled by condition")
191     public void notEnabledByCondition() @safe pure
192     {
193         testResult(false);
194     }
195 
196     // disabled, because environment variable matches pattern
197     @Test
198     @DisabledIfEnvironmentVariable("PATH", ".*")
199     public void disabledByEnvironmentVariable() @safe pure
200     {
201         testResult(false);
202     }
203 
204     // not disabled, because environment variable does not match pattern
205     @Test
206     @DisabledIfEnvironmentVariable("PATH", "42")
207     public void notDisabledByEnvironmentVariable() @safe pure
208     {
209         testResult(true);
210     }
211 
212     // not disabled, because environment variable matches pattern
213     @Test
214     @EnabledIfEnvironmentVariable("PATH", ".*")
215     public void enabledByEnvironmentVariable() @safe pure
216     {
217         testResult(true);
218     }
219 
220     // disabled, because environment variable does not match pattern
221     @Test
222     @EnabledIfEnvironmentVariable("PATH", "42")
223     public void notEnabledByEnvironmentVariable() @safe pure
224     {
225         testResult(false);
226     }
227 
228     // disabled on the operating system on which the program runs
229     @Test
230     @DisabledOnOs(os)
231     public void disabledByOs() @safe pure
232     {
233         testResult(false);
234     }
235 
236     // not disabled on the operating system on which the program runs
237     @Test
238     @EnabledOnOs(os)
239     public void enabledByOs() @safe pure
240     {
241         testResult(true);
242     }
243 
244     // failed contracts are errors, not failures
245     @Test
246     public void error() @safe pure
247     {
248         assert(false);
249     }
250 
251     // expected exception can be further verified
252     @Test
253     public void testException() @safe pure
254     {
255         import std.exception : enforce;
256 
257         auto exception = expectThrows(enforce(false));
258 
259         assertEquals("Enforcement failed", exception.msg);
260     }
261 }
262 
263 /**
264  * This example demonstrates how to test asynchronous code.
265  */
266 class TestingAsynchronousCode
267 {
268     mixin UnitTest;
269 
270     private Thread thread;
271 
272     private bool done;
273 
274     @BeforeEach
275     public void setUp()
276     {
277         done = false;
278         thread = new Thread(&threadFunction);
279     }
280 
281     @AfterEach
282     public void tearDown()
283     {
284         thread.join();
285     }
286 
287     private void threadFunction()
288     {
289         Thread.sleep(100.msecs);
290         done = true;
291     }
292 
293     @Test
294     @Tag("slow")
295     public void test()
296     {
297         assertFalse(done);
298 
299         thread.start();
300 
301         assertEventually({ return done; });
302     }
303 }
304 
305 // either use the 'Main' mixin or call 'dunit_main(args)'
306 mixin Main;