1 module unit_threaded.ut.reflection; 2 3 import unit_threaded.runner.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 17 unittest { 18 import std.algorithm: sorted = sort; 19 20 const expected = addModPrefix( 21 [ 22 "myUnitTest", 23 "StructWithUnitTests.InStruct", 24 "StructWithUnitTests.unittest_L58_C5", 25 "unittest_L36", 26 "unittest_L41", 27 ] 28 ).sorted.array; 29 const actual = moduleUnitTests!(unit_threaded.ut.modules.module_with_tests). 30 map!(a => a.name).array.sorted.array; 31 32 assertEqual(actual, expected); 33 } 34 35 version(unittest) { 36 import unit_threaded.runner.testcase: TestCase; 37 private void assertFail(TestCase test, string file = __FILE__, size_t line = __LINE__) { 38 import core.exception; 39 import std.conv; 40 41 test.silence; 42 assert(test() != [], 43 file ~ ":" ~ line.to!string ~ " Expected test case " ~ test.getPath ~ 44 " to fail but it didn't"); 45 } 46 47 private void assertPass(TestCase test, string file = __FILE__, size_t line = __LINE__) { 48 import unit_threaded.should: fail; 49 if(test() != []) 50 fail("'" ~ test.getPath ~ "' was expected to pass but failed", file, line); 51 } 52 } 53 54 55 @("Tests can be selected by tags") unittest { 56 import unit_threaded.runner.factory; 57 import unit_threaded.runner.testcase; 58 import unit_threaded.ut.modules.tags; 59 60 const testData = allTestData!(unit_threaded.ut.modules.tags).array; 61 auto testsNoTags = createTestCases(testData); 62 assertEqual(testsNoTags.length, 3); 63 assertPass(testsNoTags.find!(a => a.getPath.canFind("unittest_L6")).front); 64 assertFail(testsNoTags.find!(a => a.getPath.canFind("unittest_L8")).front); 65 assertFail(testsNoTags.find!(a => a.getPath.canFind("unittest_L14")).front); 66 67 auto testsNinja = createTestCases(testData, ["@ninja"]); 68 assertEqual(testsNinja.length, 1); 69 assertPass(testsNinja[0]); 70 71 auto testsMake = createTestCases(testData, ["@make"]); 72 assertEqual(testsMake.length, 2); 73 assertPass(testsMake.find!(a => a.getPath.canFind("unittest_L6")).front); 74 assertFail(testsMake.find!(a => a.getPath.canFind("unittest_L14")).front); 75 76 auto testsNotNinja = createTestCases(testData, ["~@ninja"]); 77 assertEqual(testsNotNinja.length, 2); 78 assertFail(testsNotNinja.find!(a => a.getPath.canFind("unittest_L8")).front); 79 assertFail(testsNotNinja.find!(a => a.getPath.canFind("unittest_L14")).front); 80 81 assertEqual(createTestCases(testData, ["unit_threaded.ut.modules.tags.testMake", "@ninja"]).length, 0); 82 } 83 84 85 @("module setup and shutdown") 86 unittest { 87 import unit_threaded.runner.testcase; 88 import unit_threaded.runner.factory; 89 import unit_threaded.ut.modules.module_with_setup: gNumBefore, gNumAfter; 90 91 const testData = allTestData!"unit_threaded.ut.modules.module_with_setup".array; 92 auto tests = createTestCases(testData); 93 assertEqual(tests.length, 2); 94 95 assertPass(tests[0]); 96 assertEqual(gNumBefore, 1); 97 assertEqual(gNumAfter, 1); 98 99 assertFail(tests[1]); 100 assertEqual(gNumBefore, 2); 101 assertEqual(gNumAfter, 2); 102 } 103 104 @("issue 33") unittest { 105 import unit_threaded.runner.factory; 106 import unit_threaded.runner.testcase; 107 108 const testData = allTestData!"unit_threaded.ut.modules.issue33"; 109 assertEqual(testData.length, 1); 110 } 111 112 @("issue 43") unittest { 113 import unit_threaded.runner.factory; 114 import unit_threaded.asserts; 115 import unit_threaded.ut.modules.module_with_tests; 116 import std.algorithm: canFind; 117 import std.array: array; 118 119 const testData = allTestData!"unit_threaded.ut.modules.module_with_tests"; 120 assertEqual(testData.canFind!(a => a.getPath.canFind("InStruct" )), true); 121 auto inStructTest = testData 122 .find!(a => a.getPath.canFind("InStruct")) 123 .array 124 .createTestCases[0]; 125 assertFail(inStructTest); 126 } 127 128 @("@DontTest should work for unittest blocks") unittest { 129 import unit_threaded.runner.factory; 130 import unit_threaded.asserts; 131 import unit_threaded.ut.modules.module_with_tests; 132 import std.algorithm: canFind; 133 import std.array: array; 134 135 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 136 assertEqual(testData.canFind!(a => a.getPath.canFind("DontTestBlock" )), false); 137 } 138 139 @("@ShouldFail") unittest { 140 import unit_threaded.runner.factory; 141 import unit_threaded.asserts; 142 import unit_threaded.ut.modules.module_with_tests; 143 import std.algorithm: find, canFind; 144 import std.array: array; 145 146 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 147 148 auto willFail = testData 149 .filter!(a => a.getPath.canFind("will fail")) 150 .array 151 .createTestCases[0]; 152 assertPass(willFail); 153 } 154 155 156 @("@ShouldFailWith") unittest { 157 import unit_threaded.runner.factory; 158 import unit_threaded.asserts; 159 import unit_threaded.ut.modules.module_with_attrs; 160 import std.algorithm: find, canFind; 161 import std.array: array; 162 163 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 164 165 auto doesntFail = testData 166 .filter!(a => a.getPath.canFind("ShouldFailWith that fails due to not failing")) 167 .array 168 .createTestCases[0]; 169 assertFail(doesntFail); 170 171 auto wrongType = testData 172 .find!(a => a.getPath.canFind("ShouldFailWith that fails due to wrong type")) 173 .array 174 .createTestCases[0]; 175 assertFail(wrongType); 176 177 auto passes = testData 178 .find!(a => a.getPath.canFind("ShouldFailWith that passes")) 179 .array 180 .createTestCases[0]; 181 assertPass(passes); 182 } 183 184 @("structs are not classes") unittest { 185 import unit_threaded.should; 186 import unit_threaded.ut.modules.structs_are_not_classes; 187 const testData = allTestData!"unit_threaded.ut.modules.structs_are_not_classes"; 188 testData.shouldBeEmpty; 189 } 190 191 @("@Flaky") unittest { 192 import unit_threaded.runner.factory; 193 import unit_threaded.asserts; 194 import unit_threaded.ut.modules.module_with_attrs; 195 import std.algorithm: find, canFind; 196 import std.array: array; 197 198 const testData = allTestData!"unit_threaded.ut.modules.module_with_attrs"; 199 200 auto flakyPasses = testData 201 .filter!(a => a.getPath.canFind("flaky that passes eventually")) 202 .array 203 .createTestCases[0]; 204 assertPass(flakyPasses); 205 206 auto flakyFails = testData 207 .filter!(a => a.getPath.canFind("flaky that fails due to not enough retries")) 208 .array 209 .createTestCases[0]; 210 assertFail(flakyFails); 211 }