1 module unit_threaded.testsuite;
2 
3 import unit_threaded.testcase;
4 import unit_threaded.writer_thread;
5 import std.datetime;
6 import std.parallelism;
7 import std.concurrency;
8 import std.stdio;
9 import std.conv;
10 
11 /**
12  * Responsible for running tests
13  */
14 struct TestSuite {
15     this(TestCase[] tests) {
16         _tests = tests;
17     }
18 
19     double run(in bool multiThreaded = true) {
20         _stopWatch.start();
21 
22         immutable redirectIo = multiThreaded;
23 
24         if(multiThreaded) {
25             foreach(test; taskPool.parallel(_tests)) innerLoop(test);
26         } else {
27             foreach(test; _tests) innerLoop(test);
28         }
29 
30         if(_failures) utWriteln("");
31         foreach(failure; _failures) {
32             utWriteln("Test ", failure, " failed.");
33         }
34         if(_failures) writeln("");
35 
36         _stopWatch.stop();
37         return _stopWatch.peek().seconds();
38     }
39 
40     @property ulong numTestsRun() const pure nothrow {
41         return _tests.length;
42     }
43 
44     @property ulong numFailures() const pure nothrow {
45         return _failures.length;
46     }
47 
48     @property bool passed() const pure nothrow {
49         return numFailures() == 0;
50     }
51 
52 private:
53     TestCase[] _tests;
54     string[] _failures;
55     StopWatch _stopWatch;
56 
57     void addFailure(in string testPath) nothrow {
58         _failures ~= testPath;
59     }
60 
61     void innerLoop(TestCase test) {
62         utWriteln(test.getPath() ~ ":");
63         immutable result = test();
64         if(result.failed) {
65             addFailure(test.getPath());
66         }
67         utWrite(result.output);
68     }
69 }