##### Coverage Report - org.jbehave.core.reporters.PostStoryStatisticsCollector

Classes in this File | Line Coverage | Branch Coverage | Complexity
PostStoryStatisticsCollector |
88% | 110/124
88% | 39/44
| 1.6875;1.688

1 |  |
     package org.jbehave.core.reporters;
2 |  |
3 |  |
     import java.io.IOException;
4 |  |
     import java.io.OutputStream;
5 |  |
     import java.util.HashMap;
6 |  |
     import java.util.List;
7 |  |
     import java.util.Map;
8 |  |
     import java.util.Properties;
9 |  |
10 |  |
     import org.apache.commons.lang.builder.ToStringBuilder;
11 |  |
     import org.apache.commons.lang.builder.ToStringStyle;
12 |  |
     import org.jbehave.core.model.ExamplesTable;
13 |  |
     import org.jbehave.core.model.GivenStories;
14 |  |
     import org.jbehave.core.model.Meta;
15 |  |
     import org.jbehave.core.model.Narrative;
16 |  |
     import org.jbehave.core.model.OutcomesTable;
17 |  |
     import org.jbehave.core.model.Scenario;
18 |  |
     import org.jbehave.core.model.Story;
19 |  |
     import org.jbehave.core.model.StoryDuration;
20 |  |
21 |  |
     import static java.util.Arrays.asList;
22 |  |
23 |  |
     /**
24 |  |
      * <p>
25 |  |
      * Reporter that collects statistics and writes them as properties to output
26 |  |
      * stream after each story
27 |  |
      * </p>
28 |  |
      */
