1 /**
2   Copyright: 2017 © LLC CERERIS
3   License: MIT
4   Authors: LLC CERERIS
5 */
6 
7 module checkit.runner;
8 
9 import checkit.block;
10 import checkit.blockmanager;
11 import checkit.reporter;
12 import std.conv;
13 import std.getopt;
14 import std.stdio;
15 
16 /// Interface for running test
17 interface RunnerInterface
18 {
19   public:
20     /// Run tests and return code
21     int run();
22 }
23 
24 /** Provide run BDD tests
25 
26   Params:
27     T = BlockManagerInterface
28 */
29 class BDDTestRunner(T): RunnerInterface
30 {
31   public:
32     /** Constructor
33 
34       Params:
35         reporter = Provide reporting test.
36 
37       Examples:
38         ---
39         auto reporter = new ConsoleReporter();
40         auto runner = new BDDTestRunner!(reporter);
41         ---
42     */
43     this(ReporterInterface reporter)
44     {
45       _reporter = reporter;
46     }
47 
48     /** Run tests and return code
49 
50     Returns:
51         Return code $(D int) for main function
52 
53       Examples:
54         ---
55         auto reporter = new ConsoleReporter();
56         auto runner = new BDDTestRunner!(reporter);
57         runner.run();
58         ---
59     */
60     int run()
61     {
62       _returnCode = 0;
63       _failBlocks = [];
64       _successBlocks = [];
65       checkNoBlock!GivenBlock();
66       checkNoBlock!WhenBlock();
67       checkNoBlock!ThenBlock();
68 
69       foreach(scenario; T.getByType!ScenarioBlock())
70       {
71         runBlock(scenario);
72       }
73 
74       _reporter.printResults(_successBlocks, _failBlocks);
75 
76       return _returnCode;
77     }
78 
79   private:
80 
81     void checkNoBlock(U)()
82     {
83       U[] blocks = T.getByType!U();
84       if(blocks.length)
85       {
86         _returnCode = -1;
87 
88         foreach(block; blocks)
89         {
90           T.removeBlockByUUID(block.getUUID());
91         }
92       }
93     }
94 
95     void runBlock(ScenarioBlock block)
96     {
97       checkNoBlock!WhenBlock();
98       checkNoBlock!ThenBlock();
99 
100       executeBlock(block);
101       foreach(given; T.getByType!GivenBlock())
102       {
103         runBlock(given);
104       }
105     }
106 
107     void runBlock(GivenBlock block)
108     {
109       checkNoBlock!ThenBlock();
110 
111       executeBlock(block);
112       foreach(when; T.getByType!WhenBlock())
113       {
114         runBlock(when);
115       }
116     }
117 
118     void runBlock(WhenBlock block)
119     {
120       executeBlock(block);
121       foreach(then; T.getByType!ThenBlock())
122       {
123         executeBlock(then);
124       }
125     }
126 
127     void executeBlock(U)(U block)
128     {
129       try
130       {
131         block.getCallback()();
132         _reporter.success(block);
133         _successBlocks ~= block;
134       }
135       catch(Exception e)
136       {
137         _returnCode = -1;
138         _failBlocks ~= block;
139         _reporter.fail(block);
140         _reporter.fail(typeid(e).toString() ~ "@" ~ e.file ~ "(" ~ to!string(e.line) ~ "): " ~ e.msg);
141       }
142 
143       T.removeBlockByUUID(block.getUUID());
144     }
145 
146     ReporterInterface _reporter;
147     int _returnCode;
148     TestBlock[] _successBlocks;
149     TestBlock[] _failBlocks;
150 }
151 
152 int runTests(string[] args)
153 {
154   bool verbose = false;
155 
156   getopt(
157     args,
158     "verbose|v", &verbose
159   );
160 
161   auto reporter = new ConsoleReporter;
162   reporter.setVerbose(verbose);
163   auto runner = new BDDTestRunner!BlockManager(reporter);
164   return runner.run();
165 }