diff --git a/.classpath b/.classpath
index 6d488d7cbbf8..f648ca63c5ff 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,10 @@
-
- You find additional samples in the
-junit.samples package:
- Common Public License - v 1.0
-
- THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
- 1. DEFINITIONS
- "Contribution" means:
-
-
- "Contributor" means any person or entity that distributes the Program.
-
- "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
-
- "Program" means the Contributions distributed in accordance with this Agreement.
-
- "Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
-
- 2. GRANT OF RIGHTS
-
- 3. REQUIREMENTS
- A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
-
- When the Program is made available in source code form:
-
-
- Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
-
- 4. COMMERCIAL DISTRIBUTION
- Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
-
- For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
-
- 5. NO WARRANTY
- EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
-
- 6. DISCLAIMER OF LIABILITY
- EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
- 7. GENERAL
- If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
-
- If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
-
- All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
-
- Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
-
- This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
-
-
-
-
-
-
\ No newline at end of file
diff --git a/doc/Changes34.html b/doc/Changes34.html
deleted file mode 100644
index 083b4d4b4a43..000000000000
--- a/doc/Changes34.html
+++ /dev/null
@@ -1,226 +0,0 @@
-
-
- A full summary of commits between 4.9 and 4.10 is on github junit-dep-4.9.jar incorrectly contained hamcrest classes, which could lead to version conflicts in projects that depend on hamcrest directly. This is fixed in 4.10 [@dsaff, closing gh-309] The RuleChain rule allows ordering of TestRules: writes the log The Thanks to JUnit now uses the latest version of Hamcrest. Thus, you can use all the available matchers and benefit from an improved Old error message: New error message: Hamcrest's new Running this test will return the following failure message: Most of the matchers in In order to easily identify the individual test cases in a Parameterized test, you may provide a name using the In the example given above, the By design, JUnit does not specify the execution order of test method invocations. Until now, the methods were simply invoked in the order returned by the reflection API. However, using the JVM order is unwise since the Java platform does not specify any particular order, and in fact JDK 7 returns a more or less random order. Of course, well-written test code would not assume any order, but some does, and a predictable failure is better than a random failure on certain platforms. From now on, JUnit will by default use a deterministic, but not predictable, order ( Up until now there were two Maven artifacts for JUnit: From this release on, you should use A number of improvements have been made to Rules:
-JUnit
-3.8.2
-
-
-11/11/2004
-
-
-
-
-Summary of Changes
-between 3.8.1 and 3.8.2
-The changes between the versions are minimal and
-the focus was on fixing the accumulated bug reports. The most
-signifanct change is replacing the much-reviled string comparison
-format with something easier to read and use.
-
-
-
-
-
-
-
-Longer prefixes and suffixes are truncated to a fixed size (currently
-20):
- Closed Bugs/Patches and Enhancment
-Requests
-
-
-
-Summary of Changes between 3.8 and 3.8.1
-
-
-
-Summary of Changes between 3.7 and 3.8
-
-Framework
-
-
-
-Test Runner
-
-
-
-
- Documentation
-
-
-Closed Bugs
-
-
-
-Summary of Changes between 3.6 and 3.7
-
-GUI
-
-
-
-Framework
-
-
-
-Text Runner
-
-
-
-Fixed Bugs (SourceForge Bug Tracker Ids)
- [420315] No trace when fail
-with message...
-
- [419375] reload warning lags
-
- [418849] Classloader warning too obtrusive
-
- [417978] constructor stack trace, please
-
- [415103] Reload checkbox should be ignored in VAJ
-
- [414954] error reporting when invoking suite()
-
- [407296] Make doRun() public
-
- [227578] rmi callbacks fail since TestCase has no
-noArg constructor
-
- [422603] Decorated decorators bug
-
-Summary of Changes between 3.5 and 3.6
-
-TestRunner
-
-
-
-
-
-Framework
-
-
-
-Builds
-
-
-
-Fixed Bugs (SourceForge Bug Tracker Ids)
-[ #229753 ] assertEquals on NaN and
-Infinity does not work
-correctly
-
-
-[ #229287 ] Class Name too long "SimpleClassPathTestCollector"
-
-[ #229609 ] Stack Filtering missing in textui.TesRunner
-
-[ #229870 ] Clicking on ... after tests failed gives NPE
-
-[ #229974 ] Incorrect icon shown for first element in Swing GUI
-
-[ #230581 ] swingui.TestTreeModel: results of decorated testcases...
-
-[ #230971 ] Make junit.extensions.TestDecorator.getTest() public
-
-[ #231569 ] DocBug: JUnit Test Infected: Programmers Love Writing Tests
-
-[ #232645 ] BaseTestRunner.getTest loses exception information
-
-[ #233094 ] TestSuite masks exceptions
-
-[ #410967 ] No icon provided for first test
-
-[ #230745 ] ClassPathTestCollector sometimes lists classes in duplicate
-Documentation
-
-
-
-Summary of Changes between 3.4 and 3.5
-
-Framework
-
-
-
-This method allows to create a TestSuite with a class containing test
-cases directly.
-
-Instead of writing suite.addTest(new TestSuite(AssertTest.class))
- you
-can now write suite.addTestSuite(AssertTest.class);
-
-was changed to addFailure(Test test, AssertionFailedError t)
-
-TestRunner
-
-
-
-
-TestCollectorClass=junit.swingui.LoadingClassPathTestCollector
-
-This class has to be installed on the class path.
-
-JUnit provides two different TestCollector implementations:
-
-
-
- By default the simple the test collector is
-used. The loading collector
-is more precise but much slower than the simple one. The loading
-collector
-doesn't scale up when many classes are available on the class path.
-
- Notice: that both TestCollectors
-assume that the class files reside are kept in the file system. This
-isn't
-case in VA/Java and they will not work there. A custom TestCollector is
-required for VA/Java.
-
-
-FailureViewClass=MyFailureViewClassName.
-
-Tests
-
-
-
-Documentation
-
-
-
-Older Change Notes
-
-
-
-Contents of the Release
-
-
-
-
-
- README.html
- this file
-
-
- junit.jar
- a jar file with the JUnit framework and tools
-
-
- src.jar
- a jar file with the source code of the junit framework
-
-
- junit
- the source code of the JUnit samples
-
-
- samples
- sample test cases
-
-
- tests
- test cases for JUnit itself
-
-
- javadoc
- javadoc generated documentation
-
-
-
-doc
- documentation and articles
-
-Installation
-Below are the installation steps for installing
-JUnit:
-
-
-
-Important:
-don't install the junit.jar
-into the extension directory of your JDK installation. If you do so the
-test class on the files system will not be found.
-
-
- Notice: that the tests are not
-contained in the junit.jar but in the installation directory directly.
-Therefore make sure that the installation directory is on the class
-path
-
-
-
-
- java junit.textui.TestRunner
-junit.samples.AllTests
-
- java junit.awtui.TestRunner
-junit.samples.AllTests
-
- java junit.swingui.TestRunner
-junit.samples.AllTests
- Getting Started
-To get started with unit testing and JUnit read
-the Java Report article:
-Test
-Infected - Programmers Love Writing Tests.
-
-This article demonstrates the development process with JUnit in the
-context of multiple currency arithmetic. The corresponding source code
-is in junit\samples\money.
-
-
-
-
-Documentation
-JUnit
-Cookbook
-
-
- A cookbook for implementing tests with JUnit.
-
- Test Infected - Programmers
-Love Writing Tests
-
- An article demonstrating the development process
-with JUnit.
-
- JUnit - A cooks tour
-
- Javadoc
-
- API documentation generated with javadoc.
-
- Frequently asked questions
-
- Some frequently asked questions about using JUnit.
-
- TestRunner Preference settings
-
- Describes the preferences settings that can be
-configured
-for the JUnit TestRunners.
- License
-
- The terms of the common public license used for
-JUnit.
-Extending JUnit
-Examples of possible JUnit extensions can be
-found in the junit.extensions
-package:
-
-
-
-
-
-
-
diff --git a/README.md b/README.md
new file mode 100644
index 000000000000..f73f89ca5ed0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# JUnit 4
+JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.
+
+For more information, please visit:
+* [Wiki](https://github.com/junit-team/junit4/wiki)
+* [Download and Install guide](https://github.com/junit-team/junit4/wiki/Download-and-Install)
+* [Getting Started](https://github.com/junit-team/junit4/wiki/Getting-started)
+
+[](https://travis-ci.org/junit-team/junit4)
diff --git a/acknowledgements.txt b/acknowledgements.txt
new file mode 100644
index 000000000000..bbc24dfe041f
--- /dev/null
+++ b/acknowledgements.txt
@@ -0,0 +1,163 @@
+2006 March 9
+ Matthias Schmidt: improved org.junit package javadoc
+
+2006 August 3
+ giovanni: better test for TestCase without a name.
+ Matthias Pfau: better error message when test case constructor fails
+
+2006 November 21
+ dakcalouro: Found defect with comparing ints and longs (1555161)
+ Ben Maurer: Found defect with timeouts taking twice as long as specified (1536198)
+
+2007 February 08
+ Kazimierz Pogoda: Found defect with null array elements (1438163)
+
+2007 July 09
+ wangqq: Found defect with @After not running after a timeout (1745048)
+
+2007 July 18
+ Andrew Dick: Found defect with assertEquals comparing non-Integer Numbers (1715326)
+ Michael Schechter: Found defect with Filters and suite() methods (1739095)
+
+2008 February 5
+ Walter Gildersleeve: Found assertEquals(null, "null") defect (1857283)
+
+2008 July 1
+ Johannes Link: Submitted test for running subclasses of Suite
+
+2008 July 23
+ Daniel Brolund: Submitted patch for build.xml, fixing 1.5 compatibility (2021396)
+
+2008 Aug 1
+ Nat Pryce: Found defect in treatment of validation errors from custom
+ subclasses of the legacy JUnit4ClassRunner.
+
+2008 Aug 18
+ Nir Soffer: Suggested adding to the cookbook information about running
+ running JUnit from the command line.
+
+2008 Aug 19
+ Jack Woehr: Discovered build.xml was missing from junit-4.x.zip
+
+2009 Jan 5
+ Amanda Robinson: Fixed overly permissive @DataPoint processing.
+
+2009 Feb 9
+ Mark Shapiro: Discovered bug in test counting after an ignored method (2106324)
+
+2009 Apr 20
+ Chris Felaco: Discovered regression in handling suite() methods with JUnit 3 runner (1812200)
+ Toby Byron: Suggested updating linking in javadoc (2090230)
+ Raphael Parree: Improved docs on Parameterized (2186792)
+ Robin de Silva Jayasinghe: Fixed Javadoc code sample for AfterClass (2126279)
+
+2009 May 04
+ James Abbley: Submitted a patch that fixed the 2-second limit on Parallel execution.
+
+2009 Nov 16
+ Kristian Rosenvold: Submitted a patch (github#16) that improves thread-safety of
+ result counting
+2010 Feb 08
+ Paul Holser: Submitted additional test for TestName rule.
+
+2010 May 03
+ jonas22@github: Found bug (github#98) with assumptions and expected exceptions.
+
+2011 Jan 03
+ jens.schauder@freenet.de: Found bug (github#74) with Categories and
+ Parameterized.
+
+2011 Jan 18
+ Markus Keller: Reported bug (github#163):
+ Bad comparison failure message when using assertEquals(String, String)
+
+ Kevin Cooney (kcooney@github):
+ Patches for runLeaf, public multiple failure exception,
+ assertion messages and null.
+
+2011 Mar 04
+ Jerome Lacoste (lacostej@github) for initial patch for GH-191.
+
+2011 Apr 15
+ reinholdfuereder@github For initial test for GH-39
+
+2011 Apr 15
+ ububenheimer@github for bug report https://github.com/junit-team/junit4/issues/208
+
+2011 Apr 29
+ reinholdfuereder@github: bug report, test, and fix for GH-38:
+ ParentRunner filtering
+2011 Apr 29
+ Markus Keller (mkeller@github): Report for GH-187:
+ Unintentional dependency on Java 6
+
+2011 May 31
+ Kevin Cooney (kcooney@github): Patches for filtering test suites:
+ copy List returned by getChildren() before mutating it;
+ optimize ParentRunner.filter for nested suites;
+ optimize Filter.intersect for common cases
+
+2011 Jun 06
+ Vampire@github: Report for GH-235: 4.7 release notes incorrect.
+
+2011 Jun 24
+ Samuel Le Berrigaud (sleberrigaud@github): Report for GH-248:
+ protected BlockJUnit4ClassRunner#rules method removed from 4.8.2
+
+2011 Jun 24
+ Daniel Rothmaler (drothmaler@github):
+ #299: random temp file/folder creation
+ #300: ErrorCollector.checkThat overload
+
+2011 Jun 25
+ Juan Cortez (jcortez@github): Fixed issue #219 where floats were being
+ printed and represented as doubles in error messages.
+
+2011 Jul 06
+ Stefan Birkner: Fixed wrong documentation of ClassRule (github#254).
+
+2011 Jul 08
+ Paul Holser (pholser@alumni.rice.edu): Beginnings of fix for GH-64:
+ Theories doesn't honor parameterized types
+
+2011 Jul 09
+ Nigel Charman: Reported Rules bugs github#257 and gihub#258.
+
+2011 Jul 09
+ Stefan Birkner: Fixed rules bugs (github#257, gihub#258, github#260).
+
+2011 Jul 09
+ Stefan Birkner: Fixed rules bugs (github#257, gihub#258, github#260).
+
+2011 Jul 16
+ Rob Dawson: Submitted a patch that makes Results serlializable.
+
+2011 Jul 20
+ Asaf Ary, Stefan Birkner: Fixed FailOnTimeout class (github#265).
+
+2011 Jul 22
+ Andreas Köhler, Stefan Birkner: Fixed wrong documentation of Parameterized (github#89).
+
+2011 Jul 28
+ electrickery, Stefan Birkner: Fixed typo in JavaDoc (github#134).
+
+2011 Aug 07
+ Esko Luontola: Fixed TemporaryFolder creating files in the current working directory (github#278).
+
+2011 Aug 09
+ Stefan Birkner: Fixed JavaDoc links.
+
+2011 Aug 10
+ rodolfoliviero@github and JoseRibeiro@github: feature to create recursive temporary folders.
+
+2011 Aug 12
+ Esko Luontola: Fixed syntax error in Parameterized's usage example (github#285).
+
+2011 Sep 09
+ Robert Munteanu, Stefan Birkner:
+ TestWatcher and TestWatchman don't call failed when assumption is violated (github#296).
+ digulla@github, Stefan Birkner: Removed useless code (github#289).
+
+== NOTE: as of September 2011, we have stopped recording contributions here.
+ For a full list of everyone who has contributed great bug reports and code, please see
+ http://github.com/junit-team/junit4
diff --git a/build.xml b/build.xml
deleted file mode 100644
index dff506ce1363..000000000000
--- a/build.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
-
-
-
-b) in the case of each subsequent Contributor:i) changes to the Program, and
-
-
-ii) additions to the Program;
-
-
-where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
-
-a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
-
-
-
-
-
-
b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
-
-
-
-
-
-
c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
-
-
-
-
-
-
d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
-
-
-
-
-
a) it complies with the terms and conditions of this Agreement; and
-
-
-b) its license agreement:
-
-
-i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
-
-
-ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
-
-
-iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
-
-
-iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
-
-
-
-
-
a) it must be made available under this Agreement; and
-
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-
-Contributors may not remove or alter any copyright notices contained within the Program.
-
-
-
-
-Summary of Changes between 3.3 and 3.4
-
-
-
-
-
-Summary of Changes between 3.2 and 3.3
-
-
-Framework
-
-
-
-
-
-Extensions
-
-
-
-
-
-TestRunner
-
-
-
-
-
-
-
-Release
-
-
-
-
-
-Summary of Changes between 3.1 and 3.2
-
-
-
-
-
-Summary of Changes between 2.1 and 3.1
-
-
-JUnit Framework
-
-
-
-
-
-TestRunner
-
-
-
-
-
java junit.swingui.TestRunner
-
There is also a LoadingTestRunner for Swing. The Swing TestRunner requires
-Swing 1.1 (javax.swing package structure) or jdk 1.2.
-
public static void main(String args[]) {
-
junit.textui.TestRunner.run(MoneyTest.class);
-
}
-Documentation
-
-
-
-
-
-Release
-
-
-
-
-
-
diff --git a/doc/JUnitProperties.html b/doc/JUnitProperties.html
deleted file mode 100644
index f471be98ac00..000000000000
--- a/doc/JUnitProperties.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
-
-JUnit TestRunner Properties
-The TestRunners use a properties file for preference settings. This file
-is stored in the folder referred to by the "user.home" system property.
-The following properties are supported:
-
-
-
-
-
-
diff --git a/doc/ReleaseNotes4.10.html b/doc/ReleaseNotes4.10.html
new file mode 100644
index 000000000000..b6b9483b8a74
--- /dev/null
+++ b/doc/ReleaseNotes4.10.html
@@ -0,0 +1,93 @@
+
-
-
-loading
-
-Use a custom class loader to load classes for each run. Default value=true.
-
-
-
-filterstack
-
-Filter JUnit internal methods in failure or error stack traces. Default
-value=true.
-
-
-
-maxmessage
-
-The maximum output length. Default value=500. Set maxmessage to -1
-to disable output truncation. Disabling the output truncation will result
-in long test runs when an assertEquals method fails and the toString()
-method results in massive output.
-
-
-
-TestCollectorClass
-
-
-
Swing UI TestRunner onlyThe Swing TestRunner supports to browse test classes. There is an additional
-browse ("...") button besides the suite combo. It shows a simple dialog
-to select a test class from a list. Different strategies to locate Test
-classes are supported and you can plug-in your own strategy. This allows
-to leverage functionality provided by an extension API of an integrated
-development environment (IDE). To define a custom test collector you 1)
-implement the junit.runner.TestCollector interface and 2) add an entry
-to the junit.properties file with the key TestCollectorClass and the name
-of your TestCollector implementation class as the key:
-
-
-TestCollectorClass=junit.swingui.LoadingTestCollector
-
This class has to be installed on the class path.
-
-FailureViewClass
-
-
-
Swing UI TestRunner onlyPlug-in a custom failure panel that provides additional functionality
-like navigating from a failure to the source. To do so you implement the
-junit.runner.FailureDetailView interface and register the implementation
-class in the junit.properties file under the key FailureViewClass, for
-example.
-
-
-FailureViewClass=somepackage.MyFailureViewClassName.
-
This class has to be installed on the class path. Summary of Changes in version 4.10
+
+junit-dep has correct contents
+
+RuleChain
+
+
+
+public static class UseRuleChain {
+ @Rule
+ public TestRule chain= RuleChain
+ .outerRule(new LoggingRule("outer rule")
+ .around(new LoggingRule("middle rule")
+ .around(new LoggingRule("inner rule");
+
+ @Test
+ public void example() {
+ assertTrue(true);
+ }
+}
+
+
+starting outer rule
+starting middle rule
+starting inner rule
+finished inner rule
+finished middle rule
+finished outer rule
+
TemporaryFolder
+
+
+
+
+TemporaryFolder#newFolder(String... folderNames)
creates recursively deep temporary folders
+[@rodolfoliviero, closing gh-283]TemporaryFolder#newFile()
creates a randomly named new file, and #newFolder()
creates a randomly named new folder
+[@Daniel Rothmaler, closing gh-299]Theories
+
+Theories
runner does not anticipate theory parameters that have generic
+types, as reported by github#64. Fixing this won't happen until Theories
is
+moved to junit-contrib. In anticipation of this, 4.9.1 adds some of the
+necessary machinery to the runner classes, and deprecates a method that only
+the Theories
runner uses, FrameworkMethod
#producesType().
+The Common Public License that JUnit is released under is now included
+in the source repository.@pholser
for identifying a potential resolution for github#64
+and initiating work on it.Bug fixes
+
+
+
+
+
+
+
+
@Category
annotations
+[@dsaff, fixing gh-291]Minor changes
+
+
+
diff --git a/doc/ReleaseNotes4.10.md b/doc/ReleaseNotes4.10.md
new file mode 100644
index 000000000000..5f19bf744889
--- /dev/null
+++ b/doc/ReleaseNotes4.10.md
@@ -0,0 +1,86 @@
+## Summary of Changes in version 4.10 ##
+
+Thanks to a full cast of contributors of bug fixes and new features.
+
+A full summary of commits between 4.9 and 4.10 is on [github](https://github.com/junit-team/junit4/compare/r4.9...r4.10)
+
+### junit-dep has correct contents ###
+
+junit-dep-4.9.jar incorrectly contained hamcrest classes, which could lead to version conflicts in projects that depend on hamcrest directly. This is fixed in 4.10 [@dsaff, closing gh-309]
+
+### RuleChain ###
+
+The RuleChain rule allows ordering of TestRules:
+
+```java
+public static class UseRuleChain {
+ @Rule
+ public TestRule chain= RuleChain
+ .outerRule(new LoggingRule("outer rule")
+ .around(new LoggingRule("middle rule")
+ .around(new LoggingRule("inner rule");
+
+ @Test
+ public void example() {
+ assertTrue(true);
+ }
+}
+```
+
+writes the log
+
+ starting outer rule
+ starting middle rule
+ starting inner rule
+ finished inner rule
+ finished middle rule
+ finished outer rule
+
+### TemporaryFolder ###
+
+- `TemporaryFolder#newFolder(String... folderNames)` creates recursively deep temporary folders
+ [@rodolfoliviero, closing gh-283]
+- `TemporaryFolder#newFile()` creates a randomly named new file, and `#newFolder()` creates a randomly named new folder
+ [@Daniel Rothmaler, closing gh-299]
+
+### Theories ###
+
+The `Theories` runner does not anticipate theory parameters that have generic
+types, as reported by github#64. Fixing this won't happen until `Theories` is
+moved to junit-contrib. In anticipation of this, 4.9.1 adds some of the
+necessary machinery to the runner classes, and deprecates a method that only
+the `Theories` runner uses, `FrameworkMethod`#producesType().
+The Common Public License that JUnit is released under is now included
+in the source repository.
+
+Thanks to `@pholser` for identifying a potential resolution for github#64
+and initiating work on it.
+
+### Bug fixes ###
+
+- Built-in Rules implementations
+ - TemporaryFolder should not create files in the current working directory if applying the rule fails
+ [@orfjackal, fixing gh-278]
+ - TestWatcher and TestWatchman should not call failed for AssumptionViolatedExceptions
+ [@stefanbirkner, fixing gh-296]
+- Javadoc bugs
+ - Assert documentation [@stefanbirkner, fixing gh-134]
+ - ClassRule [@stefanbirkner, fixing gh-254]
+ - Parameterized [@stefanbirkner, fixing gh-89]
+ - Parameterized, again [@orfjackal, fixing gh-285]
+- Miscellaneous
+ - Useless code in RunAfters [@stefanbirkner, fixing gh-289]
+ - Parameterized test classes should be able to have `@Category` annotations
+ [@dsaff, fixing gh-291]
+ - Error count should be initialized in junit.tests.framework.TestListenerTest [@stefanbirkner, fixing gh-225]
+ - AssertionFailedError constructor shouldn't call super with null message [@stefanbirkner, fixing gh-318]
+ - Clearer error message for non-static inner test classes [@stefanbirkner, fixing gh-42]
+
+### Minor changes ###
+
+- Description, Result and Failure are Serializable [@ephox-rob, closing gh-101]
+- FailOnTimeout is reusable, allowing for retrying Rules [@stefanbirkner, closing gh-265]
+- New `ErrorCollector.checkThat` overload, that allows you to specify a reason [@drothmaler, closing gh-300]
+
+
+
diff --git a/doc/ReleaseNotes4.10.txt b/doc/ReleaseNotes4.10.txt
new file mode 100644
index 000000000000..bc63f07611c7
--- /dev/null
+++ b/doc/ReleaseNotes4.10.txt
@@ -0,0 +1 @@
+Please see ReleaseNotes4.10.md
diff --git a/doc/ReleaseNotes4.11.html b/doc/ReleaseNotes4.11.html
new file mode 100644
index 000000000000..fefd79f6910a
--- /dev/null
+++ b/doc/ReleaseNotes4.11.html
@@ -0,0 +1,121 @@
+ErrorCollector.checkThat
overload, that allows you to specify a reason [@drothmaler, closing gh-300]Summary of changes in version 4.11
+
+Matchers: Upgrade to Hamcrest 1.3
+
+assertThat
which will now print the mismatch description from the matcher when an assertion fails.Example
+
+
+
+assertThat(Long.valueOf(1), instanceOf(Integer.class));
+
+
+Expected: an instance of java.lang.Integer
+ got: <1L>
+
+
+Expected: an instance of java.lang.Integer
+ but: <1L> is a java.lang.Long
+
FeatureMatcher
makes writing custom matchers that make use of custom mismatch descriptions quite easy:
+
+@Test
+public void featureMatcher() throws Exception {
+ assertThat("Hello World!", length(is(0)));
+}
+
+private Matcher<String> length(Matcher<? super Integer> matcher) {
+ return new FeatureMatcher<String, Integer>(matcher, "a String of length that", "length") {
+ @Override
+ protected Integer featureValueOf(String actual) {
+ return actual.length();
+ }
+ };
+}
+
+
+Expected: a String of length that is <0>
+ but: length was <12>
+
JUnitMatchers
have been deprecated. Please use org.hamcrest.CoreMatchers
directly.Parameterized Tests
+
+@Parameters
annotation. This name is allowed to contain placeholders that are replaced at runtime:
+
+
+{index}
: the current parameter index{0}
, {1}
, …: the first, second, and so on, parameter valueExample
+
+
+
+@RunWith(Parameterized.class)
+public class FibonacciTest {
+
+ @Parameters(name = "{index}: fib({0})={1}")
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
+ { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
+ }
+
+ private int input;
+ private int expected;
+
+ public FibonacciTest(int input, int expected) {
+ this.input = input;
+ this.expected = expected;
+ }
+
+ @Test
+ public void test() {
+ assertEquals(expected, Fibonacci.compute(input));
+ }
+}
+
Parameterized
runner creates names like [1: fib(3)=2]
. If you don't specify a name, the current parameter index will be used by default.Test execution order
+
+MethodSorters.DEFAULT
). To change the test execution order simply annotate your test class using @FixMethodOrder
and specify one of the available MethodSorters
:
+
+
+@FixMethodOrder(MethodSorters.JVM)
: Leaves the test methods in the order returned by the JVM. This order may vary from run to run.@FixMethodOrder(MethodSorters.NAME_ASCENDING)
: Sorts the test methods by method name, in lexicographic order.Maven artifacts
+
+junit:junit-dep
and junit:junit
. From a Maven point-of-view only the former made sense because it did not contain the Hamcrest classes but declared a dependency to the Hamcrest Maven artifact. The latter included the Hamcrest classes which was very un-Maven-like.junit:junit
which will be what junit:junit-dep
used to. If you still reference junit:junit-dep
, Maven will automatically relocate you to the new junit:junit
and issue a warning for you to fix.Rules
+
+
+
+
+MethodRule
is no longer deprecated.@Rule
and @ClassRule
can now be used on methods that return a TestRule
.ExpectedException
now always prints the stacktrace of the actual exception in case of failure.TemporaryFolder
. In addition, the newFile
/newFolder
methods will now fail when the file or folder could not be created.TestWatcher
has a new template method called skipped
that is invoked when a test is skipped due to a failed assumption.Improvements to Assert and Assume
+
+
+
diff --git a/doc/ReleaseNotes4.11.md b/doc/ReleaseNotes4.11.md
new file mode 100644
index 000000000000..740c64a09d7c
--- /dev/null
+++ b/doc/ReleaseNotes4.11.md
@@ -0,0 +1,116 @@
+## Summary of changes in version 4.11
+
+### Matchers: Upgrade to Hamcrest 1.3
+
+JUnit now uses the latest version of Hamcrest. Thus, you can use all the available matchers and benefit from an improved `assertThat` which will now print the mismatch description from the matcher when an assertion fails.
+
+#### Example
+
+```java
+assertThat(Long.valueOf(1), instanceOf(Integer.class));
+```
+
+Old error message:
+
+ Expected: an instance of java.lang.Integer
+ got: <1L>
+
+New error message:
+
+ Expected: an instance of java.lang.Integer
+ but: <1L> is a java.lang.Long
+
+Hamcrest's new `FeatureMatcher` makes writing custom matchers that make use of custom mismatch descriptions quite easy:
+
+```java
+@Test
+public void featureMatcher() throws Exception {
+ assertThat("Hello World!", length(is(0)));
+}
+
+private MatcherassertNotEquals
has been added to Assert
.assertEquals
has been overloaded in order to check whether two floats are equal given a certain float delta.Assume
now allow to pass a custom message.
false
, the method will attempt to stop the test and ignore it by
+ * throwing {@link AssumptionViolatedException}.
+ * @param message A message to pass to {@link AssumptionViolatedException}.
+ */
+ public static void assumeTrue(String message, boolean b) {
+ if (!b) throw new AssumptionViolatedException(message);
+ }
+
+ /**
+ * The inverse of {@link #assumeTrue(String, boolean)}.
+ */
+ public static void assumeFalse(String message, boolean b) {
+ assumeTrue(message, !b);
+ }
+
+ /**
+ * If called with a {@code null} array or one or more {@code null} elements in {@code objects},
+ * the test will halt and be ignored.
+ */
+ public static void assumeNotNull(Object... objects) {
+ assumeThat(objects, notNullValue());
+ assumeThat(asList(objects), everyItem(notNullValue()));
+ }
+
+ /**
+ * Call to assume that actual
satisfies the condition specified by matcher
.
+ * If not, the test halts and is ignored.
+ * Example:
+ * : + * assumeThat(1, is(1)); // passes + * foo(); // will execute + * assumeThat(0, is(1)); // assumption failure! test halts + * int x = 1 / 0; // will never execute + *+ * + * @param
actual
satisfies the condition specified by matcher
.
+ * If not, the test halts and is ignored.
+ * Example:
+ * : + * assumeThat("alwaysPasses", 1, is(1)); // passes + * foo(); // will execute + * assumeThat("alwaysFails", 0, is(1)); // assumption failure! test halts + * int x = 1 / 0; // will never execute + *+ * + * @param
+ * \@Test public void parseDataFile() { + * DataFile file; + * try { + * file = DataFile.open("sampledata.txt"); + * } catch (IOException e) { + * // stop test and ignore if data can't be opened + * assumeNoException(e); + * } + * // ... + * } + *+ * + * @param e if non-null, the offending exception + */ + public static void assumeNoException(Throwable e) { + assumeThat(e, nullValue()); + } + + /** + * Attempts to halt the test and ignore it if Throwable
e
is
+ * not null
. Similar to {@link #assumeNoException(Throwable)},
+ * but provides an additional message that can explain the details
+ * concerning the assumption.
+ *
+ * @param e if non-null, the offending exception
+ * @param message Additional message to pass to {@link AssumptionViolatedException}.
+ * @see #assumeNoException(Throwable)
+ */
+ public static void assumeNoException(String message, Throwable e) {
+ assumeThat(message, e, nullValue());
+ }
+}
diff --git a/src/main/java/org/junit/AssumptionViolatedException.java b/src/main/java/org/junit/AssumptionViolatedException.java
new file mode 100644
index 000000000000..1d62190a2315
--- /dev/null
+++ b/src/main/java/org/junit/AssumptionViolatedException.java
@@ -0,0 +1,46 @@
+package org.junit;
+
+import org.hamcrest.Matcher;
+
+/**
+ * An exception class used to implement assumptions (state in which a given test
+ * is meaningful and should or should not be executed). A test for which an assumption
+ * fails should not generate a test case failure.
+ *
+ * @see org.junit.Assume
+ * @since 4.12
+ */
+@SuppressWarnings("deprecation")
+public class AssumptionViolatedException extends org.junit.internal.AssumptionViolatedException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * An assumption exception with the given actual value and a matcher describing
+ * the expectation that failed.
+ */
+ public public void
method
+ * with @Before
causes that method to be run before the {@link org.junit.Test} method.
+ * The @Before
methods of superclasses will be run before those of the current class,
+ * unless they are overridden in the current class. No other ordering is defined.
+ * + * Here is a simple example: + *
+ * public class Example { + * List empty; + * @Before public void initialize() { + * empty= new ArrayList(); + * } + * @Test public void size() { + * ... + * } + * @Test public void remove() { + * ... + * } + * } + *+ * + * @see org.junit.BeforeClass + * @see org.junit.After + * @since 4.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Before { +} + diff --git a/src/main/java/org/junit/BeforeClass.java b/src/main/java/org/junit/BeforeClass.java new file mode 100644 index 000000000000..8183fa0f0a14 --- /dev/null +++ b/src/main/java/org/junit/BeforeClass.java @@ -0,0 +1,37 @@ +package org.junit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Sometimes several tests need to share computationally expensive setup + * (like logging into a database). While this can compromise the independence of + * tests, sometimes it is a necessary optimization. Annotating a
public static void
no-arg method
+ * with @BeforeClass
causes it to be run once before any of
+ * the test methods in the class. The @BeforeClass
methods of superclasses
+ * will be run before those of the current class, unless they are shadowed in the current class.
+ * + * For example: + *
+ * public class Example { + * @BeforeClass public static void onlyOnce() { + * ... + * } + * @Test public void one() { + * ... + * } + * @Test public void two() { + * ... + * } + * } + *+ * + * @see org.junit.AfterClass + * @since 4.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface BeforeClass { +} diff --git a/src/main/java/org/junit/ClassRule.java b/src/main/java/org/junit/ClassRule.java new file mode 100644 index 000000000000..94ee29f9f51d --- /dev/null +++ b/src/main/java/org/junit/ClassRule.java @@ -0,0 +1,118 @@ +package org.junit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates static fields that reference rules or methods that return them. A field must be public, + * static, and a subtype of {@link org.junit.rules.TestRule}. A method must be public static, and return + * a subtype of {@link org.junit.rules.TestRule}. + *
+ * The {@link org.junit.runners.model.Statement} passed + * to the {@link org.junit.rules.TestRule} will run any {@link BeforeClass} methods, + * then the entire body of the test class (all contained methods, if it is + * a standard JUnit test class, or all contained classes, if it is a + * {@link org.junit.runners.Suite}), and finally any {@link AfterClass} methods. + *
+ * The statement passed to the {@link org.junit.rules.TestRule} will never throw an exception, + * and throwing an exception from the {@link org.junit.rules.TestRule} will result in undefined + * behavior. This means that some {@link org.junit.rules.TestRule}s, such as + * {@link org.junit.rules.ErrorCollector}, + * {@link org.junit.rules.ExpectedException}, + * and {@link org.junit.rules.Timeout}, + * have undefined behavior when used as {@link ClassRule}s. + *
+ * If there are multiple + * annotated {@link ClassRule}s on a class, they will be applied in an order + * that depends on your JVM's implementation of the reflection API, which is + * undefined, in general. However, Rules defined by fields will always be applied + * after Rules defined by methods, i.e. the Statements returned by the former will + * be executed around those returned by the latter. + * + *
+ * For example, here is a test suite that connects to a server once before + * all the test classes run, and disconnects after they are finished: + *
+ * @RunWith(Suite.class) + * @SuiteClasses({A.class, B.class, C.class}) + * public class UsesExternalResource { + * public static Server myServer= new Server(); + * + * @ClassRule + * public static ExternalResource resource= new ExternalResource() { + * @Override + * protected void before() throws Throwable { + * myServer.connect(); + * } + * + * @Override + * protected void after() { + * myServer.disconnect(); + * } + * }; + * } + *+ *
+ * and the same using a method + *
+ * @RunWith(Suite.class) + * @SuiteClasses({A.class, B.class, C.class}) + * public class UsesExternalResource { + * public static Server myServer= new Server(); + * + * @ClassRule + * public static ExternalResource getResource() { + * return new ExternalResource() { + * @Override + * protected void before() throws Throwable { + * myServer.connect(); + * } + * + * @Override + * protected void after() { + * myServer.disconnect(); + * } + * }; + * } + * } + *+ *
+ * For more information and more examples, see {@link org.junit.rules.TestRule}. + * + *
+ * You can use {@link #order()} if you want to have control over the order in + * which the Rules are applied. + * + *
+ * public class ThreeClassRules { + * @ClassRule(order = 0) + * public static LoggingRule outer = new LoggingRule("outer rule"); + * + * @ClassRule(order = 1) + * public static LoggingRule middle = new LoggingRule("middle rule"); + * + * @ClassRule(order = 2) + * public static LoggingRule inner = new LoggingRule("inner rule"); + * + * // ... + * } + *+ * + * @since 4.9 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +public @interface ClassRule { + + /** + * Specifies the order in which rules are applied. The rules with a higher value are inner. + * + * @since 4.13 + */ + int order() default Rule.DEFAULT_ORDER; + +} diff --git a/src/main/java/org/junit/ComparisonFailure.java b/src/main/java/org/junit/ComparisonFailure.java new file mode 100644 index 000000000000..d1daa863c3f3 --- /dev/null +++ b/src/main/java/org/junit/ComparisonFailure.java @@ -0,0 +1,171 @@ +package org.junit; + +/** + * Thrown when an {@link org.junit.Assert#assertEquals(Object, Object) assertEquals(String, String)} fails. + * Create and throw a
ComparisonFailure
manually if you want to show users the
+ * difference between two complex strings.
+ *
+ * Inspired by a patch from Alex Chaffee (alex@purpletech.com)
+ *
+ * @since 4.0
+ */
+public class ComparisonFailure extends AssertionError {
+ /**
+ * The maximum length for expected and actual strings. If it is exceeded, the strings should be shortened.
+ *
+ * @see ComparisonCompactor
+ */
+ private static final int MAX_CONTEXT_LENGTH = 20;
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * We have to use the f prefix until the next major release to ensure
+ * serialization compatibility.
+ * See https://github.com/junit-team/junit4/issues/976
+ */
+ private String fExpected;
+ private String fActual;
+
+ /**
+ * Constructs a comparison failure.
+ *
+ * @param message the identifying message or null
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonFailure(String message, String expected, String actual) {
+ super(message);
+ this.fExpected = expected;
+ this.fActual = actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in place of common suffix between expected and actual.
+ *
+ * @see Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
+ }
+
+ /**
+ * Returns the actual string value
+ *
+ * @return the actual string value
+ */
+ public String getActual() {
+ return fActual;
+ }
+
+ /**
+ * Returns the expected string value
+ *
+ * @return the expected string value
+ */
+ public String getExpected() {
+ return fExpected;
+ }
+
+ private static class ComparisonCompactor {
+ private static final String ELLIPSIS = "...";
+ private static final String DIFF_END = "]";
+ private static final String DIFF_START = "[";
+
+ /**
+ * The maximum length for expected
and actual
strings to show. When
+ * contextLength
is exceeded, the Strings are shortened.
+ */
+ private final int contextLength;
+ private final String expected;
+ private final String actual;
+
+ /**
+ * @param contextLength the maximum length of context surrounding the difference between the compared strings.
+ * When context length is exceeded, the prefixes and suffixes are compacted.
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonCompactor(int contextLength, String expected, String actual) {
+ this.contextLength = contextLength;
+ this.expected = expected;
+ this.actual = actual;
+ }
+
+ public String compact(String message) {
+ if (expected == null || actual == null || expected.equals(actual)) {
+ return Assert.format(message, expected, actual);
+ } else {
+ DiffExtractor extractor = new DiffExtractor();
+ String compactedPrefix = extractor.compactPrefix();
+ String compactedSuffix = extractor.compactSuffix();
+ return Assert.format(message,
+ compactedPrefix + extractor.expectedDiff() + compactedSuffix,
+ compactedPrefix + extractor.actualDiff() + compactedSuffix);
+ }
+ }
+
+ private String sharedPrefix() {
+ int end = Math.min(expected.length(), actual.length());
+ for (int i = 0; i < end; i++) {
+ if (expected.charAt(i) != actual.charAt(i)) {
+ return expected.substring(0, i);
+ }
+ }
+ return expected.substring(0, end);
+ }
+
+ private String sharedSuffix(String prefix) {
+ int suffixLength = 0;
+ int maxSuffixLength = Math.min(expected.length() - prefix.length(),
+ actual.length() - prefix.length()) - 1;
+ for (; suffixLength <= maxSuffixLength; suffixLength++) {
+ if (expected.charAt(expected.length() - 1 - suffixLength)
+ != actual.charAt(actual.length() - 1 - suffixLength)) {
+ break;
+ }
+ }
+ return expected.substring(expected.length() - suffixLength);
+ }
+
+ private class DiffExtractor {
+ private final String sharedPrefix;
+ private final String sharedSuffix;
+
+ /**
+ * Can not be instantiated outside {@link org.junit.ComparisonFailure.ComparisonCompactor}.
+ */
+ private DiffExtractor() {
+ sharedPrefix = sharedPrefix();
+ sharedSuffix = sharedSuffix(sharedPrefix);
+ }
+
+ public String expectedDiff() {
+ return extractDiff(expected);
+ }
+
+ public String actualDiff() {
+ return extractDiff(actual);
+ }
+
+ public String compactPrefix() {
+ if (sharedPrefix.length() <= contextLength) {
+ return sharedPrefix;
+ }
+ return ELLIPSIS + sharedPrefix.substring(sharedPrefix.length() - contextLength);
+ }
+
+ public String compactSuffix() {
+ if (sharedSuffix.length() <= contextLength) {
+ return sharedSuffix;
+ }
+ return sharedSuffix.substring(0, contextLength) + ELLIPSIS;
+ }
+
+ private String extractDiff(String source) {
+ return DIFF_START + source.substring(sharedPrefix.length(), source.length() - sharedSuffix.length())
+ + DIFF_END;
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/junit/FixMethodOrder.java b/src/main/java/org/junit/FixMethodOrder.java
new file mode 100644
index 000000000000..aaa0313e710c
--- /dev/null
+++ b/src/main/java/org/junit/FixMethodOrder.java
@@ -0,0 +1,41 @@
+package org.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.runners.MethodSorters;
+
+/**
+ * This class allows the user to choose the order of execution of the methods within a test class.
+ *
+ * The default order of execution of JUnit tests within a class is deterministic but not predictable. + * The order of execution is not guaranteed for Java 7 (and some previous versions), and can even change + * from run to run, so the order of execution was changed to be deterministic (in JUnit 4.11) + * + *
It is recommended that test methods be written so that they are independent of the order that they are executed. + * However, there may be a number of dependent tests either through error or by design. + * This class allows the user to specify the order of execution of test methods. + * + *
For possibilities, see {@link MethodSorters} + * + * Here is an example: + * + *
+ * @FixMethodOrder(MethodSorters.NAME_ASCENDING) + * public class MyTest { + * } + *+ * + * @see org.junit.runners.MethodSorters + * @since 4.11 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface FixMethodOrder { + /** + * Optionally specify
value
to have the methods executed in a particular order
+ */
+ MethodSorters value() default MethodSorters.DEFAULT;
+}
diff --git a/src/main/java/org/junit/Ignore.java b/src/main/java/org/junit/Ignore.java
new file mode 100644
index 000000000000..db23581073bd
--- /dev/null
+++ b/src/main/java/org/junit/Ignore.java
@@ -0,0 +1,40 @@
+package org.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Sometimes you want to temporarily disable a test or a group of tests. Methods annotated with
+ * {@link org.junit.Test} that are also annotated with @Ignore
will not be executed as tests.
+ * Also, you can annotate a class containing test methods with @Ignore
and none of the containing
+ * tests will be executed. Native JUnit 4 test runners should report the number of ignored tests along with the
+ * number of tests that ran and the number of tests that failed.
+ *
+ * For example: + *
+ * @Ignore @Test public void something() { ... + *+ * @Ignore takes an optional default parameter if you want to record why a test is being ignored: + *
+ * @Ignore("not ready yet") @Test public void something() { ... + *+ * @Ignore can also be applied to the test class: + *
+ * @Ignore public class IgnoreMe { + * @Test public void test1() { ... } + * @Test public void test2() { ... } + * } + *+ * + * @since 4.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Ignore { + /** + * The optional reason why the test is ignored. + */ + String value() default ""; +} diff --git a/src/main/java/org/junit/Rule.java b/src/main/java/org/junit/Rule.java new file mode 100644 index 000000000000..9370e94f51fc --- /dev/null +++ b/src/main/java/org/junit/Rule.java @@ -0,0 +1,101 @@ +package org.junit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates fields that reference rules or methods that return a rule. A field must be public, not + * static, and a subtype of {@link org.junit.rules.TestRule} (preferred) or + * {@link org.junit.rules.MethodRule}. A method must be public, not static, + * and must return a subtype of {@link org.junit.rules.TestRule} (preferred) or + * {@link org.junit.rules.MethodRule}. + *
+ * The {@link org.junit.runners.model.Statement} passed + * to the {@link org.junit.rules.TestRule} will run any {@link Before} methods, + * then the {@link Test} method, and finally any {@link After} methods, + * throwing an exception if any of these fail. If there are multiple + * annotated {@link Rule}s on a class, they will be applied in order of methods first, then fields. + * However, if there are multiple fields (or methods) they will be applied in an order + * that depends on your JVM's implementation of the reflection API, which is + * undefined, in general. Rules defined by fields will always be applied + * after Rules defined by methods, i.e. the Statements returned by the former will + * be executed around those returned by the latter. + * + *
+ * For example, here is a test class that creates a temporary folder before + * each test method, and deletes it after each: + *
+ * public static class HasTempFolder { + * @Rule + * public TemporaryFolder folder= new TemporaryFolder(); + * + * @Test + * public void testUsingTempFolder() throws IOException { + * File createdFile= folder.newFile("myfile.txt"); + * File createdFolder= folder.newFolder("subfolder"); + * // ... + * } + * } + *+ *
+ * And the same using a method. + *
+ * public static class HasTempFolder { + * private TemporaryFolder folder= new TemporaryFolder(); + * + * @Rule + * public TemporaryFolder getFolder() { + * return folder; + * } + * + * @Test + * public void testUsingTempFolder() throws IOException { + * File createdFile= folder.newFile("myfile.txt"); + * File createdFolder= folder.newFolder("subfolder"); + * // ... + * } + * } + *+ *
+ * For more information and more examples, see + * {@link org.junit.rules.TestRule}. + * + *
+ * You can use {@link #order()} if you want to have control over the order in + * which the Rules are applied. + * + *
+ * public class ThreeRules { + * @Rule(order = 0) + * public LoggingRule outer = new LoggingRule("outer rule"); + * + * @Rule(order = 1) + * public LoggingRule middle = new LoggingRule("middle rule"); + * + * @Rule(order = 2) + * public LoggingRule inner = new LoggingRule("inner rule"); + * + * // ... + * } + *+ * + * @since 4.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +public @interface Rule { + + int DEFAULT_ORDER = -1; + + /** + * Specifies the order in which rules are applied. The rules with a higher value are inner. + * + * @since 4.13 + */ + int order() default DEFAULT_ORDER; + +} diff --git a/src/main/java/org/junit/Test.java b/src/main/java/org/junit/Test.java new file mode 100644 index 000000000000..1db6fc7ab073 --- /dev/null +++ b/src/main/java/org/junit/Test.java @@ -0,0 +1,117 @@ +package org.junit; + +import org.junit.function.ThrowingRunnable; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The
Test
annotation tells JUnit that the public void
method
+ * to which it is attached can be run as a test case. To run the method,
+ * JUnit first constructs a fresh instance of the class then invokes the
+ * annotated method. Any exceptions thrown by the test will be reported
+ * by JUnit as a failure. If no exceptions are thrown, the test is assumed
+ * to have succeeded.
+ * + * A simple test looks like this: + *
+ * public class Example { + * @Test + * public void method() { + * org.junit.Assert.assertTrue( new ArrayList().isEmpty() ); + * } + * } + *+ *
+ * The Test
annotation supports two optional parameters for
+ * exception testing and for limiting test execution time.
+ *
+ *
+ * The parameter expected
declares that a test method should throw
+ * an exception. If it doesn't throw an exception or if it throws a different exception
+ * than the one declared, the test fails. For example, the following test succeeds:
+ *
+ * @Test(expected=IndexOutOfBoundsException.class) + * public void outOfBounds() { + * new ArrayList<Object>().get(1); + * } + *+ * + * Using the parameter
expected
for exception testing comes with
+ * some limitations: only the exception's type can be checked and it is not
+ * possible to precisely specify the code that throws the exception. Therefore
+ * JUnit 4 has improved its support for exception testing with
+ * {@link Assert#assertThrows(Class, ThrowingRunnable)} and the
+ * {@link org.junit.rules.ExpectedException ExpectedException} rule.
+ * With assertThrows
the code that throws the exception can be
+ * precisely specified. If the exception's message or one of its properties
+ * should be verified, the ExpectedException
rule can be used. Further
+ * information about exception testing can be found at the
+ * JUnit Wiki.
+ *
+ *
+ * The parameter timeout
causes a test to fail if it takes
+ * longer than a specified amount of clock time (measured in milliseconds). The following test fails:
+ *
+ * @Test(timeout=100) + * public void infinity() { + * while(true); + * } + *+ * Warning: while
timeout
is useful to catch and terminate
+ * infinite loops, it should not be considered deterministic. The
+ * following test may or may not fail depending on how the operating system
+ * schedules threads:
+ * + * @Test(timeout=100) + * public void sleep100() { + * Thread.sleep(100); + * } + *+ * THREAD SAFETY WARNING: Test methods with a timeout parameter are run in a thread other than the + * thread which runs the fixture's @Before and @After methods. This may yield different behavior for + * code that is not thread safe when compared to the same test method without a timeout parameter. + * Consider using the {@link org.junit.rules.Timeout} rule instead, which ensures a test method is run on the + * same thread as the fixture's @Before and @After methods. + * + * @since 4.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface Test { + + /** + * Default empty exception. + */ + static class None extends Throwable { + private static final long serialVersionUID = 1L; + + private None() { + } + } + + /** + * Optionally specify
expected
, a Throwable, to cause a test method to succeed if
+ * and only if an exception of the specified class is thrown by the method. If the Throwable's
+ * message or one of its properties should be verified, the
+ * {@link org.junit.rules.ExpectedException ExpectedException} rule can be used instead.
+ */
+ Class extends Throwable> expected() default None.class;
+
+ /**
+ * Optionally specify timeout
in milliseconds to cause a test method to fail if it
+ * takes longer than that number of milliseconds.
+ * + * THREAD SAFETY WARNING: Test methods with a timeout parameter are run in a thread other than the + * thread which runs the fixture's @Before and @After methods. This may yield different behavior for + * code that is not thread safe when compared to the same test method without a timeout parameter. + * Consider using the {@link org.junit.rules.Timeout} rule instead, which ensures a test method is run on the + * same thread as the fixture's @Before and @After methods. + *
+ */ + long timeout() default 0L; +} diff --git a/src/main/java/org/junit/TestCouldNotBeSkippedException.java b/src/main/java/org/junit/TestCouldNotBeSkippedException.java new file mode 100644 index 000000000000..4804493290ef --- /dev/null +++ b/src/main/java/org/junit/TestCouldNotBeSkippedException.java @@ -0,0 +1,19 @@ +package org.junit; + +/** + * Indicates that a test that indicated that it should be skipped could not be skipped. + * This can be thrown if a test uses the methods in {@link Assume} to indicate that + * it should be skipped, but before processing of the test was completed, other failures + * occured. + * + * @see org.junit.Assume + * @since 4.13 + */ +public class TestCouldNotBeSkippedException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** Creates an instance using the given assumption failure. */ + public TestCouldNotBeSkippedException(org.junit.internal.AssumptionViolatedException cause) { + super("Test could not be skipped due to other failures", cause); + } +} diff --git a/src/main/java/org/junit/experimental/ParallelComputer.java b/src/main/java/org/junit/experimental/ParallelComputer.java new file mode 100644 index 000000000000..97da0f759f48 --- /dev/null +++ b/src/main/java/org/junit/experimental/ParallelComputer.java @@ -0,0 +1,67 @@ +package org.junit.experimental; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.junit.runner.Computer; +import org.junit.runner.Runner; +import org.junit.runners.ParentRunner; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; +import org.junit.runners.model.RunnerScheduler; + +public class ParallelComputer extends Computer { + private final boolean classes; + + private final boolean methods; + + public ParallelComputer(boolean classes, boolean methods) { + this.classes = classes; + this.methods = methods; + } + + public static Computer classes() { + return new ParallelComputer(true, false); + } + + public static Computer methods() { + return new ParallelComputer(false, true); + } + + private static Runner parallelize(Runner runner) { + if (runner instanceof ParentRunner) { + ((ParentRunner>) runner).setScheduler(new RunnerScheduler() { + private final ExecutorService fService = Executors.newCachedThreadPool(); + + public void schedule(Runnable childStatement) { + fService.submit(childStatement); + } + + public void finished() { + try { + fService.shutdown(); + fService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + } catch (InterruptedException e) { + e.printStackTrace(System.err); + } + } + }); + } + return runner; + } + + @Override + public Runner getSuite(RunnerBuilder builder, java.lang.Class>[] classes) + throws InitializationError { + Runner suite = super.getSuite(builder, classes); + return this.classes ? parallelize(suite) : suite; + } + + @Override + protected Runner getRunner(RunnerBuilder builder, Class> testClass) + throws Throwable { + Runner runner = super.getRunner(builder, testClass); + return methods ? parallelize(runner) : runner; + } +} diff --git a/src/main/java/org/junit/experimental/categories/Categories.java b/src/main/java/org/junit/experimental/categories/Categories.java new file mode 100644 index 000000000000..0c73ed82afff --- /dev/null +++ b/src/main/java/org/junit/experimental/categories/Categories.java @@ -0,0 +1,375 @@ +package org.junit.experimental.categories; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.junit.runner.Description; +import org.junit.runner.manipulation.Filter; +import org.junit.runner.manipulation.NoTestsRemainException; +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; + +/** + * From a given set of test classes, runs only the classes and methods that are + * annotated with either the category given with the @IncludeCategory + * annotation, or a subtype of that category. + *+ * Note that, for now, annotating suites with {@code @Category} has no effect. + * Categories must be annotated on the direct method or class. + *
+ * Example: + *
+ * public interface FastTests { + * } + * + * public interface SlowTests { + * } + * + * public interface SmokeTests + * } + * + * public static class A { + * @Test + * public void a() { + * fail(); + * } + * + * @Category(SlowTests.class) + * @Test + * public void b() { + * } + * + * @Category({FastTests.class, SmokeTests.class}) + * @Test + * public void c() { + * } + * } + * + * @Category({SlowTests.class, FastTests.class}) + * public static class B { + * @Test + * public void d() { + * } + * } + * + * @RunWith(Categories.class) + * @IncludeCategory(SlowTests.class) + * @SuiteClasses({A.class, B.class}) + * // Note that Categories is a kind of Suite + * public static class SlowTestSuite { + * // Will run A.b and B.d, but not A.a and A.c + * } + *+ *
+ * Example to run multiple categories: + *
+ * @RunWith(Categories.class) + * @IncludeCategory({FastTests.class, SmokeTests.class}) + * @SuiteClasses({A.class, B.class}) + * public static class FastOrSmokeTestSuite { + * // Will run A.c and B.d, but not A.b because it is not any of FastTests or SmokeTests + * } + *+ * + * @version 4.12 + * @see Categories at JUnit wiki + */ +public class Categories extends Suite { + + @Retention(RetentionPolicy.RUNTIME) + public @interface IncludeCategory { + /** + * Determines the tests to run that are annotated with categories specified in + * the value of this annotation or their subtypes unless excluded with {@link ExcludeCategory}. + */ + Class>[] value() default {}; + + /** + * If true, runs tests annotated with any of the categories in + * {@link IncludeCategory#value()}. Otherwise, runs tests only if annotated with all of the categories. + */ + boolean matchAny() default true; + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface ExcludeCategory { + /** + * Determines the tests which do not run if they are annotated with categories specified in the + * value of this annotation or their subtypes regardless of being included in {@link IncludeCategory#value()}. + */ + Class>[] value() default {}; + + /** + * If true, the tests annotated with any of the categories in {@link ExcludeCategory#value()} + * do not run. Otherwise, the tests do not run if and only if annotated with all categories. + */ + boolean matchAny() default true; + } + + public static class CategoryFilter extends Filter { + private final Set
+ * public interface FastTests {} + * public interface SlowTests {} + * + * public static class A { + * @Test + * public void a() { + * fail(); + * } + * + * @Category(SlowTests.class) + * @Test + * public void b() { + * } + * } + * + * @Category({SlowTests.class, FastTests.class}) + * public static class B { + * @Test + * public void c() { + * + * } + * } + *+ * + * For more usage, see code example on {@link Categories}. + */ +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@ValidateWith(CategoryValidator.class) +public @interface Category { + Class>[] value(); +} \ No newline at end of file diff --git a/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java b/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java new file mode 100644 index 000000000000..e9bdab77e502 --- /dev/null +++ b/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java @@ -0,0 +1,51 @@ +package org.junit.experimental.categories; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.internal.Classes; +import org.junit.runner.FilterFactory; +import org.junit.runner.FilterFactoryParams; +import org.junit.runner.manipulation.Filter; + +/** + * Implementation of FilterFactory for Category filtering. + */ +abstract class CategoryFilterFactory implements FilterFactory { + /** + * Creates a {@link org.junit.experimental.categories.Categories.CategoryFilter} given a + * {@link FilterFactoryParams} argument. + * + * @param params Parameters needed to create the {@link Filter} + */ + public Filter createFilter(FilterFactoryParams params) throws FilterNotCreatedException { + try { + return createFilter(parseCategories(params.getArgs())); + } catch (ClassNotFoundException e) { + throw new FilterNotCreatedException(e); + } + } + + /** + * Creates a {@link org.junit.experimental.categories.Categories.CategoryFilter} given an array of classes. + * + * @param categories Category classes. + */ + protected abstract Filter createFilter(List
+ * --filter=org.junit.experimental.categories.ExcludeCategories=pkg.of.Cat1,pkg.of.Cat2
+ *
+ *
+ * Usage from API:
+ *
+ * new ExcludeCategories().createFilter(Cat1.class, Cat2.class);
+ *
+ */
+public final class ExcludeCategories extends CategoryFilterFactory {
+ /**
+ * Creates a {@link Filter} which is only passed by tests that are
+ * not categorized with any of the specified categories.
+ *
+ * @param categories Category classes.
+ */
+ @Override
+ protected Filter createFilter(List
+ * --filter=org.junit.experimental.categories.IncludeCategories=pkg.of.Cat1,pkg.of.Cat2
+ *
+ *
+ * Usage from API:
+ *
+ * new IncludeCategories().createFilter(Cat1.class, Cat2.class);
+ *
+ */
+public final class IncludeCategories extends CategoryFilterFactory {
+ /**
+ * Creates a {@link Filter} which is only passed by tests that are
+ * categorized with any of the specified categories.
+ *
+ * @param categories Category classes.
+ */
+ @Override
+ protected Filter createFilter(Listclass
.
+ *
+ * @return a {@link Result} describing the details of the test run and the failed tests.
+ */
+ public Result run(Class> testClass) {
+ return run(Request.aClass(testClass));
+ }
+
+ /**
+ * Run all the tests contained in request
.
+ *
+ * @param request the request describing tests
+ * @return a {@link Result} describing the details of the test run and the failed tests.
+ */
+ public Result run(Request request) {
+ return run(request, new JUnitCore());
+ }
+
+ /**
+ * Run all the tests contained in request
.
+ *
+ * This variant should be used if {@code core} has attached listeners that this
+ * run should notify.
+ *
+ * @param request the request describing tests
+ * @param core a JUnitCore to delegate to.
+ * @return a {@link Result} describing the details of the test run and the failed tests.
+ */
+ public Result run(Request request, JUnitCore core) {
+ core.addListener(history.listener());
+ return core.run(sortRequest(request).getRunner());
+ }
+
+ /**
+ * @return a new Request, which contains all of the same tests, but in a new order.
+ */
+ public Request sortRequest(Request request) {
+ if (request instanceof SortingRequest) {
+ // We'll pay big karma points for this
+ return request;
+ }
+ List+ * assertThat(testResult(HasExpectedException.class), isSuccessful()); + *+ */ +public class PrintableResult { + private Result result; + + /** + * The result of running JUnit on {@code type} + */ + public static PrintableResult testResult(Class> type) { + return testResult(Request.aClass(type)); + } + + /** + * The result of running JUnit on Request {@code request} + */ + public static PrintableResult testResult(Request request) { + return new PrintableResult(new JUnitCore().run(request)); + } + + /** + * A result that includes the given {@code failures} + */ + public PrintableResult(List
+ * assertThat(testResult(HasExpectedException.class), isSuccessful()); + *+ */ +public class ResultMatchers { + + /** + * Do not instantiate. + * @deprecated will be private soon. + */ + @Deprecated + public ResultMatchers() { + } + + /** + * Matches if the tests are all successful + */ + public static Matcher
+ * So, for example: + *
+ * @RunWith(Enclosed.class) + * public class ListTests { + * ...useful shared stuff... + * public static class OneKindOfListTest {...} + * public static class AnotherKind {...} + * abstract public static class Ignored {...} + * } + *+ */ +public class Enclosed extends Suite { + /** + * Only called reflectively. Do not use programmatically. + */ + public Enclosed(Class> klass, RunnerBuilder builder) throws Throwable { + super(builder, klass, filterAbstractClasses(klass.getClasses())); + } + + private static Class>[] filterAbstractClasses(final Class>[] classes) { + final List
+ * A DataPoint is only considered as a potential value for parameters for
+ * which its type is assignable. When multiple {@code DataPoint}s exist
+ * with overlapping types more control can be obtained by naming each DataPoint
+ * using the value of this annotation, e.g. with
+ * @DataPoint({"dataset1", "dataset2"})
, and then specifying
+ * which named set to consider as potential values for each parameter using the
+ * {@link org.junit.experimental.theories.FromDataPoints @FromDataPoints}
+ * annotation.
+ *
+ * Parameters with no specified source (i.e. without @FromDataPoints or + * other {@link org.junit.experimental.theories.ParametersSuppliedBy + * @ParameterSuppliedBy} annotations) will use all {@code DataPoint}s that are + * assignable to the parameter type as potential values, including named sets of + * {@code DataPoint}s. + * + *
+ * @DataPoint + * public static String dataPoint = "value"; + * + * @DataPoint("generated") + * public static String generatedDataPoint() { + * return "generated value"; + * } + * + * @Theory + * public void theoryMethod(String param) { + * ... + * } + *+ * + * @see org.junit.experimental.theories.Theories + * @see org.junit.experimental.theories.Theory + * @see org.junit.experimental.theories.DataPoint + * @see org.junit.experimental.theories.FromDataPoints + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({FIELD, METHOD}) +public @interface DataPoint { + String[] value() default {}; + Class extends Throwable>[] ignoredExceptions() default {}; +} \ No newline at end of file diff --git a/src/main/java/org/junit/experimental/theories/DataPoints.java b/src/main/java/org/junit/experimental/theories/DataPoints.java new file mode 100644 index 000000000000..b47461b388cd --- /dev/null +++ b/src/main/java/org/junit/experimental/theories/DataPoints.java @@ -0,0 +1,64 @@ +package org.junit.experimental.theories; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotating an array or iterable-typed field or method with @DataPoints + * will cause the values in the array or iterable given to be used as potential + * parameters for theories in that class when run with the + * {@link org.junit.experimental.theories.Theories Theories} runner. + *
+ * DataPoints will only be considered as potential values for parameters for
+ * which their types are assignable. When multiple sets of DataPoints exist with
+ * overlapping types more control can be obtained by naming the DataPoints using
+ * the value of this annotation, e.g. with
+ * @DataPoints({"dataset1", "dataset2"})
, and then specifying
+ * which named set to consider as potential values for each parameter using the
+ * {@link org.junit.experimental.theories.FromDataPoints @FromDataPoints}
+ * annotation.
+ *
+ * Parameters with no specified source (i.e. without @FromDataPoints or + * other {@link org.junit.experimental.theories.ParametersSuppliedBy + * @ParameterSuppliedBy} annotations) will use all DataPoints that are + * assignable to the parameter type as potential values, including named sets of + * DataPoints. + *
+ * DataPoints methods whose array types aren't assignable from the target + * parameter type (and so can't possibly return relevant values) will not be + * called when generating values for that parameter. Iterable-typed datapoints + * methods must always be called though, as this information is not available + * here after generic type erasure, so expensive methods returning iterable + * datapoints are a bad idea. + * + *
+ * @DataPoints + * public static String[] dataPoints = new String[] { ... }; + * + * @DataPoints + * public static String[] generatedDataPoints() { + * return new String[] { ... }; + * } + * + * @Theory + * public void theoryMethod(String param) { + * ... + * } + *+ * + * @see org.junit.experimental.theories.Theories + * @see org.junit.experimental.theories.Theory + * @see org.junit.experimental.theories.DataPoint + * @see org.junit.experimental.theories.FromDataPoints + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ FIELD, METHOD }) +public @interface DataPoints { + String[] value() default {}; + + Class extends Throwable>[] ignoredExceptions() default {}; +} diff --git a/src/main/java/org/junit/experimental/theories/FromDataPoints.java b/src/main/java/org/junit/experimental/theories/FromDataPoints.java new file mode 100644 index 000000000000..2b149cae9cf1 --- /dev/null +++ b/src/main/java/org/junit/experimental/theories/FromDataPoints.java @@ -0,0 +1,54 @@ +package org.junit.experimental.theories; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.experimental.theories.internal.SpecificDataPointsSupplier; + +/** + * Annotating a parameter of a {@link org.junit.experimental.theories.Theory + * @Theory} method with
@FromDataPoints
will limit the
+ * datapoints considered as potential values for that parameter to just the
+ * {@link org.junit.experimental.theories.DataPoints DataPoints} with the given
+ * name. DataPoint names can be given as the value parameter of the
+ * @DataPoints annotation.
+ * + * DataPoints without names will not be considered as values for any parameters + * annotated with @FromDataPoints. + *
+ * @DataPoints + * public static String[] unnamed = new String[] { ... }; + * + * @DataPoints("regexes") + * public static String[] regexStrings = new String[] { ... }; + * + * @DataPoints({"forMatching", "alphanumeric"}) + * public static String[] testStrings = new String[] { ... }; + * + * @Theory + * public void stringTheory(String param) { + * // This will be called with every value in 'regexStrings', + * // 'testStrings' and 'unnamed'. + * } + * + * @Theory + * public void regexTheory(@FromDataPoints("regexes") String regex, + * @FromDataPoints("forMatching") String value) { + * // This will be called with only the values in 'regexStrings' as + * // regex, only the values in 'testStrings' as value, and none + * // of the values in 'unnamed'. + * } + *+ * + * @see org.junit.experimental.theories.Theory + * @see org.junit.experimental.theories.DataPoint + * @see org.junit.experimental.theories.DataPoints + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@ParametersSuppliedBy(SpecificDataPointsSupplier.class) +public @interface FromDataPoints { + String value(); +} diff --git a/src/main/java/org/junit/experimental/theories/ParameterSignature.java b/src/main/java/org/junit/experimental/theories/ParameterSignature.java new file mode 100644 index 000000000000..cf225835e5b4 --- /dev/null +++ b/src/main/java/org/junit/experimental/theories/ParameterSignature.java @@ -0,0 +1,134 @@ +package org.junit.experimental.theories; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ParameterSignature { + + private static final Map
+ * For example, here is a supplier for values between two integers, and an annotation that references it: + * + *
+ * @Retention(RetentionPolicy.RUNTIME) + * @ParametersSuppliedBy(BetweenSupplier.class) + * public @interface Between { + * int first(); + * + * int last(); + * } + * + * public static class BetweenSupplier extends ParameterSupplier { + * @Override + * public List<PotentialAssignment> getValueSources(ParameterSignature sig) { + * List<PotentialAssignment> list = new ArrayList<PotentialAssignment>(); + * Between annotation = (Between) sig.getSupplierAnnotation(); + * + * for (int i = annotation.first(); i <= annotation.last(); i++) + * list.add(PotentialAssignment.forValue("ints", i)); + * return list; + * } + * } + *+ * + * + * @see org.junit.experimental.theories.ParametersSuppliedBy + * @see org.junit.experimental.theories.Theories + * @see org.junit.experimental.theories.FromDataPoints + */ +public abstract class ParameterSupplier { + public abstract List
+ * @ParametersSuppliedBy(Supplier.class) + * public @interface SpecialParameter { } + * + * @Theory + * public void theoryMethod(@SpecialParameter String param) { + * ... + * } + *+ * + * equivalent to: + * + *
+ * @Theory + * public void theoryMethod(@ParametersSuppliedBy(Supplier.class) String param) { + * ... + * } + *+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ANNOTATION_TYPE, PARAMETER }) +public @interface ParametersSuppliedBy { + + Class extends ParameterSupplier> value(); + +} diff --git a/src/main/java/org/junit/experimental/theories/PotentialAssignment.java b/src/main/java/org/junit/experimental/theories/PotentialAssignment.java new file mode 100644 index 000000000000..18ca07a4044d --- /dev/null +++ b/src/main/java/org/junit/experimental/theories/PotentialAssignment.java @@ -0,0 +1,52 @@ +package org.junit.experimental.theories; + +import static java.lang.String.format; + +public abstract class PotentialAssignment { + public static class CouldNotGenerateValueException extends Exception { + private static final long serialVersionUID = 1L; + + public CouldNotGenerateValueException() { + } + + public CouldNotGenerateValueException(Throwable e) { + super(e); + } + } + + public static PotentialAssignment forValue(final String name, final Object value) { + return new PotentialAssignment() { + @Override + public Object getValue() { + return value; + } + + @Override + public String toString() { + return format("[%s]", value); + } + + @Override + public String getDescription() { + String valueString; + + if (value == null) { + valueString = "null"; + } else { + try { + valueString = format("\"%s\"", value); + } catch (Throwable e) { + valueString = format("[toString() threw %s: %s]", + e.getClass().getSimpleName(), e.getMessage()); + } + } + + return format("%s
+ * A Theory is a piece of functionality (a method) that is executed against several data inputs called data points. + * To make a test method a theory you mark it with @Theory. To create a data point you create a public + * field in your test class and mark it with @DataPoint. The Theories runner then executes your test + * method as many times as the number of data points declared, providing a different data point as + * the input argument on each invocation. + *
+ *+ * A Theory differs from standard test method in that it captures some aspect of the intended behavior in possibly + * infinite numbers of scenarios which corresponds to the number of data points declared. Using assumptions and + * assertions properly together with covering multiple scenarios with different data points can make your tests more + * flexible and bring them closer to scientific theories (hence the name). + *
+ *+ * For example: + *
+ * + * @RunWith(Theories.class) + * public class UserTest { + * @DataPoint + * public static String GOOD_USERNAME = "optimus"; + * @DataPoint + * public static String USERNAME_WITH_SLASH = "optimus/prime"; + * + * @Theory + * public void filenameIncludesUsername(String username) { + * assumeThat(username, not(containsString("/"))); + * assertThat(new User(username).configFileName(), containsString(username)); + * } + * } + *+ * This makes it clear that the username should be included in the config file name, + * only if it doesn't contain a slash. Another test or theory might define what happens when a username does contain + * a slash.
UserTest
will attempt to run filenameIncludesUsername
on every compatible data
+ * point defined in the class. If any of the assumptions fail, the data point is silently ignored. If all of the
+ * assumptions pass, but an assertion fails, the test fails. If no parameters can be found that satisfy all assumptions, the test fails.
+ * + * Defining general statements as theories allows data point reuse across a bunch of functionality tests and also + * allows automated tools to search for new, unexpected data points that expose bugs. + *
+ *+ * The support for Theories has been absorbed from the Popper project, and more complete documentation can be found + * from that projects archived documentation. + *
+ * + * @see Archived Popper project documentation + * @see Paper on Theories + */ +public class Theories extends BlockJUnit4ClassRunner { + public Theories(Class> klass) throws InitializationError { + super(klass); + } + + /** @since 4.13 */ + protected Theories(TestClass testClass) throws InitializationError { + super(testClass); + } + + @Override + protected void collectInitializationErrors(List+ * @Theory + * public void shouldPassForSomeInts(@TestedOn(ints={1, 2, 3}) int param) { + * ... + * } + *+ */ +@ParametersSuppliedBy(TestedOnSupplier.class) +@Retention(RetentionPolicy.RUNTIME) +@Target(PARAMETER) +public @interface TestedOn { + int[] ints(); +} diff --git a/src/main/java/org/junit/experimental/theories/suppliers/TestedOnSupplier.java b/src/main/java/org/junit/experimental/theories/suppliers/TestedOnSupplier.java new file mode 100644 index 000000000000..dc3d0c9ce326 --- /dev/null +++ b/src/main/java/org/junit/experimental/theories/suppliers/TestedOnSupplier.java @@ -0,0 +1,25 @@ +package org.junit.experimental.theories.suppliers; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.experimental.theories.ParameterSignature; +import org.junit.experimental.theories.ParameterSupplier; +import org.junit.experimental.theories.PotentialAssignment; + +/** + * @see org.junit.experimental.theories.suppliers.TestedOn + * @see org.junit.experimental.theories.ParameterSupplier + */ +public class TestedOnSupplier extends ParameterSupplier { + @Override + public List
ArrayComparisonFailure
with an error text and the array's
+ * dimension that was not equal
+ *
+ * @param cause the exception that caused the array's content to fail the assertion test
+ * @param index the array position of the objects that are not equal.
+ * @see Assert#assertArrayEquals(String, Object[], Object[])
+ */
+ public ArrayComparisonFailure(String message, AssertionError cause, int index) {
+ this.fMessage = message;
+ this.fCause = cause;
+ initCause(fCause);
+ addDimension(index);
+ }
+
+ public void addDimension(int index) {
+ fIndices.add(0, index);
+ }
+
+ @Override
+ public synchronized Throwable getCause() {
+ return super.getCause() == null ? fCause : super.getCause();
+ }
+
+ @Override
+ public String getMessage() {
+ StringBuilder sb = new StringBuilder();
+ if (fMessage != null) {
+ sb.append(fMessage);
+ }
+ sb.append("arrays first differed at element ");
+ for (int each : fIndices) {
+ sb.append("[");
+ sb.append(each);
+ sb.append("]");
+ }
+ sb.append("; ");
+ sb.append(getCause().getMessage());
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getMessage();
+ }
+}
diff --git a/src/main/java/org/junit/internal/AssumptionViolatedException.java b/src/main/java/org/junit/internal/AssumptionViolatedException.java
new file mode 100644
index 000000000000..15c27af1b279
--- /dev/null
+++ b/src/main/java/org/junit/internal/AssumptionViolatedException.java
@@ -0,0 +1,111 @@
+package org.junit.internal;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.SelfDescribing;
+import org.hamcrest.StringDescription;
+
+/**
+ * An exception class used to implement assumptions (state in which a given test
+ * is meaningful and should or should not be executed). A test for which an assumption
+ * fails should not generate a test case failure.
+ *
+ * @see org.junit.Assume
+ */
+public class AssumptionViolatedException extends RuntimeException implements SelfDescribing {
+ private static final long serialVersionUID = 2L;
+
+ /*
+ * We have to use the f prefix until the next major release to ensure
+ * serialization compatibility.
+ * See https://github.com/junit-team/junit4/issues/976
+ */
+ private final String fAssumption;
+ private final boolean fValueMatcher;
+ private final Object fValue;
+ private final Matcher> fMatcher;
+
+ /**
+ * @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
+ */
+ @Deprecated
+ public AssumptionViolatedException(String assumption, boolean hasValue, Object value, Matcher> matcher) {
+ this.fAssumption = assumption;
+ this.fValue = value;
+ this.fMatcher = matcher;
+ this.fValueMatcher = hasValue;
+
+ if (value instanceof Throwable) {
+ initCause((Throwable) value);
+ }
+ }
+
+ /**
+ * An assumption exception with the given value (String or
+ * Throwable) and an additional failing {@link Matcher}.
+ *
+ * @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
+ */
+ @Deprecated
+ public AssumptionViolatedException(Object value, Matcher> matcher) {
+ this(null, true, value, matcher);
+ }
+
+ /**
+ * An assumption exception with the given value (String or
+ * Throwable) and an additional failing {@link Matcher}.
+ *
+ * @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
+ */
+ @Deprecated
+ public AssumptionViolatedException(String assumption, Object value, Matcher> matcher) {
+ this(assumption, true, value, matcher);
+ }
+
+ /**
+ * An assumption exception with the given message only.
+ *
+ * @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
+ */
+ @Deprecated
+ public AssumptionViolatedException(String assumption) {
+ this(assumption, false, null, null);
+ }
+
+ /**
+ * An assumption exception with the given message and a cause.
+ *
+ * @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
+ */
+ @Deprecated
+ public AssumptionViolatedException(String assumption, Throwable e) {
+ this(assumption, false, null, null);
+ initCause(e);
+ }
+
+ @Override
+ public String getMessage() {
+ return StringDescription.asString(this);
+ }
+
+ public void describeTo(Description description) {
+ if (fAssumption != null) {
+ description.appendText(fAssumption);
+ }
+
+ if (fValueMatcher) {
+ // a value was passed in when this instance was constructed; print it
+ if (fAssumption != null) {
+ description.appendText(": ");
+ }
+
+ description.appendText("got: ");
+ description.appendValue(fValue);
+
+ if (fMatcher != null) {
+ description.appendText(", expected: ");
+ description.appendDescriptionOf(fMatcher);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/junit/internal/Checks.java b/src/main/java/org/junit/internal/Checks.java
new file mode 100644
index 000000000000..9724947f9977
--- /dev/null
+++ b/src/main/java/org/junit/internal/Checks.java
@@ -0,0 +1,37 @@
+package org.junit.internal;
+
+/** @since 4.13 */
+public final class Checks {
+
+ private Checks() {}
+
+ /**
+ * Checks that the given value is not {@code null}.
+ *
+ * @param value object reference to check
+ * @return the passed-in value, if not {@code null}
+ * @throws NullPointerException if {@code value} is {@code null}
+ */
+ public static expecteds
and
+ * actuals
are null
, they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (
+ * null
okay)
+ * @param expecteds Object array or array of arrays (multi-dimensional array) with
+ * expected values.
+ * @param actuals Object array or array of arrays (multi-dimensional array) with
+ * actual values
+ */
+ public void arrayEquals(String message, Object expecteds, Object actuals)
+ throws ArrayComparisonFailure {
+ arrayEquals(message, expecteds, actuals, true);
+ }
+
+ private void arrayEquals(String message, Object expecteds, Object actuals, boolean outer)
+ throws ArrayComparisonFailure {
+ if (expecteds == actuals
+ || Arrays.deepEquals(new Object[] {expecteds}, new Object[] {actuals})) {
+ // The reflection-based loop below is potentially very slow, especially for primitive
+ // arrays. The deepEquals check allows us to circumvent it in the usual case where
+ // the arrays are exactly equal.
+ return;
+ }
+ String header = message == null ? "" : message + ": ";
+
+ // Only include the user-provided message in the outer exception.
+ String exceptionMessage = outer ? header : "";
+
+ if (expecteds == null) {
+ Assert.fail(exceptionMessage + "expected array was null");
+ }
+ if (actuals == null) {
+ Assert.fail(exceptionMessage + "actual array was null");
+ }
+
+ int actualsLength = Array.getLength(actuals);
+ int expectedsLength = Array.getLength(expecteds);
+ if (actualsLength != expectedsLength) {
+ header += "array lengths differed, expected.length="
+ + expectedsLength + " actual.length=" + actualsLength + "; ";
+ }
+ int prefixLength = Math.min(actualsLength, expectedsLength);
+
+ for (int i = 0; i < prefixLength; i++) {
+ Object expected = Array.get(expecteds, i);
+ Object actual = Array.get(actuals, i);
+
+ if (isArray(expected) && isArray(actual)) {
+ try {
+ arrayEquals(message, expected, actual, false);
+ } catch (ArrayComparisonFailure e) {
+ e.addDimension(i);
+ throw e;
+ } catch (AssertionError e) {
+ // Array lengths differed.
+ throw new ArrayComparisonFailure(header, e, i);
+ }
+ } else {
+ try {
+ assertElementsEqual(expected, actual);
+ } catch (AssertionError e) {
+ throw new ArrayComparisonFailure(header, e, i);
+ }
+ }
+ }
+
+ if (actualsLength != expectedsLength) {
+ Object expected = getToStringableArrayElement(expecteds, expectedsLength, prefixLength);
+ Object actual = getToStringableArrayElement(actuals, actualsLength, prefixLength);
+ try {
+ Assert.assertEquals(expected, actual);
+ } catch (AssertionError e) {
+ throw new ArrayComparisonFailure(header, e, prefixLength);
+ }
+ }
+ }
+
+ private static final Object END_OF_ARRAY_SENTINEL = objectWithToString("end of array");
+
+ private Object getToStringableArrayElement(Object array, int length, int index) {
+ if (index < length) {
+ Object element = Array.get(array, index);
+ if (isArray(element)) {
+ return objectWithToString(componentTypeName(element.getClass()) + "[" + Array.getLength(element) + "]");
+ } else {
+ return element;
+ }
+ } else {
+ return END_OF_ARRAY_SENTINEL;
+ }
+ }
+
+ private static Object objectWithToString(final String string) {
+ return new Object() {
+ @Override
+ public String toString() {
+ return string;
+ }
+ };
+ }
+
+ private String componentTypeName(Class> arrayClass) {
+ Class> componentType = arrayClass.getComponentType();
+ if (componentType.isArray()) {
+ return componentTypeName(componentType) + "[]";
+ } else {
+ return componentType.getName();
+ }
+ }
+
+ private boolean isArray(Object expected) {
+ return expected != null && expected.getClass().isArray();
+ }
+
+ protected abstract void assertElementsEqual(Object expected, Object actual);
+}
diff --git a/src/main/java/org/junit/internal/ExactComparisonCriteria.java b/src/main/java/org/junit/internal/ExactComparisonCriteria.java
new file mode 100644
index 000000000000..a267f7fe285d
--- /dev/null
+++ b/src/main/java/org/junit/internal/ExactComparisonCriteria.java
@@ -0,0 +1,10 @@
+package org.junit.internal;
+
+import org.junit.Assert;
+
+public class ExactComparisonCriteria extends ComparisonCriteria {
+ @Override
+ protected void assertElementsEqual(Object expected, Object actual) {
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/src/main/java/org/junit/internal/InexactComparisonCriteria.java b/src/main/java/org/junit/internal/InexactComparisonCriteria.java
new file mode 100644
index 000000000000..16e804b9450f
--- /dev/null
+++ b/src/main/java/org/junit/internal/InexactComparisonCriteria.java
@@ -0,0 +1,24 @@
+package org.junit.internal;
+
+import org.junit.Assert;
+
+public class InexactComparisonCriteria extends ComparisonCriteria {
+ public Object fDelta;
+
+ public InexactComparisonCriteria(double delta) {
+ fDelta = delta;
+ }
+
+ public InexactComparisonCriteria(float delta) {
+ fDelta = delta;
+ }
+
+ @Override
+ protected void assertElementsEqual(Object expected, Object actual) {
+ if (expected instanceof Double) {
+ Assert.assertEquals((Double) expected, (Double) actual, (Double) fDelta);
+ } else {
+ Assert.assertEquals((Float) expected, (Float) actual, (Float) fDelta);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/JUnitSystem.java b/src/main/java/org/junit/internal/JUnitSystem.java
new file mode 100644
index 000000000000..cf0f2c055243
--- /dev/null
+++ b/src/main/java/org/junit/internal/JUnitSystem.java
@@ -0,0 +1,14 @@
+package org.junit.internal;
+
+import java.io.PrintStream;
+
+public interface JUnitSystem {
+
+ /**
+ * Will be removed in the next major release
+ */
+ @Deprecated
+ void exit(int code);
+
+ PrintStream out();
+}
diff --git a/src/main/java/org/junit/internal/MethodSorter.java b/src/main/java/org/junit/internal/MethodSorter.java
new file mode 100644
index 000000000000..d8e661aa8824
--- /dev/null
+++ b/src/main/java/org/junit/internal/MethodSorter.java
@@ -0,0 +1,72 @@
+package org.junit.internal;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.junit.FixMethodOrder;
+
+public class MethodSorter {
+ /**
+ * DEFAULT sort order
+ */
+ public static final Comparator+ * try { + * doSomething(); + * } catch (Throwable e} { + * throw Throwables.rethrowAsException(e); + * } + * doSomethingLater(); + *+ * + * @param e exception to rethrow + * @return does not return anything + * @since 4.12 + */ + public static Exception rethrowAsException(Throwable e) throws Exception { + Throwables.
+ * If a runner supports inner member classes, the member classes will inherit the runner from the enclosing class, e.g.: + *
+ * @RunWith(MyRunner.class) + * public class MyTest { + * // some tests might go here + * + * public class MyMemberClass { + * @Test + * public void thisTestRunsWith_MyRunner() { + * // some test logic + * } + * + * // some more tests might go here + * } + * + * @RunWith(AnotherRunner.class) + * public class AnotherMemberClass { + * // some tests might go here + * + * public class DeepInnerClass { + * @Test + * public void thisTestRunsWith_AnotherRunner() { + * // some test logic + * } + * } + * + * public class DeepInheritedClass extends SuperTest { + * @Test + * public void thisTestRunsWith_SuperRunner() { + * // some test logic + * } + * } + * } + * } + * + * @RunWith(SuperRunner.class) + * public class SuperTest { + * // some tests might go here + * } + *+ * The key points to note here are: + *
Always returns an empty list.
+ */
+ public List Always throws an {@link UnsupportedOperationException}
+ */
+ public long getThreadCpuTime(long id) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Always returns false.
+ */
+ public boolean isThreadCpuTimeSupported() {
+ return false;
+ }
+
+}
+
diff --git a/src/main/java/org/junit/internal/management/ManagementFactory.java b/src/main/java/org/junit/internal/management/ManagementFactory.java
new file mode 100644
index 000000000000..5be1447532e9
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ManagementFactory.java
@@ -0,0 +1,77 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Reflective wrapper around {@link java.lang.management.ManagementFactory}
+ */
+public class ManagementFactory {
+ private static final class FactoryHolder {
+ private static final Class> MANAGEMENT_FACTORY_CLASS;
+
+ static {
+ Class> managementFactoryClass = null;
+ try {
+ managementFactoryClass = Classes.getClass("java.lang.management.ManagementFactory");
+ } catch (ClassNotFoundException e) {
+ // do nothing, managementFactoryClass will be none on failure
+ }
+ MANAGEMENT_FACTORY_CLASS = managementFactoryClass;
+ }
+
+ static Object getBeanObject(String methodName) {
+ if (MANAGEMENT_FACTORY_CLASS != null) {
+ try {
+ return MANAGEMENT_FACTORY_CLASS.getMethod(methodName).invoke(null);
+ } catch (IllegalAccessException e) {
+ // fallthrough
+ } catch (IllegalArgumentException e) {
+ // fallthrough
+ } catch (InvocationTargetException e) {
+ // fallthrough
+ } catch (NoSuchMethodException e) {
+ // fallthrough
+ } catch (SecurityException e) {
+ // fallthrough
+ }
+ }
+ return null;
+ }
+ }
+
+ private static final class RuntimeHolder {
+ private static final RuntimeMXBean RUNTIME_MX_BEAN =
+ getBean(FactoryHolder.getBeanObject("getRuntimeMXBean"));
+
+ private static final RuntimeMXBean getBean(Object runtimeMxBean) {
+ return runtimeMxBean != null
+ ? new ReflectiveRuntimeMXBean(runtimeMxBean) : new FakeRuntimeMXBean();
+ }
+ }
+
+ private static final class ThreadHolder {
+ private static final ThreadMXBean THREAD_MX_BEAN =
+ getBean(FactoryHolder.getBeanObject("getThreadMXBean"));
+
+ private static final ThreadMXBean getBean(Object threadMxBean) {
+ return threadMxBean != null
+ ? new ReflectiveThreadMXBean(threadMxBean) : new FakeThreadMXBean();
+ }
+ }
+
+ /**
+ * @see java.lang.management.ManagementFactory#getRuntimeMXBean()
+ */
+ public static RuntimeMXBean getRuntimeMXBean() {
+ return RuntimeHolder.RUNTIME_MX_BEAN;
+ }
+
+ /**
+ * @see java.lang.management.ManagementFactory#getThreadMXBean()
+ */
+ public static ThreadMXBean getThreadMXBean() {
+ return ThreadHolder.THREAD_MX_BEAN;
+ }
+}
diff --git a/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java b/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
new file mode 100644
index 000000000000..289587a44776
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
@@ -0,0 +1,61 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Implementation of {@link RuntimeMXBean} using the JVM reflectively.
+ */
+final class ReflectiveRuntimeMXBean implements RuntimeMXBean {
+ private final Object runtimeMxBean;
+
+ private static final class Holder {
+ private static final Method getInputArgumentsMethod;
+ static {
+ Method inputArguments = null;
+ try {
+ Class> threadMXBeanClass = Classes.getClass("java.lang.management.RuntimeMXBean");
+ inputArguments = threadMXBeanClass.getMethod("getInputArguments");
+ } catch (ClassNotFoundException e) {
+ // do nothing, input arguments will be null on failure
+ } catch (NoSuchMethodException e) {
+ // do nothing, input arguments will be null on failure
+ } catch (SecurityException e) {
+ // do nothing, input arguments will be null on failure
+ }
+ getInputArgumentsMethod = inputArguments;
+ }
+ }
+
+ ReflectiveRuntimeMXBean(Object runtimeMxBean) {
+ super();
+ this.runtimeMxBean = runtimeMxBean;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public Listrequest
+ */
+ public FilterRequest(Request request, Filter filter) {
+ this.request = request;
+ this.fFilter = filter;
+ }
+
+ @Override
+ public Runner getRunner() {
+ try {
+ Runner runner = request.getRunner();
+ fFilter.apply(runner);
+ return runner;
+ } catch (NoTestsRemainException e) {
+ return new ErrorReportingRunner(Filter.class, new Exception(String
+ .format("No tests found matching %s from %s", fFilter
+ .describe(), request.toString())));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/requests/MemoizingRequest.java b/src/main/java/org/junit/internal/requests/MemoizingRequest.java
new file mode 100644
index 000000000000..191c23022536
--- /dev/null
+++ b/src/main/java/org/junit/internal/requests/MemoizingRequest.java
@@ -0,0 +1,30 @@
+package org.junit.internal.requests;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+
+abstract class MemoizingRequest extends Request {
+ private final Lock runnerLock = new ReentrantLock();
+ private volatile Runner runner;
+
+ @Override
+ public final Runner getRunner() {
+ if (runner == null) {
+ runnerLock.lock();
+ try {
+ if (runner == null) {
+ runner = createRunner();
+ }
+ } finally {
+ runnerLock.unlock();
+ }
+ }
+ return runner;
+ }
+
+ /** Creates the {@link Runner} to return from {@link #getRunner()}. Called at most once. */
+ protected abstract Runner createRunner();
+}
diff --git a/src/main/java/org/junit/internal/requests/OrderingRequest.java b/src/main/java/org/junit/internal/requests/OrderingRequest.java
new file mode 100644
index 000000000000..441e595a3680
--- /dev/null
+++ b/src/main/java/org/junit/internal/requests/OrderingRequest.java
@@ -0,0 +1,29 @@
+package org.junit.internal.requests;
+
+import org.junit.internal.runners.ErrorReportingRunner;
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.InvalidOrderingException;
+import org.junit.runner.manipulation.Ordering;
+
+/** @since 4.13 */
+public class OrderingRequest extends MemoizingRequest {
+ private final Request request;
+ private final Ordering ordering;
+
+ public OrderingRequest(Request request, Ordering ordering) {
+ this.request = request;
+ this.ordering = ordering;
+ }
+
+ @Override
+ protected Runner createRunner() {
+ Runner runner = request.getRunner();
+ try {
+ ordering.apply(runner);
+ } catch (InvalidOrderingException e) {
+ return new ErrorReportingRunner(ordering.getClass(), e);
+ }
+ return runner;
+ }
+}
diff --git a/src/main/java/org/junit/internal/requests/SortingRequest.java b/src/main/java/org/junit/internal/requests/SortingRequest.java
new file mode 100644
index 000000000000..77061da27d5c
--- /dev/null
+++ b/src/main/java/org/junit/internal/requests/SortingRequest.java
@@ -0,0 +1,25 @@
+package org.junit.internal.requests;
+
+import java.util.Comparator;
+
+import org.junit.runner.Description;
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Sorter;
+
+public class SortingRequest extends Request {
+ private final Request request;
+ private final Comparator