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;