29 |  |
     public class PostStoryStatisticsCollector implements StoryReporter {
30 |  |
31 |  |
         private final OutputStream output;
32 | 13 |
         private final Map<String, Integer> data = new HashMap<String, Integer>();
33 | 13 |
         private final List<String> events = asList("notAllowed", "pending", "scenariosNotAllowed",
34 |  |
                 "givenStoryScenariosNotAllowed", "steps", "stepsSuccessful", "stepsIgnorable", "stepsPending",
35 |  |
                 "stepsNotPerformed", "stepsFailed", "currentScenarioSteps", "currentScenarioStepsPending", "scenarios",
36 |  |
                 "scenariosSuccessful", "scenariosPending", "scenariosFailed", "givenStories", "givenStoryScenarios",
37 |  |
                 "givenStoryScenariosSuccessful", "givenStoryScenariosPending", "givenStoryScenariosFailed", "examples");
38 |  |
39 |  |
         private Throwable cause;
40 |  |
         private OutcomesTable outcomesFailed;
41 |  |
         private int givenStories;
42 |  |
         private long storyStartTime;
43 |  |
         private boolean currentScenarioNotAllowed;
44 |  |
45 | 13 |
         public PostStoryStatisticsCollector(OutputStream output) {
46 | 13 |
             this.output = output;
47 | 13 |
         }
48 |  |
49 |  |
         public void beforeStep(String step) {
50 | 0 |
         }
51 |  |
52 |  |
         public void successful(String step) {
53 | 4 |
             add("steps");
54 | 4 |
             add("stepsSuccessful");
55 | 4 |
             add("currentScenarioSteps");
56 | 4 |
         }
57 |  |
58 |  |
         public void ignorable(String step) {
59 | 1 |
             add("steps");
60 | 1 |
             add("stepsIgnorable");
61 | 1 |
             add("currentScenarioSteps");
62 | 1 |
         }
63 |  |
64 |  |
         public void pending(String step) {
65 | 1 |
             add("steps");
66 | 1 |
             add("stepsPending");
67 | 1 |
             add("currentScenarioSteps");
68 | 1 |
             add("currentScenarioStepsPending");
69 | 1 |
         }
70 |  |
71 |  |
         public void notPerformed(String step) {
72 | 2 |
             add("steps");
73 | 2 |
             add("stepsNotPerformed");
74 | 2 |
             add("currentScenarioSteps");
75 | 2 |
         }
76 |  |
77 |  |
         public void failed(String step, Throwable cause) {
78 | 2 |
             this.cause = cause;
79 | 2 |
             add("steps");
80 | 2 |
             add("stepsFailed");
81 | 2 |
             add("currentScenarioSteps");
82 | 2 |
         }
83 |  |
84 |  |
         public void failedOutcomes(String step, OutcomesTable table) {
85 | 2 |
             this.outcomesFailed = table;
86 | 2 |
             add("steps");
87 | 2 |
             add("stepsFailed");
88 | 2 |
             add("currentScenarioSteps");
89 | 2 |
         }
90 |  |
91 |  |
         public void beforeStory(Story story, boolean givenStory) {
92 | 6 |
             if (givenStory) {
93 | 3 |
                 this.givenStories++;
94 |  |
             }
95 |  |
96 | 6 |
             if (!givenStory) {
97 | 3 |
                 resetData();
98 | 3 |
                 storyStartTime = System.currentTimeMillis();
99 |  |
             }
100 | 6 |
         }
101 |  |
102 |  |
         public void narrative(final Narrative narrative) {
103 | 0 |
         }
104 |  |
105 |  |
         public void storyNotAllowed(Story story, String filter) {
106 | 1 |
             resetData();
107 | 1 |
             add("notAllowed");
108 | 1 |
             writeData();
109 | 1 |
         }
110 |  |
111 |  |
         public void storyCancelled(Story story, StoryDuration storyDuration) {
112 | 0 |
             add("cancelled");
113 | 0 |
         }
114 |  |
115 |  |
         public void afterStory(boolean givenStory) {
116 | 6 |
                 boolean write = false;
117 | 6 |
             if (givenStory) {
118 | 3 |
                 this.givenStories--;
119 | 3 |
                 if ( has("stepsFailed") ){
120 | 0 |
                         add("scenariosFailed");
121 | 0 |
                         write = true;
122 |  |
                 }
123 |  |
             } else {
124 | 3 |
                 if (has("scenariosPending") || has("givenStoryScenariosPending")) {
125 | 1 |
                     add("pending");
126 |  |
                 }
127 | 3 |
                 write = true;
128 |  |
             }
129 | 6 |
             if ( write ) {
130 | 3 |
                 int duration = (int)(System.currentTimeMillis() - storyStartTime);
131 | 3 |
                 data.put("duration", duration);
132 | 3 |
                 writeData();
133 |  |
             }
134 | 6 |
         }
135 |  |
136 |  |
         public void givenStories(GivenStories givenStories) {
137 | 0 |
             add("givenStories");
138 | 0 |
         }
139 |  |
140 |  |
         public void givenStories(List<String> storyPaths) {
141 | 2 |
             add("givenStories");
142 | 2 |
         }
143 |  |
144 |  |
         public void beforeScenario(String title) {
145 | 7 |
             cause = null;
146 | 7 |
             outcomesFailed = null;
147 | 7 |
             currentScenarioNotAllowed = false;
148 | 7 |
             reset("currentScenarioSteps");
149 | 7 |
             reset("currentScenarioStepsPending");
150 | 7 |
         }
151 |  |
152 |  |
         public void scenarioNotAllowed(Scenario scenario, String filter) {
153 | 1 |
             if (givenStories > 0) {
154 | 0 |
                 add("givenStoryScenariosNotAllowed");
155 |  |
             } else {
156 | 1 |
                 add("scenariosNotAllowed");
157 | 1 |
                 currentScenarioNotAllowed = true;
158 |  |
             }
159 | 1 |
         }
160 |  |
161 |  |
         public void scenarioMeta(Meta meta) {
162 | 1 |
         }
163 |  |
164 |  |
         public void afterScenario() {
165 | 7 |
             if (givenStories > 0) {
166 | 3 |
                 countScenarios("givenStoryScenarios");
167 |  |
             } else {
168 | 4 |
                 countScenarios("scenarios");
169 |  |
             }
170 | 7 |
             if (has("currentScenarioStepsPending") || (!has("currentScenarioSteps") && !currentScenarioNotAllowed)) {
171 | 2 |
                 if (givenStories > 0) {
172 | 1 |
                     add("givenStoryScenariosPending");
173 |  |
                 } else {
174 | 1 |
                     add("scenariosPending");
175 |  |
                 }
176 |  |
             }
177 | 7 |
         }
178 |  |
179 |  |
         private void countScenarios(String namespace) {
180 | 7 |
             add(namespace);
181 | 7 |
             if (!currentScenarioNotAllowed){
182 | 6 |
                     if (cause != null || outcomesFailed != null) {
183 | 1 |
                         add(namespace + "Failed");
184 |  |
                     } else {
185 | 5 |
                         add(namespace + "Successful");
186 |  |
                     }
187 |  |
             }
188 | 7 |
         }
189 |  |
190 |  |
         public void beforeExamples(List<String> steps, ExamplesTable table) {
191 | 1 |
         }
192 |  |
193 |  |
         public void example(Map<String, String> tableRow) {
194 | 2 |
             add("examples");
195 | 2 |
         }
196 |  |
197 |  |
         public void afterExamples() {
198 | 1 |
         }
199 |  |
200 |  |
         public void dryRun() {
201 | 1 |
         }
202 |  |
203 |  |
         public void pendingMethods(List<String> methods) {
204 | 0 |
         }
205 |  |
206 |  |
         public void restarted(String step, Throwable cause) {
207 | 0 |
         }
208 |  |
209 |  |
         private void add(String event) {
210 | 59 |
             Integer count = data.get(event);
211 | 59 |
             if (count == null) {
212 | 6 |
                 count = 0;
213 |  |
             }
214 | 59 |
             count++;
215 | 59 |
             data.put(event, count);
216 | 59 |
         }
217 |  |
218 |  |
         private boolean has(String event) {
219 | 21 |
             Integer count = data.get(event);
220 | 21 |
             if (count == null) {
221 | 0 |
                 count = 0;
222 |  |
             }
223 | 21 |
             return count > 0;
224 |  |
         }
225 |  |
226 |  |
         private void writeData() {
227 | 4 |
             Properties p = new Properties();
228 | 4 |
             for (String event : data.keySet()) {
229 | 91 |
                 if (!event.startsWith("current")) {
230 | 83 |
                     p.setProperty(event, data.get(event).toString());
231 |  |
                 }
232 |  |
             }
233 |  |
             try {
234 | 4 |
                 p.store(output, this.getClass().getName());
235 | 4 |
                 output.close();
236 | 0 |
             } catch (IOException e) {
237 | 0 |
                 e.printStackTrace();
238 | 4 |
             }
239 | 4 |
         }
240 |  |
241 |  |
         private void resetData() {
242 | 4 |
             data.clear();
243 | 4 |
             for (String event : events) {
244 | 88 |
                 reset(event);
245 |  |
             }
246 | 4 |
         }
247 |  |
248 |  |
         private void reset(String event) {
249 | 102 |
             data.put(event, 0);
250 | 102 |
         }
251 |  |
252 |  |
         @Override
253 |  |
         public String toString() {
254 | 1 |
             return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append(output).append(data).toString();
255 |  |
         }
256 |  |
257 |  |
258 |  |
     }