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