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