1 /**
2  * This module implements functions to run the unittests with
3  * command-line options.
4  */
5 
6 module unit_threaded.runner;
7 
8 import unit_threaded.reflection: TestData;
9 import unit_threaded.options: Options;
10 
11 /**
12  * Runs all tests in passed-in modules. Modules can be symbols or
13  * strings. Generates a main function and substitutes the default D
14  * runtime unittest runner. This mixin should be used instead of
15  * $(D runTests) if Phobos is linked as a shared library.
16  */
17 mixin template runTestsMixin(Modules...) if(Modules.length > 0) {
18 
19     shared static this() {
20         import unit_threaded.testsuite : replaceModuleUnitTester;
21 
22         replaceModuleUnitTester;
23     }
24 
25     int main(string[] args) {
26         return runTests!Modules(args);
27     }
28 }
29 
30 /**
31  * Runs all tests in passed-in modules. Modules can be symbols
32  * or strings. Arguments are taken from the command-line.
33  * -s Can be passed to run in single-threaded mode. The rest
34  * of argv is considered to be test names to be run.
35  * Params:
36  *   args = Arguments passed to main.
37  * Returns: An integer suitable for the program's return code.
38  */
39 int runTests(Modules...)(string[] args) if(Modules.length > 0) {
40     import unit_threaded.reflection: allTestData;
41     return runTests(args, allTestData!Modules);
42 }
43 
44 /**
45  * Runs all tests in passed-in testData. Arguments are taken from the
46  * command-line. `-s` Can be passed to run in single-threaded mode. The
47  * rest of argv is considered to be test names to be run.
48  * Params:
49  *   args = Arguments passed to main.
50  *   testData = Data about the tests to run.
51  * Returns: An integer suitable for the program's return code.
52  */
53 int runTests(string[] args, in TestData[] testData) {
54     import unit_threaded.options: getOptions;
55     import unit_threaded.testsuite: TestSuite;
56 
57     const options = getOptions(args);
58     handleCmdLineOptions(options, testData);
59     if (options.exit)
60         return 0;
61 
62     auto suite = TestSuite(options, testData);
63     return suite.run ? 0 : 1;
64 }
65 
66 private void handleCmdLineOptions(in Options options, in TestData[] testData) {
67 
68     import unit_threaded.io: enableDebugOutput, forceEscCodes;
69     import unit_threaded.testcase: enableStackTrace;
70     import std.algorithm: map;
71 
72     if (options.list) {
73         import std.stdio: writeln;
74 
75         writeln("Listing tests:");
76         foreach (test; testData.map!(a => a.name)) {
77             writeln(test);
78         }
79     }
80 
81     if (options.debugOutput)
82         enableDebugOutput();
83 
84     if (options.forceEscCodes)
85         forceEscCodes();
86 
87     if (options.stackTraces)
88         enableStackTrace();
89 }