62f3f6f38918941cc005aa2ece45ad5773d924e6
1 package be
.nikiroo
.utils
.test
;
3 import java
.io
.PrintWriter
;
4 import java
.io
.StringWriter
;
5 import java
.util
.ArrayList
;
9 * A {@link TestLauncher} starts a series of {@link TestCase}s and displays the
14 public class TestLauncher
{
16 * {@link Exception} happening during the setup process.
20 private class SetupException
extends Exception
{
21 private static final long serialVersionUID
= 1L;
23 public SetupException(Throwable e
) {
29 * {@link Exception} happening during the tear-down process.
33 private class TearDownException
extends Exception
{
34 private static final long serialVersionUID
= 1L;
36 public TearDownException(Throwable e
) {
41 private List
<TestLauncher
> series
;
42 private List
<TestCase
> tests
;
44 private String okString
;
45 private String koString
;
49 protected int executed
;
52 private int currentSeries
= 0;
55 * Create a new {@link TestLauncher} with default parameters.
60 * the arguments to configure the number of columns and the ok/ko
63 public TestLauncher(String name
, String
[] args
) {
67 if (args
!= null && args
.length
>= 1) {
69 cols
= Integer
.parseInt(args
[0]);
70 } catch (NumberFormatException e
) {
71 System
.err
.println("Test configuration: given number "
72 + "of columns is not parseable: " + args
[0]);
78 String okString
= "[ ok ]";
79 String koString
= "[ !! ]";
80 if (args
!= null && args
.length
>= 3) {
85 setOkString(okString
);
86 setKoString(koString
);
88 series
= new ArrayList
<TestLauncher
>();
89 tests
= new ArrayList
<TestCase
>();
94 * Called before actually starting the tests themselves.
99 protected void start() throws Exception
{
103 * Called when the tests are passed (or failed to do so).
108 protected void stop() throws Exception
{
111 protected void addTest(TestCase test
) {
115 protected void addSeries(TestLauncher series
) {
116 this.series
.add(series
);
120 * Launch the series of {@link TestCase}s and the {@link TestCase}s.
122 * @return the number of errors
124 public int launch() {
129 * Launch the series of {@link TestCase}s and the {@link TestCase}s.
132 * the level at which is the launcher (0 = main launcher)
134 * @return the number of errors
136 public int launch(int depth
) {
139 total
= tests
.size();
146 errors
+= launchTests(depth
);
147 if (tests
.size() > 0 && depth
== 0) {
148 System
.out
.println("");
152 for (TestLauncher serie
: series
) {
153 errors
+= serie
.launch(depth
+ 1);
154 executed
+= serie
.executed
;
155 total
+= serie
.total
;
158 } catch (Exception e
) {
159 print(depth
, "__start");
164 } catch (Exception e
) {
165 print(depth
, "__stop");
170 print(depth
, executed
, errors
, total
);
176 * Launch the {@link TestCase}s.
179 * the level at which is the launcher (0 = main launcher)
181 * @return the number of errors
183 protected int launchTests(int depth
) {
185 for (TestCase test
: tests
) {
186 print(depth
, test
.getName());
192 } catch (Throwable e
) {
193 throw new SetupException(e
);
198 } catch (Throwable e
) {
199 throw new TearDownException(e
);
201 } catch (Throwable e
) {
213 if (ex
!= null && !cont
) {
222 * Specify a custom number of columns to use for the display of messages.
225 * the number of columns
227 public void setColumns(int columns
) {
228 this.columns
= columns
;
232 * Continue to run the tests when an error is detected.
237 public void setContinueAfterFail(boolean cont
) {
242 * Set a custom "[ ok ]" {@link String} when a test passed.
245 * the {@link String} to display at the end of a success
247 public void setOkString(String okString
) {
248 this.okString
= okString
;
252 * Set a custom "[ !! ]" {@link String} when a test failed.
255 * the {@link String} to display at the end of a failure
257 public void setKoString(String koString
) {
258 this.koString
= koString
;
262 * Print the test suite header.
265 * the level at which is the launcher (0 = main launcher)
267 protected void print(int depth
) {
269 System
.out
.println("[ Test suite: " + name
+ " ]");
270 System
.out
.println("");
272 System
.out
.println(prefix(depth
, false) + name
+ ":");
277 * Print the name of the {@link TestCase} we will start immediately after.
280 * the level at which is the launcher (0 = main launcher)
282 * the {@link TestCase} name
284 protected void print(int depth
, String name
) {
285 name
= prefix(depth
, false)
286 + (name
== null ?
"" : name
).replace("\t", " ");
288 while (name
.length() < columns
- 11) {
292 System
.out
.print(name
);
296 * Print the result of the {@link TestCase} we just ran.
299 * the level at which is the launcher (0 = main launcher)
301 * the {@link Exception} it ran into if any
303 private void print(int depth
, Throwable error
) {
305 System
.out
.println(" " + koString
);
306 StringWriter sw
= new StringWriter();
307 PrintWriter pw
= new PrintWriter(sw
);
308 error
.printStackTrace(pw
);
309 String lines
= sw
.toString();
310 for (String line
: lines
.split("\n")) {
311 System
.out
.println(prefix(depth
, false) + "\t\t" + line
);
314 System
.out
.println(" " + okString
);
319 * Print the total result for this test suite.
322 * the level at which is the launcher (0 = main launcher)
324 * the number of tests actually ran
326 * the number of errors encountered
328 * the total number of tests in the suite
330 private void print(int depth
, int executed
, int errors
, int total
) {
331 int ok
= executed
- errors
;
332 int pc
= (int) ((100.0 * ok
) / executed
);
333 if (pc
== 0 && ok
> 0) {
336 int pcTotal
= (int) ((100.0 * ok
) / total
);
337 if (pcTotal
== 0 && ok
> 0) {
341 String resume
= "Tests passed: " + ok
+ "/" + executed
+ " (" + pc
342 + "%) on a total of " + total
+ " (" + pcTotal
+ "% total)";
344 System
.out
.println(resume
);
346 String arrow
= "┗▶ ";
347 System
.out
.println(prefix(depth
, currentSeries
== 0) + arrow
349 System
.out
.println(prefix(depth
, currentSeries
== 0));
353 private int last
= -1;
356 * Return the prefix to print before the current line.
361 * this line is the first of its tabulation level
365 private String
prefix(int depth
, boolean first
) {
366 String space
= tabs(depth
- 1);
371 if (depth
!= last
&& first
) {
372 line
= "╻"; // first line
374 line
= "┃"; // continuation
378 space
+= line
+ tabs(1);
386 * Return the given number of space-converted tabs in a {@link String}.
389 * the number of tabs to return
393 private String
tabs(int depth
) {
394 StringBuilder builder
= new StringBuilder();
395 for (int i
= 0; i
< depth
; i
++) {
398 return builder
.toString();