1 /**
2 Advanced unit-testing.
3 
4 Copyright: Atila Neves
5 License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
6 Authors: Atila Neves
7 
8 $(D D)'s $(D unittest) blocks are a built-in feature of the language that allows
9 for easy unit testing with no boilerplate. As a program grows it's usual to need
10 or want more advanced testing features, which are provided by this package.
11 
12 The easiest way to run tests with the functionality provided is to have a $(D D)
13 module implementing a $(D main) function similar to this one:
14 
15 -----
16 import unit_threaded;
17 
18 int main(string[] args) {
19      return runTests!("name.of.mymodule",
20                       "name.of.other.module")(args);
21 }
22 -----
23 
24 This will (by default) run all $(D unittest) blocks in the modules
25 passed in as compile-time parameters in multiple threads. Unit tests
26 can be named: to do so simply use the supplied $(D name)
27 $(LINK2 http://dlang.org/attribute.html#uda, UDA). There are other supplied
28 UDAs. Please consult the relevant documentation.
29 
30 As an alternative to writing a program like the one above manually,
31 the included $(D gen_ut_main.d) file can be run as a script and will
32 generate such a file.  This can be run as part of the build system to
33 recreate the unit test main file.  $(D gen_ut_main.d) checks to see if
34 the file list has changed and will not regenerate the file if that's
35 not needed.
36 
37 Examples:
38 
39 -----
40 
41 @name("testTimesTwo")
42 unittest
43 {
44     int timesTwo(int i) { return i * 2; }
45 
46     2.timesTwo.shouldEqual(4);
47     3.timesTwo.shouldEqual(6);
48 }
49 
50 @name("testRange")
51 unittest
52 {
53     import std.range: iota;
54     iota(3).shouldEqual([0, 1, 2]);
55     3.shouldBeIn(iota(5));
56 }
57 
58 @name("testIn")
59 unittest
60 {
61     auto ints = [1, 2, 3, 4];
62     3.shouldBeIn(ints);
63     1.shouldBeIn(ints);
64     5.shouldNotBeIn(ints);
65 }
66 
67 @name("testThrows")
68 unittest
69 {
70     void throwRangeError()
71     {
72         ubyte[] bytes;
73         bytes = bytes[1..$];
74     }
75     import core.exception: RangeError;
76     throwRangeError.shouldThrow!RangeError;
77 }
78 
79 //a test that is expected to fail
80 @name("testOops")
81 @shouldFail("Bug #1234")
82 unittest
83 {
84     3.shouldEqual(5); //won't cause the suite to fail
85 }
86 
87 //prevent data races
88 __gshared int i;
89 
90 @name("sideEffect1")
91 @serial //all @serial tests in a module run in the same thread
92 unittest
93 {
94     i++;
95     i.shouldEqual(1);
96 }
97 
98 @name("sideEffect2")
99 @serial //all @serial tests in a module run in the same thread
100 unittest
101 {
102     i++;
103     i.shouldEqual(2);
104 }
105 
106 
107 -----
108  */
109 
110 module unit_threaded;
111 
112 public import unit_threaded.should;
113 public import unit_threaded.testcase;
114 public import unit_threaded.io;
115 public import unit_threaded.reflection;
116 public import unit_threaded.runner;
117 public import unit_threaded.runtime;