1 module unit_threaded.ut.reflection; 2 3 import unit_threaded.reflection; 4 import unit_threaded.ut.modules.module_with_tests; //defines tests and non-tests 5 import unit_threaded.asserts; 6 import std.algorithm; 7 import std.array; 8 9 //helper function for the unittest blocks below 10 private auto addModPrefix(string[] elements, 11 string module_ = "unit_threaded.ut.modules.module_with_tests") nothrow { 12 return elements.map!(a => module_ ~ "." ~ a).array; 13 } 14 15 16 unittest { 17 const expected = addModPrefix([ "FooTest", "BarTest", "Blergh", "Issue83"]); 18 const actual = moduleTestClasses!(unit_threaded.ut.modules.module_with_tests). 19 map!(a => a.name).array; 20 assertEqual(actual, expected); 21 } 22 23 unittest { 24 const expected = addModPrefix([ "testFoo", "testBar", "funcThatShouldShowUpCosOfAttr"]); 25 const actual = moduleTestFunctions!(unit_threaded.ut.modules.module_with_tests). 26 map!(a => a.getPath).array; 27 assertEqual(actual, expected); 28 } 29 30 31 unittest { 32 const expected = addModPrefix(["unittest0", "unittest1", "myUnitTest", 33 "StructWithUnitTests.InStruct", "StructWithUnitTests.unittest1"]); 34 const actual = moduleUnitTests!(unit_threaded.ut.modules.module_with_tests). 35 map!(a => a.name).array; 36 assertEqual(actual, expected); 37 } 38 39 version(unittest) { 40 import unit_threaded.testcase: TestCase; 41 private void assertFail(TestCase test, string file = __FILE__, size_t line = __LINE__) { 42 import core.exception; 43 import std.conv; 44 45 test.silence; 46 assert(test() != [], 47 file ~ ":" ~ line.to!string ~ " Expected test case " ~ test.getPath ~ 48 " to fail but it didn't"); 49 } 50 51 private void assertPass(TestCase test, string file = __FILE__, size_t line = __LINE__) { 52 import unit_threaded.should: fail; 53 if(test() != []) 54 fail("'" ~ test.getPath ~ "' was expected to pass but failed", file, line); 55 } 56 } 57 58 @("Test that parametrized value tests work") 59 unittest { 60 import unit_threaded.factory; 61 import unit_threaded.testcase; 62 import unit_threaded.ut.modules.parametrized; 63 64 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 65 filter!(a => a.name.endsWith("testValues")).array; 66 67 auto tests = createTestCases(testData); 68 assertEqual(tests.length, 3); 69 70 // the first and third test should pass, the second should fail 71 assertPass(tests[0]); 72 assertPass(tests[2]); 73 74 assertFail(tests[1]); 75 } 76 77 78 @("Test that parametrized type tests work") 79 unittest { 80 import unit_threaded.factory; 81 import unit_threaded.testcase; 82 import unit_threaded.ut.modules.parametrized; 83 84 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 85 filter!(a => a.name.endsWith("testTypes")).array; 86 const expected = addModPrefix(["testTypes.float", "testTypes.int"], 87 "unit_threaded.ut.modules.parametrized"); 88 const actual = testData.map!(a => a.getPath).array; 89 assertEqual(actual, expected); 90 91 auto tests = createTestCases(testData); 92 assertEqual(tests.map!(a => a.getPath).array, expected); 93 94 assertPass(tests[1]); 95 assertFail(tests[0]); 96 } 97 98 @("Value parametrized built-in unittests") 99 unittest { 100 import unit_threaded.factory; 101 import unit_threaded.testcase; 102 import unit_threaded.ut.modules.parametrized; 103 104 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 105 filter!(a => a.name.canFind("builtinIntValues")).array; 106 107 auto tests = createTestCases(testData); 108 assertEqual(tests.length, 4); 109 110 // these should be ok 111 assertPass(tests[1]); 112 113 //these should fail 114 assertFail(tests[0]); 115 assertFail(tests[2]); 116 assertFail(tests[3]); 117 } 118 119 120 @("Tests can be selected by tags") unittest { 121 import unit_threaded.factory; 122 import unit_threaded.testcase; 123 import unit_threaded.ut.modules.tags; 124 125 const testData = allTestData!(unit_threaded.ut.modules.tags).array; 126 auto testsNoTags = createTestCases(testData); 127 assertEqual(testsNoTags.length, 4); 128 assertPass(testsNoTags[0]); 129 assertFail(testsNoTags.find!(a => a.getPath.canFind("unittest1")).front); 130 assertFail(testsNoTags[2]); 131 assertFail(testsNoTags[3]); 132 133 auto testsNinja = createTestCases(testData, ["@ninja"]); 134 assertEqual(testsNinja.length, 1); 135 assertPass(testsNinja[0]); 136 137 auto testsMake = createTestCases(testData, ["@make"]); 138 assertEqual(testsMake.length, 3); 139 assertPass(testsMake.find!(a => a.getPath.canFind("testMake")).front); 140 assertPass(testsMake.find!(a => a.getPath.canFind("unittest0")).front); 141 assertFail(testsMake.find!(a => a.getPath.canFind("unittest2")).front); 142 143 auto testsNotNinja = createTestCases(testData, ["~@ninja"]); 144 assertEqual(testsNotNinja.length, 3); 145 assertPass(testsNotNinja.find!(a => a.getPath.canFind("testMake")).front); 146 assertFail(testsNotNinja.find!(a => a.getPath.canFind("unittest1")).front); 147 assertFail(testsNotNinja.find!(a => a.getPath.canFind("unittest2")).front); 148 149 assertEqual(createTestCases(testData, ["unit_threaded.ut.modules.tags.testMake", "@ninja"]).length, 0); 150 } 151 152 @("Parametrized built-in tests with @AutoTags get tagged by value") 153 unittest { 154 import unit_threaded.factory; 155 import unit_threaded.testcase; 156 import unit_threaded.ut.modules.parametrized; 157 158 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 159 filter!(a => a.name.canFind("builtinIntValues")).array; 160 161 auto two = createTestCases(testData, ["@2"]); 162 163 assertEqual(two.length, 1); 164 assertFail(two[0]); 165 166 auto three = createTestCases(testData, ["@3"]); 167 assertEqual(three.length, 1); 168 assertPass(three[0]); 169 } 170 171 @("Value parametrized function tests with @AutoTags get tagged by value") 172 unittest { 173 import unit_threaded.factory; 174 import unit_threaded.testcase; 175 import unit_threaded.ut.modules.parametrized; 176 177 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 178 filter!(a => a.name.canFind("testValues")).array; 179 180 auto two = createTestCases(testData, ["@2"]); 181 assertEqual(two.length, 1); 182 assertFail(two[0]); 183 } 184 185 @("Type parameterized tests with @AutoTags get tagged by type") 186 unittest { 187 import unit_threaded.factory; 188 import unit_threaded.testcase; 189 import unit_threaded.ut.modules.parametrized; 190 191 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 192 filter!(a => a.name.canFind("testTypes")).array; 193 194 auto tests = createTestCases(testData, ["@int"]); 195 assertEqual(tests.length, 1); 196 assertPass(tests[0]); 197 } 198 199 @("Cartesian parameterized built-in values") unittest { 200 import unit_threaded.factory; 201 import unit_threaded.testcase; 202 import unit_threaded.should: shouldBeSameSetAs; 203 import unit_threaded.ut.modules.parametrized; 204 import unit_threaded.attrs: getValue; 205 206 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 207 filter!(a => a.name.canFind("cartesianBuiltinNoAutoTags")).array; 208 209 auto tests = createTestCases(testData); 210 tests.map!(a => a.getPath).array.shouldBeSameSetAs( 211 addModPrefix(["foo.red", "foo.blue", "foo.green", "bar.red", "bar.blue", "bar.green"]. 212 map!(a => "cartesianBuiltinNoAutoTags." ~ a).array, 213 "unit_threaded.ut.modules.parametrized")); 214 assertEqual(tests.length, 6); 215 216 auto fooRed = tests.find!(a => a.getPath.canFind("foo.red")).front; 217 assertPass(fooRed); 218 assertEqual(getValue!(string, 0), "foo"); 219 assertEqual(getValue!(string, 1), "red"); 220 assertEqual(testData.find!(a => a.getPath.canFind("foo.red")).front.tags, []); 221 222 auto barGreen = tests.find!(a => a.getPath.canFind("bar.green")).front; 223 assertFail(barGreen); 224 assertEqual(getValue!(string, 0), "bar"); 225 assertEqual(getValue!(string, 1), "green"); 226 227 assertEqual(testData.find!(a => a.getPath.canFind("bar.green")).front.tags, []); 228 assertEqual(allTestData!(unit_threaded.ut.modules.parametrized). 229 filter!(a => a.name.canFind("cartesianBuiltinAutoTags")).array. 230 find!(a => a.getPath.canFind("bar.green")).front.tags, 231 ["bar", "green"]); 232 } 233 234 @("Cartesian parameterized function values") unittest { 235 import unit_threaded.factory; 236 import unit_threaded.testcase; 237 import unit_threaded.should: shouldBeSameSetAs; 238 239 const testData = allTestData!(unit_threaded.ut.modules.parametrized). 240 filter!(a => a.name.canFind("CartesianFunction")).array; 241 242 auto tests = createTestCases(testData); 243 tests.map!(a => a.getPath).array.shouldBeSameSetAs( 244 addModPrefix(["1.foo", "1.bar", "2.foo", "2.bar", "3.foo", "3.bar"]. 245 map!(a => "testCartesianFunction." ~ a).array, 246 "unit_threaded.ut.modules.parametrized")); 247 248 foreach(test; tests) { 249 test.getPath.canFind("2.bar") 250 ? assertPass(test) 251 : assertFail(test); 252 } 253 254 assertEqual(testData.find!(a => a.getPath.canFind("2.bar")).front.tags, 255 ["2", "bar"]); 256 257 } 258 259 @("module setup and shutdown") 260 unittest { 261 import unit_threaded.testcase; 262 import unit_threaded.factory; 263 import unit_threaded.ut.modules.module_with_setup: gNumBefore, gNumAfter; 264 265 const testData = allTestData!"unit_threaded.ut.modules.module_with_setup".array; 266 auto tests = createTestCases(testData); 267 assertEqual(tests.length, 2); 268 269 assertPass(tests[0]); 270 assertEqual(gNumBefore, 1); 271 assertEqual(gNumAfter, 1); 272 273 assertFail(tests[1]); 274 assertEqual(gNumBefore, 2); 275 assertEqual(gNumAfter, 2); 276 } 277 278 @("issue 33") unittest { 279 import unit_threaded.factory; 280 import unit_threaded.testcase; 281 282 const testData = allTestData!"unit_threaded.ut.modules.issue33"; 283 assertEqual(testData.length, 1); 284 } 285 286 @("issue 43") unittest { 287 import unit_threaded.factory; 288 import unit_threaded.asserts; 289 import unit_threaded.ut.modules.module_with_tests; 290 import std.algorithm: canFind; 291 import std.array: array; 292 293 const testData = allTestData!"unit_threaded.ut.modules.module_with_tests"; 294 assertEqual(testData.canFind!(a => a.getPath.canFind("InStruct" )), true); 295 auto inStructTest = testData 296 .find!(a => a.getPath.canFind("InStruct")) 297 .array 298 .createTestCases[0]; 299 assertFail(inStructTest); 300 } 301 302 @("@DontTest should work for unittest blocks") unittest { 303 import unit_threaded.factory; 304 import unit_threaded.asserts; 305 import unit_threaded.ut.modules.module_with_tests; 306 import std.algorithm: canFind; 307 import std.array: array; 308 309 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 310 assertEqual(testData.canFind!(a => a.getPath.canFind("DontTestBlock" )), false); 311 } 312 313 @("@ShouldFail") unittest { 314 import unit_threaded.factory; 315 import unit_threaded.asserts; 316 import unit_threaded.ut.modules.module_with_tests; 317 import std.algorithm: find, canFind; 318 import std.array: array; 319 320 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 321 322 auto willFail = testData 323 .filter!(a => a.getPath.canFind("will fail")) 324 .array 325 .createTestCases[0]; 326 assertPass(willFail); 327 } 328 329 330 @("@ShouldFailWith") unittest { 331 import unit_threaded.factory; 332 import unit_threaded.asserts; 333 import unit_threaded.ut.modules.module_with_attrs; 334 import std.algorithm: find, canFind; 335 import std.array: array; 336 337 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 338 339 auto doesntFail = testData 340 .filter!(a => a.getPath.canFind("ShouldFailWith that fails due to not failing")) 341 .array 342 .createTestCases[0]; 343 assertFail(doesntFail); 344 345 auto wrongType = testData 346 .find!(a => a.getPath.canFind("ShouldFailWith that fails due to wrong type")) 347 .array 348 .createTestCases[0]; 349 assertFail(wrongType); 350 351 auto passes = testData 352 .find!(a => a.getPath.canFind("ShouldFailWith that passes")) 353 .array 354 .createTestCases[0]; 355 assertPass(passes); 356 } 357 358 @("structs are not classes") unittest { 359 import unit_threaded.should; 360 import unit_threaded.ut.modules.structs_are_not_classes; 361 const testData = allTestData!"unit_threaded.ut.modules.structs_are_not_classes"; 362 testData.shouldBeEmpty; 363 } 364 365 @("@Flaky") unittest { 366 import unit_threaded.factory; 367 import unit_threaded.asserts; 368 import unit_threaded.ut.modules.module_with_attrs; 369 import std.algorithm: find, canFind; 370 import std.array: array; 371 372 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 373 374 auto flakyPasses = testData 375 .filter!(a => a.getPath.canFind("flaky that passes eventually")) 376 .array 377 .createTestCases[0]; 378 assertPass(flakyPasses); 379 380 auto flakyFails = testData 381 .filter!(a => a.getPath.canFind("flaky that fails due to not enough retries")) 382 .array 383 .createTestCases[0]; 384 assertFail(flakyFails); 385 }