forked from scalatest/scalatest
/
Suite.scala
2211 lines (2058 loc) · 95.1 KB
/
Suite.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright 2001-2013 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalatest
import org.scalactic.{ exceptions => _, Resources => _, _ }
import org.scalatest.events._
import Requirements._
import exceptions._
import java.lang.annotation.AnnotationFormatError
import java.lang.reflect.{Method, Modifier}
import java.nio.charset.CoderMalfunctionError
import javax.xml.parsers.FactoryConfigurationError
import javax.xml.transform.TransformerFactoryConfigurationError
import org.scalactic.Prettifier
import org.scalatest.time.{Seconds, Span}
import scala.collection.immutable.TreeSet
import scala.util.control.NonFatal
import StackDepthExceptionHelper.getStackDepthFun
import Suite.checkChosenStyles
import Suite.formatterForSuiteAborted
import Suite.formatterForSuiteCompleted
import Suite.formatterForSuiteStarting
import Suite.getEscapedIndentedTextForTest
import Suite.getSimpleNameOfAnObjectsClass
import Suite.getTopOfMethod
import Suite.isTestMethodGoodies
import Suite.reportTestIgnored
import Suite.takesInformer
import Suite.wrapReporterIfNecessary
import annotation.tailrec
import collection.GenTraversable
import collection.mutable.ListBuffer
// SKIP-SCALATESTJS-START
import Suite.getTopOfClass
import org.scalatest.tools.StandardOutReporter
import tools.SuiteDiscoveryHelper
// SKIP-SCALATESTJS-END
/*
* <h2>Using <code>info</code> and <code>markup</code></h2>
*
* <p>
* One of the parameters to <code>Suite</code>'s <code>run</code> method is a <code>Reporter</code>, which
* will collect and report information about the running suite of tests.
* Information about suites and tests that were run, whether tests succeeded or failed,
* and tests that were ignored will be passed to the <code>Reporter</code> as the suite runs.
* Most often the reporting done by default will be sufficient, but
* occasionally you may wish to provide custom information to the <code>Reporter</code> from a test.
* For this purpose, an <a href="Informer.html"><code>Informer</code></a> that will forward information
* to the current <code>Reporter</code> is provided via the <code>info</code> parameterless method.
* You can pass the extra information to the <code>Informer</code> via its <code>apply</code> method.
* The <code>Informer</code> will then pass the information to the <code>Reporter</code> via an <code>InfoProvided</code> event.
* Here's an example that shows both a direct use as well as an indirect use through the methods
* of <a href="GivenWhenThen.html"><code>GivenWhenThen</code></a>:
* </p>
*
* <pre class="stHighlight">
* package org.scalatest.examples.suite.info
*
* import collection.mutable
* import org.scalatest._
*
* class SetSuite extends Suite with GivenWhenThen {
*
* def `test: an element can be added to an empty mutable Set` {
*
* given("an empty mutable Set")
* val set = mutable.Set.empty[String]
*
* when("an element is added")
* set += "clarity"
*
* then("the Set should have size 1")
* assert(set.size === 1)
*
* and("the Set should contain the added element")
* assert(set.contains("clarity"))
*
* info("That's all folks!")
* }
* }
* </pre>
*
* If you run this <code>Suite</code> from the interpreter, you will see the messages
* included in the output:
*
* <pre class="stREPL">
* scala> org.scalatest.run(new SetSuite)
* <span class="stGreen">SetSuite:
* - an element can be added to an empty mutable Set
* + Given an empty mutable Set
* + When an element is added
* + Then the Set should have size 1
* + And the Set should contain the added element
* + That's all folks!</span>
* </pre>
*
* <p>
* Trait <code>Suite</code> also carries a <a href="Documenter.html"><code>Documenter</code></a> named <code>markup</code>, which
* you can use to transmit markup text to the <code>Reporter</code>.
* </p>
* --------------
* <h2>Assertions and <code>=</code><code>=</code><code>=</code></h2>
*
* <p>
* Inside test methods in a <code>Suite</code>, you can write assertions by invoking <code>assert</code> and passing in a <code>Boolean</code> expression,
* such as:
* </p>
*
* <pre class="stHighlight">
* val left = 2
* val right = 1
* assert(left == right)
* </pre>
*
* <p>
* If the passed expression is <code>true</code>, <code>assert</code> will return normally. If <code>false</code>,
* <code>assert</code> will complete abruptly with a <code>TestFailedException</code>. This exception is usually not caught
* by the test method, which means the test method itself will complete abruptly by throwing the <code>TestFailedException</code>. Any
* test method that completes abruptly with an exception is considered a failed
* test. A test method that returns normally is considered a successful test.
* </p>
*
* <p>
* If you pass a <code>Boolean</code> expression to <code>assert</code>, a failed assertion will be reported, but without
* reporting the left and right values. You can alternatively encode these values in a <code>String</code> passed as
* a second argument to <code>assert</code>, as in:
* </p>
*
* <pre class="stHighlight">
* val left = 2
* val right = 1
* assert(left == right, left + " did not equal " + right)
* </pre>
*
* <p>
* Using this form of <code>assert</code>, the failure report will include the left and right values,
* helping you debug the problem. However, ScalaTest provides the <code>===</code> operator to make this easier.
* (The <code>===</code> operator is defined in trait <a href="Assertions.html"><code>Assertions</code></a> which trait <code>Suite</code> extends.)
* You use it like this:
* </p>
*
* <pre class="stHighlight">
* val left = 2
* val right = 1
* assert(left === right)
* </pre>
*
* <p>
* Because you use <code>===</code> here instead of <code>==</code>, the failure report will include the left
* and right values. For example, the detail message in the thrown <code>TestFailedException</code> from the <code>assert</code>
* shown previously will include, "2 did not equal 1".
* From this message you will know that the operand on the left had the value 2, and the operand on the right had the value 1.
* </p>
*
* <p>
* If you're familiar with JUnit, you would use <code>===</code>
* in a ScalaTest <code>Suite</code> where you'd use <code>assertEquals</code> in a JUnit <code>TestCase</code>.
* The <code>===</code> operator is made possible by an implicit conversion from <code>Any</code>
* to <code>Equalizer</code>. If you're curious to understand the mechanics, see the <a href="Assertions$Equalizer.html">documentation for
* <code>Equalizer</code></a> and the <code>convertToEqualizer</code> method.
* </p>
*
* <h2>Expected results</h2>
*
* Although <code>===</code> provides a natural, readable extension to Scala's <code>assert</code> mechanism,
* as the operands become lengthy, the code becomes less readable. In addition, the <code>===</code> comparison
* doesn't distinguish between actual and expected values. The operands are just called <code>left</code> and <code>right</code>,
* because if one were named <code>expected</code> and the other <code>actual</code>, it would be difficult for people to
* remember which was which. To help with these limitations of assertions, <code>Suite</code> includes a method called <code>assertResult</code> that
* can be used as an alternative to <code>assert</code> with <code>===</code>. To use <code>assertResult</code>, you place
* the expected value in parentheses after <code>assertResult</code>, followed by curly braces containing code
* that should result in the expected value. For example:
*
* <pre class="stHighlight">
* val a = 5
* val b = 2
* assertResult(2) {
* a - b
* }
* </pre>
*
* <p>
* In this case, the expected value is <code>2</code>, and the code being tested is <code>a - b</code>. This expectation will fail, and
* the detail message in the <code>TestFailedException</code> will read, "Expected 2, but got 3."
* </p>
*
* <h2>Intercepted exceptions</h2>
*
* <p>
* Sometimes you need to test whether a method throws an expected exception under certain circumstances, such
* as when invalid arguments are passed to the method. You can do this in the JUnit style, like this:
* </p>
*
* <pre class="stHighlight">
* val s = "hi"
* try {
* s.charAt(-1)
* fail()
* }
* catch {
* case _: IndexOutOfBoundsException => // Expected, so continue
* }
* </pre>
*
* <p>
* If <code>charAt</code> throws <code>IndexOutOfBoundsException</code> as expected, control will transfer
* to the catch case, which does nothing. If, however, <code>charAt</code> fails to throw an exception,
* the next statement, <code>fail()</code>, will be executed. The <code>fail</code> method always completes abruptly with
* a <code>TestFailedException</code>, thereby signaling a failed test.
* </p>
*
* <p>
* To make this common use case easier to express and read, ScalaTest provides an <code>intercept</code>
* method. You use it like this:
* </p>
*
* <pre class="stHighlight">
* val s = "hi"
* intercept[IndexOutOfBoundsException] {
* s.charAt(-1)
* }
* </pre>
*
* <p>
* This code behaves much like the previous example. If <code>charAt</code> throws an instance of <code>IndexOutOfBoundsException</code>,
* <code>intercept</code> will return that exception. But if <code>charAt</code> completes normally, or throws a different
* exception, <code>intercept</code> will complete abruptly with a <code>TestFailedException</code>. The <code>intercept</code> method returns the
* caught exception so that you can inspect it further if you wish, for example, to ensure that data contained inside
* the exception has the expected values. Here's an example:
* </p>
*
* <pre class="stHighlight">
* val s = "hi"
* val caught =
* intercept[IndexOutOfBoundsException] {
* s.charAt(-1)
* }
* assert(caught.getMessage === "String index out of range: -1")
* </pre>
*
* <h2>Using matchers and other assertions</h2>
*
* <p>
* ScalaTest also supports another style of assertions via its matchers DSL. By mixing in
* trait <a href="matchers/Matchers.html"><code>Matchers</code></a>, you can
* write suites that look like:
* </p>
*
* <pre class="stHighlight">
* package org.scalatest.examples.suite.matchers
*
* import org.scalatest._
*
* class SetSuite extends Suite with Matchers {
*
* def `test: an empty Set should have size 0` {
* Set.empty.size should equal (0)
* }
*
* def `test: invoking head on an empty Set should produce NoSuchElementException` {
* a [NoSuchElementException] should be thrownBy { Set.empty.head }
* }
* }
* </pre>
*
* <p>If you prefer the word "<code>must</code>" to the word "<code>should</code>," you can alternatively mix in
* trait <a href="matchers/MustMatchers.html"><code>MustMatchers</code></a>.
* </p>
*
* <p>
* If you are comfortable with assertion mechanisms from other test frameworks, chances
* are you can use them with ScalaTest. Any assertion mechanism that indicates a failure with an exception
* can be used as is with ScalaTest. For example, to use the <code>assertEquals</code>
* methods provided by JUnit or TestNG, simply import them and use them. (You will of course need
* to include the relevant JAR file for the framework whose assertions you want to use on either the
* classpath or runpath when you run your tests.)
* </p>
*/
/**
* A suite of tests. A <code>Suite</code> instance encapsulates a conceptual
* suite (<em>i.e.</em>, a collection) of tests.
*
* <p>
* This trait provides an interface composed of "lifecycle methods" that allow suites of tests to be run.
* Its implementation enables a default way of writing and executing tests. Subtraits and subclasses can
* override <code>Suite</code>'s lifecycle methods to enable other ways of writing and executing tests.
* </p>
*
* <h2>Nested suites</h2>
*
* <p>
* A <code>Suite</code> can refer to a collection of other <code>Suite</code>s,
* which are called <em>nested</em> <code>Suite</code>s. Those nested <code>Suite</code>s can in turn have
* their own nested <code>Suite</code>s, and so on. Large test suites can be organized, therefore, as a tree of
* nested <code>Suite</code>s.
* This trait's <code>run</code> method, in addition to invoking its
* test methods, invokes <code>run</code> on each of its nested <code>Suite</code>s.
* </p>
*
* <p>
* A <code>List</code> of a <code>Suite</code>'s nested <code>Suite</code>s can be obtained by invoking its
* <code>nestedSuites</code> method. If you wish to create a <code>Suite</code> that serves as a
* container for nested <code>Suite</code>s, whether or not it has test methods of its own, simply override <code>nestedSuites</code>
* to return a <code>List</code> of the nested <code>Suite</code>s. Because this is a common use case, ScalaTest provides
* a convenience <code>Suites</code> class, which takes a variable number of nested <code>Suite</code>s as constructor
* parameters. Here's an example:
* </p>
*
* <pre class="stHighlight">
* package org.scalatest.examples.suite.nested
*
* import org.scalatest._
*
* class ASuite extends FunSuite {
* test("A should have ASCII value 41 hex") {
* assert('A' === 0x41)
* }
* test("a should have ASCII value 61 hex") {
* assert('a' === 0x61)
* }
* }
* class BSuite extends FunSuite {
* test("B should have ASCII value 42 hex") {
* assert('B' === 0x42)
* }
* test("b should have ASCII value 62 hex") {
* assert('b' === 0x62)
* }
* }
* class CSuite extends FunSuite {
* test("C should have ASCII value 43 hex") {
* assert('C' === 0x43)
* }
* test("c should have ASCII value 63 hex") {
* assert('c' === 0x63)
* }
* }
*
* class ASCIISuite extends Suites(
* new ASuite,
* new BSuite,
* new CSuite
* )
* </pre>
*
* <p>
* If you now run <code>ASCIISuite</code>:
* </p>
*
* <pre class="stREPL">
* scala> org.scalatest.run(new ASCIISuite)
* </pre>
*
* <p>
* You will see reports printed to the standard output that indicate the nested
* suites—<code>ASuite</code>, <code>BSuite</code>, and
* <code>CSuite</code>—were run:
* </p>
*
* <pre class="stREPL">
* <span class="stGreen">ASCIISuite:
* ASuite:
* - A should have ASCII value 41 hex
* - a should have ASCII value 61 hex
* BSuite:
* - B should have ASCII value 42 hex
* - b should have ASCII value 62 hex
* CSuite:
* - C should have ASCII value 43 hex
* - c should have ASCII value 63 hex</span>
* </pre>
*
* <p>
* Note that <code>Runner</code> can discover <code>Suite</code>s automatically, so you need not
* necessarily define nested <code>Suites</code> explicitly. See the <a href="tools/Runner$.html#membersOnlyWildcard">documentation
* for <code>Runner</code></a> for more information.
* </p>
*
* <a name="configMapSection"></a><h2>The config map</h2>
*
* <p>
* In some cases you may need to pass information to a suite of tests.
* For example, perhaps a suite of tests needs to grab information from a file, and you want
* to be able to specify a different filename during different runs. You can accomplish this in ScalaTest by passing
* the filename in a <em>config map</em> of key-value pairs, which is passed to <code>run</code> as a <a href="ConfigMap.html"><code>ConfigMap</code></a>.
* The values in the config map are called "config objects," because they can be used to <em>configure</em>
* suites, reporters, and tests.
* </p>
*
* <p>
* You can specify a string config object is via the ScalaTest <code>Runner</code>, either via the command line
* or ScalaTest's ant task.
* (See the <a href="tools/Runner$.html#configMapSection">documentation for Runner</a> for information on how to specify
* config objects on the command line.)
* The config map is passed to <code>run</code>, <code>runNestedSuites</code>, <code>runTests</code>, and <code>runTest</code>,
* so one way to access it in your suite is to override one of those methods. If you need to use the config map inside your tests, you
* can access it from the <code>NoArgTest</code> passed to <code>withFixture</code>, or the <code>OneArgTest</code> passed to
* <code>withFixture</code> in the traits in the <code>org.scalatest.fixture</code> package. (See the
* <a href="fixture/Suite.html">documentation for <code>fixture.Suite</code></a>
* for instructions on how to access the config map in tests.)
* </p>
*
* <h2>Executing suites in parallel</h2>
*
* <p>
* The <code>run</code> method takes as one of its parameters an optional <a href="Distributor.html"><code>Distributor</code></a>. If
* a <code>Distributor</code> is passed in, this trait's implementation of <code>run</code> puts its nested
* <code>Suite</code>s into the distributor rather than executing them directly. The caller of <code>run</code>
* is responsible for ensuring that some entity runs the <code>Suite</code>s placed into the
* distributor. The <code>-P</code> command line parameter to <code>Runner</code>, for example, will cause
* <code>Suite</code>s put into the <code>Distributor</code> to be run in parallel via a pool of threads.
* If you wish to execute the tests themselves in parallel, mix in <a href="ParallelTestExecution.html"><code>ParallelTestExecution</code></a>.
* </p>
*
* <a name="errorHandling"></a>
* <h2>"Run-aborting" exceptions</h2>
*
* <p>
* The Javadoc documentation for <code>java.lang.Error</code> states:
* </p>
*
* <blockquote>
* An <code>Error</code> is a subclass of <code>Throwable</code> that indicates serious problems that a reasonable application
* should not try to catch. Most
* such errors are abnormal conditions.
* </blockquote>
*
* <p>
* Because <code>Error</code>s are used to denote serious errors, trait <code>Suite</code> and its subtypes in the ScalaTest API
* do not always treat a test that completes abruptly with an <code>Error</code> as a test failure, but sometimes as an indication
* that serious problems have arisen that should cause the run to abort. For example, if a test completes abruptly with an
* <code>OutOfMemoryError</code>, it will not be reported as a test failure, but will instead cause the run to abort. Because not
* everyone uses <code>Error</code>s only to represent serious
* problems, however, ScalaTest only behaves this way for the following <em>run-aborting</em> exception types (and their subclasses):
* </p>
*
* <ul>
* <li><code>java.lang.annotation.AnnotationFormatError</code></li>
* <li><code>java.awt.AWTError</code></li>
* <li><code>java.nio.charset.CoderMalfunctionError</code></li>
* <li><code>javax.xml.parsers.FactoryConfigurationError</code></li>
* <li><code>java.lang.LinkageError</code></li>
* <li><code>java.lang.ThreadDeath</code></li>
* <li><code>javax.xml.transform.TransformerFactoryConfigurationError</code></li>
* <li><code>java.lang.VirtualMachineError</code></li>
* </ul>
*
* <p>
* The previous list includes all <code>Error</code>s that exist as part of Java 1.5 API, excluding <code>java.lang.AssertionError</code>.
* ScalaTest does treat a thrown <code>AssertionError</code> as an indication of a test failure. In addition, any other
* <code>Error</code> that is not an instance of a type mentioned in the previous list will be caught by the <code>Suite</code> traits
* in the ScalaTest API and reported as the cause of a test failure.
* </p>
*
* <p>
* Although trait <code>Suite</code> and all its subtypes in the ScalaTest API consistently behave this way with regard to <code>Error</code>s,
* this behavior is not required by the contract of <code>Suite</code>. Subclasses and subtraits that you define, for example, may treat all
* <code>Error</code>s as test failures, or indicate errors in some other way that has nothing to do with exceptions.
* </p>
*
* <a name="lifecyle-methods"></a>
* <h2>Extensibility</h2>
*
* <p>
* Trait <code>Suite</code> provides default implementations of its methods that should
* be sufficient for most applications, but many methods can be overridden when desired. Here's
* a summary of the methods that are intended to be overridden:
* </p>
*
* <ul>
* <li><code>run</code> - override this method to define custom ways to run suites of
* tests.</li>
* <li><code>runNestedSuites</code> - override this method to define custom ways to run nested suites.</li>
* <li><code>runTests</code> - override this method to define custom ways to run a suite's tests.</li>
* <li><code>runTest</code> - override this method to define custom ways to run a single named test.</li>
* <li><code>testNames</code> - override this method to specify the <code>Suite</code>'s test names in a custom way.</li>
* <li><code>tags</code> - override this method to specify the <code>Suite</code>'s test tags in a custom way.</li>
* <li><code>nestedSuites</code> - override this method to specify the <code>Suite</code>'s nested <code>Suite</code>s in a custom way.</li>
* <li><code>suiteName</code> - override this method to specify the <code>Suite</code>'s name in a custom way.</li>
* <li><code>expectedTestCount</code> - override this method to count this <code>Suite</code>'s expected tests in a custom way.</li>
* </ul>
*
* <p>
* For example, this trait's implementation of <code>testNames</code> performs reflection to discover methods starting with <code>test</code>,
* and places these in a <code>Set</code> whose iterator returns the names in alphabetical order. If you wish to run tests in a different
* order in a particular <code>Suite</code>, perhaps because a test named <code>testAlpha</code> can only succeed after a test named
* <code>testBeta</code> has run, you can override <code>testNames</code> so that it returns a <code>Set</code> whose iterator returns
* <code>testBeta</code> <em>before</em> <code>testAlpha</code>. (This trait's implementation of <code>run</code> will invoke tests
* in the order they come out of the <code>testNames</code> <code>Set</code> iterator.)
* </p>
*
* <p>
* Alternatively, you may not like starting your test methods with <code>test</code>, and prefer using <code>@Test</code> annotations in
* the style of Java's JUnit 4 or TestNG. If so, you can override <code>testNames</code> to discover tests using either of these two APIs
* <code>@Test</code> annotations, or one of your own invention. (This is in fact
* how <code>org.scalatest.junit.JUnitSuite</code> and <code>org.scalatest.testng.TestNGSuite</code> work.)
* </p>
*
* <p>
* Moreover, <em>test</em> in ScalaTest does not necessarily mean <em>test method</em>. A test can be anything that can be given a name,
* that starts and either succeeds or fails, and can be ignored. In <code>org.scalatest.FunSuite</code>, for example, tests are represented
* as function values. This
* approach might look foreign to JUnit users, but may feel more natural to programmers with a functional programming background.
* To facilitate this style of writing tests, <code>FunSuite</code> overrides <code>testNames</code>, <code>runTest</code>, and <code>run</code> such that you can
* define tests as function values.
* </p>
*
* <p>
* You can also model existing JUnit 3, JUnit 4, or TestNG tests as suites of tests, thereby incorporating tests written in Java into a ScalaTest suite.
* The "wrapper" classes in packages <code>org.scalatest.junit</code> and <code>org.scalatest.testng</code> exist to make this easy.
* No matter what legacy tests you may have, it is likely you can create or use an existing <code>Suite</code> subclass that allows you to model those tests
* as ScalaTest suites and tests and incorporate them into a ScalaTest suite. You can then write new tests in Scala and continue supporting
* older tests in Java.
* </p>
*
* @author Bill Venners
*/
trait Suite extends Assertions with Serializable { thisSuite =>
import Suite.InformerInParens
/**
* An immutable <code>IndexedSeq</code> of this <code>Suite</code> object's nested <code>Suite</code>s. If this <code>Suite</code> contains no nested <code>Suite</code>s,
* this method returns an empty <code>IndexedSeq</code>. This trait's implementation of this method returns an empty <code>List</code>.
*/
def nestedSuites: collection.immutable.IndexedSeq[Suite] = Vector.empty
// SKIP-SCALATESTJS-START
/**
* Executes one or more tests in this <code>Suite</code>, printing results to the standard output.
*
* <p>
* This method invokes <code>run</code> on itself, passing in values that can be configured via the parameters to this
* method, all of which have default values. This behavior is convenient when working with ScalaTest in the Scala interpreter.
* Here's a summary of this method's parameters and how you can use them:
* </p>
*
* <p>
* <strong>The <code>testName</code> parameter</strong>
* </p>
*
* <p>
* If you leave <code>testName</code> at its default value (of <code>null</code>), this method will pass <code>None</code> to
* the <code>testName</code> parameter of <code>run</code>, and as a result all the tests in this suite will be executed. If you
* specify a <code>testName</code>, this method will pass <code>Some(testName)</code> to <code>run</code>, and only that test
* will be run. Thus to run all tests in a suite from the Scala interpreter, you can write:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute()
* </pre>
*
* <p>
* (The above syntax actually invokes the overloaded parameterless form of <code>execute</code>, which calls this form with its default parameter values.)
* To run just the test named <code>"my favorite test"</code> in a suite from the Scala interpreter, you would write:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute("my favorite test")
* </pre>
*
* <p>
* Or:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(testName = "my favorite test")
* </pre>
*
* <p>
* <strong>The <code>configMap</code> parameter</strong>
* </p>
*
* <p>
* If you provide a value for the <code>configMap</code> parameter, this method will pass it to <code>run</code>. If not, the default value
* of an empty <code>Map</code> will be passed. For more information on how to use a config map to configure your test suites, see
* the <a href="#configMapSection">config map section</a> in the main documentation for this trait. Here's an example in which you configure
* a run with the name of an input file:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(configMap = Map("inputFileName" -> "in.txt")
* </pre>
*
* <p>
* <strong>The <code>color</code> parameter</strong>
* </p>
*
* <p>
* If you leave the <code>color</code> parameter unspecified, this method will configure the reporter it passes to <code>run</code> to print
* to the standard output in color (via ansi escape characters). If you don't want color output, specify false for <code>color</code>, like this:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(color = false)
* </pre>
*
* <p>
* <strong>The <code>durations</code> parameter</strong>
* </p>
*
* <p>
* If you leave the <code>durations</code> parameter unspecified, this method will configure the reporter it passes to <code>run</code> to
* <em>not</em> print durations for tests and suites to the standard output. If you want durations printed, specify true for <code>durations</code>,
* like this:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(durations = true)
* </pre>
*
* <p>
* <strong>The <code>shortstacks</code> and <code>fullstacks</code> parameters</strong>
* </p>
*
* <p>
* If you leave both the <code>shortstacks</code> and <code>fullstacks</code> parameters unspecified, this method will configure the reporter
* it passes to <code>run</code> to <em>not</em> print stack traces for failed tests if it has a stack depth that identifies the offending
* line of test code. If you prefer a short stack trace (10 to 15 stack frames) to be printed with any test failure, specify true for
* <code>shortstacks</code>:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(shortstacks = true)
* </pre>
*
* <p>
* For full stack traces, set <code>fullstacks</code> to true:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(fullstacks = true)
* </pre>
*
* <p>
* If you specify true for both <code>shortstacks</code> and <code>fullstacks</code>, you'll get full stack traces.
* </p>
*
* <p>
* <strong>The <code>stats</code> parameter</strong>
* </p>
*
* <p>
* If you leave the <code>stats</code> parameter unspecified, this method will <em>not</em> fire <code>RunStarting</code> and either <code>RunCompleted</code>
* or <code>RunAborted</code> events to the reporter it passes to <code>run</code>.
* If you specify true for <code>stats</code>, this method will fire the run events to the reporter, and the reporter will print the
* expected test count before the run, and various statistics after, including the number of suites completed and number of tests that
* succeeded, failed, were ignored or marked pending. Here's how you get the stats:
* </p>
*
* <pre class="stREPL">
* scala> (new ExampleSuite).execute(stats = true)
* </pre>
*
*
* <p>
* To summarize, this method will pass to <code>run</code>:
* </p>
* <ul>
* <li><code>testName</code> - <code>None</code> if this method's <code>testName</code> parameter is left at its default value of <code>null</code>, else <code>Some(testName)</code>.
* <li><code>reporter</code> - a reporter that prints to the standard output</li>
* <li><code>stopper</code> - a <code>Stopper</code> whose <code>apply</code> method always returns <code>false</code></li>
* <li><code>filter</code> - a <code>Filter</code> constructed with <code>None</code> for <code>tagsToInclude</code> and <code>Set()</code>
* for <code>tagsToExclude</code></li>
* <li><code>configMap</code> - the <code>configMap</code> passed to this method</li>
* <li><code>distributor</code> - <code>None</code></li>
* <li><code>tracker</code> - a new <code>Tracker</code></li>
* </ul>
*
* <p>
* Note: In ScalaTest, the terms "execute" and "run" basically mean the same thing and
* can be used interchangably. The reason this method isn't named <code>run</code> is that it takes advantage of
* default arguments, and you can't mix overloaded methods and default arguments in Scala. (If named <code>run</code>,
* this method would have the same name but different arguments than the main <a href="#run"><code>run</code> method</a> that
* takes seven arguments. Thus it would overload and couldn't be used with default argument values.)
* </p>
*
* <p>
* Design note: This method has two "features" that may seem unidiomatic. First, the default value of <code>testName</code> is <code>null</code>.
* Normally in Scala the type of <code>testName</code> would be <code>Option[String]</code> and the default value would
* be <code>None</code>, as it is in this trait's <code>run</code> method. The <code>null</code> value is used here for two reasons. First, in
* ScalaTest 1.5, <code>execute</code> was changed from four overloaded methods to one method with default values, taking advantage of
* the default and named parameters feature introduced in Scala 2.8.
* To not break existing source code, <code>testName</code> needed to have type <code>String</code>, as it did in two of the overloaded
* <code>execute</code> methods prior to 1.5. The other reason is that <code>execute</code> has always been designed to be called primarily
* from an interpeter environment, such as the Scala REPL (Read-Evaluate-Print-Loop). In an interpreter environment, minimizing keystrokes is king.
* A <code>String</code> type with a <code>null</code> default value lets users type <code>suite.execute("my test name")</code> rather than
* <code>suite.execute(Some("my test name"))</code>, saving several keystrokes.
* </p>
*
* <p>
* The second non-idiomatic feature is that <code>shortstacks</code> and <code>fullstacks</code> are all lower case rather than
* camel case. This is done to be consistent with the <a href="Shell.html"><code>Shell</code></a>, which also uses those forms. The reason
* lower case is used in the <code>Shell</code> is to save keystrokes in an interpreter environment. Most Unix commands, for
* example, are all lower case, making them easier and quicker to type. In the ScalaTest
* <code>Shell</code>, methods like <code>shortstacks</code>, <code>fullstacks</code>, and <code>nostats</code>, <em>etc.</em>, are
* designed to be all lower case so they feel more like shell commands than methods.
* </p>
*
* @param testName the name of one test to run.
* @param configMap a <code>Map</code> of key-value pairs that can be used by the executing <code>Suite</code> of tests.
* @param color a boolean that configures whether output is printed in color
* @param durations a boolean that configures whether test and suite durations are printed to the standard output
* @param shortstacks a boolean that configures whether short stack traces should be printed for test failures
* @param fullstacks a boolean that configures whether full stack traces should be printed for test failures
* @param stats a boolean that configures whether test and suite statistics are printed to the standard output
*
* @throws NullArgumentException if the passed <code>configMap</code> parameter is <code>null</code>.
* @throws IllegalArgumentException if <code>testName</code> is defined, but no test with the specified test name
* exists in this <code>Suite</code>
*/
final def execute(
testName: String = null,
configMap: ConfigMap = ConfigMap.empty,
color: Boolean = true,
durations: Boolean = false,
shortstacks: Boolean = false,
fullstacks: Boolean = false,
stats: Boolean = false
): Unit = {
requireNonNull(configMap)
val SelectedTag = "Selected"
val SelectedSet = Set(SelectedTag)
val desiredTests: scala.collection.Set[String] =
if (testName == null) Set.empty
else {
testNames.filter { s =>
s.indexOf(testName) >= 0 || NameTransformer.decode(s).indexOf(testName) >= 0
}
}
if (testName != null && desiredTests.isEmpty)
throw new IllegalArgumentException(Resources.testNotFound(testName))
val dispatch = new DispatchReporter(List(new StandardOutReporter(durations, color, shortstacks, fullstacks, false, false, false, false, false, false)))
val tracker = new Tracker
val filter =
if (testName == null) Filter()
else {
val taggedTests: Map[String, Set[String]] = desiredTests.map(_ -> SelectedSet).toMap
Filter(
tagsToInclude = Some(SelectedSet),
excludeNestedSuites = true,
dynaTags = DynaTags(Map.empty, Map(suiteId -> taggedTests))
)
}
val runStartTime = System.currentTimeMillis
if (stats)
dispatch(RunStarting(tracker.nextOrdinal(), expectedTestCount(filter), configMap))
val suiteStartTime = System.currentTimeMillis
def dispatchSuiteAborted(e: Throwable): Unit = {
val eMessage = e.getMessage
val rawString =
if (eMessage != null && eMessage.length > 0)
Resources.runOnSuiteException
else
Resources.runOnSuiteExceptionWithMessage(eMessage)
val formatter = formatterForSuiteAborted(thisSuite, rawString)
val duration = System.currentTimeMillis - suiteStartTime
dispatch(SuiteAborted(tracker.nextOrdinal(), rawString, thisSuite.suiteName, thisSuite.suiteId, Some(thisSuite.getClass.getName), Some(e), Some(duration), formatter, Some(SeeStackDepthException)))
}
try {
val formatter = formatterForSuiteStarting(thisSuite)
dispatch(SuiteStarting(tracker.nextOrdinal(), thisSuite.suiteName, thisSuite.suiteId, Some(thisSuite.getClass.getName), formatter, Some(getTopOfClass(thisSuite))))
val status =
run(
None,
Args(dispatch,
Stopper.default,
filter,
configMap,
None,
tracker,
Set.empty)
)
status.waitUntilCompleted()
val suiteCompletedFormatter = formatterForSuiteCompleted(thisSuite)
val duration = System.currentTimeMillis - suiteStartTime
dispatch(SuiteCompleted(tracker.nextOrdinal(), thisSuite.suiteName, thisSuite.suiteId, Some(thisSuite.getClass.getName), Some(duration), suiteCompletedFormatter, Some(getTopOfClass(thisSuite))))
if (stats) {
val duration = System.currentTimeMillis - runStartTime
dispatch(RunCompleted(tracker.nextOrdinal(), Some(duration)))
}
}
catch {
case e: InstantiationException =>
dispatchSuiteAborted(e)
dispatch(RunAborted(tracker.nextOrdinal(), Resources.cannotInstantiateSuite(e.getMessage), Some(e), Some(System.currentTimeMillis - runStartTime)))
case e: IllegalAccessException =>
dispatchSuiteAborted(e)
dispatch(RunAborted(tracker.nextOrdinal(), Resources.cannotInstantiateSuite(e.getMessage), Some(e), Some(System.currentTimeMillis - runStartTime)))
case e: NoClassDefFoundError =>
dispatchSuiteAborted(e)
dispatch(RunAborted(tracker.nextOrdinal(), Resources.cannotLoadClass(e.getMessage), Some(e), Some(System.currentTimeMillis - runStartTime)))
case e: Throwable =>
dispatchSuiteAborted(e)
dispatch(RunAborted(tracker.nextOrdinal(), Resources.bigProblems(e), Some(e), Some(System.currentTimeMillis - runStartTime)))
if (!NonFatal(e))
throw e
}
finally {
dispatch.dispatchDisposeAndWaitUntilDone()
}
}
/**
* <strong>The parameterless <code>execute</code> method has been deprecated and will be removed in a future version
* of ScalaTest. Please invoke <code>execute</code> with empty parens instead: <code>execute()</code>.</strong>
*
* <p>
* The original purpose of this method, which simply invokes the other overloaded form of <code>execute</code> with default parameter values,
* was to serve as a mini-DSL for the Scala interpreter. It allowed you to execute a <code>Suite</code> in the
* interpreter with a minimum of finger typing:
* </p>
*
* <pre class="stREPL">
* scala> org.scalatest.run(new SetSpec)
* <span class="stGreen">An empty Set</span>
* <span class="stGreen">- should have size 0</span>
* <span class="stYellow">- should produce NoSuchElementException when head is invoked !!! IGNORED !!!</span>
* </pre>
*
* <p>
* However it uses postfix notation, which is now behind a language feature import. Thus better to use
* the other <code>execute</code> method or <code>org.scalatest.run</code>:
* </p>
*
* <pre class="stREPL">
* (new ExampleSuite).execute()
* // or
* org.scalatest.run(new ExampleSuite)
* </pre>
*/
@deprecated("The parameterless execute method has been deprecated and will be removed in a future version of ScalaTest. Please invoke execute with empty parens instead: execute().")
final def execute: Unit = { execute() }
// SKIP-SCALATESTJS-END
/**
* A <code>Map</code> whose keys are <code>String</code> names of tests that are tagged and
* whose associated values are the <code>Set</code> of tag names for the test. If a test has no associated tags, its name
* does not appear as a key in the returned <code>Map</code>. If this <code>Suite</code> contains no tests with tags, this
* method returns an empty <code>Map</code>.
*
* <p>
* This trait's implementation of this method uses Java reflection to discover any Java annotations attached to its test methods. The
* fully qualified name of each unique annotation that extends <code>TagAnnotation</code> is considered a tag. This trait's
* implementation of this method, therefore, places one key/value pair into to the
* <code>Map</code> for each test for which a tag annotation is discovered through reflection.
* </p>
*
* <p>
* In addition to test methods annotations, this trait's implementation will also auto-tag test methods with class level annotations.
* For example, if you annotate @Ignore at the class level, all test methods in the class will be auto-annotated with @Ignore.
* </p>
*
* <p>
* Subclasses may override this method to define and/or discover tags in a custom manner, but overriding method implementations
* should never return an empty <code>Set</code> as a value. If a test has no tags, its name should not appear as a key in the
* returned <code>Map</code>.
* </p>
*/
def tags: Map[String, Set[String]] = Map.empty
/**
* A <code>Set</code> of test names. If this <code>Suite</code> contains no tests, this method returns an empty <code>Set</code>.
*
* <p>
* This trait's implementation of this method returns an empty <code>Set</code>.
*/
def testNames: scala.collection.Set[String] = Set.empty
// SKIP-SCALATESTJS-START
// Leave this around for a while so can print out a warning if we find testXXX methods.
private[scalatest] def yeOldeTestNames: Set[String] = {
def isTestMethod(m: Method) = {
// Factored out to share code with fixture.Suite.testNames
val (isInstanceMethod, simpleName, firstFour, paramTypes, hasNoParams, isTestNames, isTestTags, isTestDataFor) = isTestMethodGoodies(m)
isInstanceMethod && (firstFour == "test") && !isTestDataFor && ((hasNoParams && !isTestNames && !isTestTags) || takesInformer(m))
}
val testNameArray =
for (m <- getClass.getMethods; if isTestMethod(m))
yield if (takesInformer(m)) m.getName + InformerInParens else m.getName
val result = TreeSet.empty[String](EncodedOrdering) ++ testNameArray
if (result.size != testNameArray.length) {
throw new NotAllowedException("Howdy", 0)
}
result
}
// SKIP-SCALATESTJS-END
/*
Old style method names will have (Informer) at the end still, but new ones will
not. This method will find the one without a Rep if the same name is used
with and without a Rep.
private[scalatest] def getMethodForTestName(theSuite: Suite, testName: String): Method =
try {
theSuite.getClass.getMethod(
simpleNameForTest(testName),
(if (testMethodTakesAnInformer(testName)) Array(classOf[Informer]) else new Array[Class[_]](0)): _*
)
}
catch {
case e: NoSuchMethodException =>
// Try (Rep) on the end
try {
theSuite.getClass.getMethod(simpleNameForTest(testName), classOf[Rep])
}
catch {
case e: NoSuchMethodException =>
throw new IllegalArgumentException(Resources.testNotFound(testName))
}
case e: Throwable =>
throw e
}
*/
/**
* Run a test.
*
* <p>
* This trait's implementation of this method simply returns <code>SucceededStatus</code>
* and has no other effect.
* </p>
*
* @param testName the name of one test to run.
* @param args the <code>Args</code> for this run
* @return a <code>Status</code> object that indicates when the test started by this method has completed, and whether or not it failed .
*
* @throws NullArgumentException if any of <code>testName</code> or <code>args</code> is <code>null</code>.
* @throws IllegalArgumentException if <code>testName</code> is defined, but no test with the specified test name
* exists in this <code>Suite</code>
*/
protected def runTest(testName: String, args: Args): Status = SucceededStatus
/**
* Run zero to many of this <code>Suite</code>'s tests.
*
* <p>
* This method takes a <code>testName</code> parameter that optionally specifies a test to invoke.
* If <code>testName</code> is defined, this trait's implementation of this method
* invokes <code>runTest</code> on this object, passing in:
* </p>
*
* <ul>
* <li><code>testName</code> - the <code>String</code> value of the <code>testName</code> <code>Option</code> passed
* to this method</li>
* <li><code>reporter</code> - the <code>Reporter</code> passed to this method, or one that wraps and delegates to it</li>
* <li><code>stopper</code> - the <code>Stopper</code> passed to this method, or one that wraps and delegates to it</li>
* <li><code>configMap</code> - the <code>configMap</code> <code>Map</code> passed to this method, or one that wraps and delegates to it</li>
* </ul>
*
* <p>
* This method takes a <code>Filter</code>, which encapsulates an optional <code>Set</code> of tag names that should be included
* (<code>tagsToInclude</code>) and a <code>Set</code> that should be excluded (<code>tagsToExclude</code>), when deciding which
* of this <code>Suite</code>'s tests to run.
* If <code>tagsToInclude</code> is <code>None</code>, all tests will be run
* except those those belonging to tags listed in the <code>tagsToExclude</code> <code>Set</code>. If <code>tagsToInclude</code> is defined, only tests
* belonging to tags mentioned in the <code>tagsToInclude</code> <code>Set</code>, and not mentioned in the <code>tagsToExclude</code <code>Set</code>
* will be run. However, if <code>testName</code> is defined, <code>tagsToInclude</code> and <code>tagsToExclude</code> are essentially ignored.
* Only if <code>testName</code> is <code>None</code> will <code>tagsToInclude</code> and <code>tagsToExclude</code> be consulted to
* determine which of the tests named in the <code>testNames</code> <code>Set</code> should be run. This trait's implementation
* behaves this way, and it is part of the general contract of this method, so all overridden forms of this method should behave
* this way as well. For more information on test tags, see the main documentation for this trait and for class <a href="Filter"><code>Filter</code></a>.
* Note that this means that even if a test is marked as ignored, for example a test method in a <code>Suite</code> annotated with
* <code>org.scalatest.Ignore</code>, if that test name is passed as <code>testName</code> to <code>runTest</code>, it will be invoked
* despite the <code>Ignore</code> annotation.
* </p>
*
* <p>
* If <code>testName</code> is <code>None</code>, this trait's implementation of this method
* invokes <code>testNames</code> on this <code>Suite</code> to get a <code>Set</code> of names of tests to potentially run.
* (A <code>testNames</code> value of <code>None</code> essentially acts as a wildcard that means all tests in
* this <code>Suite</code> that are selected by <code>tagsToInclude</code> and <code>tagsToExclude</code> should be run.)
* For each test in the <code>testName</code> <code>Set</code>, in the order
* they appear in the iterator obtained by invoking the <code>elements</code> method on the <code>Set</code>, this trait's implementation