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