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;