Re: Decoupling JUnit and Hamcrest

"[email protected] [junit]" <[email protected]> 12 Jan 2015 15:20:54 -0800
Newsgroups gmane.comp.java.junit.user
Message-ID <[email protected]>
Hi.  Nat Pryce here... 

 I'm hoping that the hamcrest-junit project will be able to alleviate the risks you (rightly) are worried about.  In fact that's why we're writing it.
 

 Some background...
 

 Hamcrest offers three levels of API:
 

 1) An API used by libraries that want to parametrise behaviour by a predicate and be able to describe failed matches (the Matcher interface and StringDescription class).
 2) An API used to implement new Matchers (various abstract classes that implement Matcher)
 3) A library of compositional matchers, and syntactic sugar (factory functions) for making expressions that compose matchers easy to read.
 

 API 1 has been very stable.  Since it was defined in 2001 (or thereabouts) it has been changed twice: repackaged when factored out of jMock and gained the describeMismatch method on the Matcher interface. Thanks to API 2 we were able to add the describeMismatch method without breaking code that implemented Matcher.  API 3 has been much more volatile, due to some historical poor design decisions and mistakes about generic type bounds.  We want to change the library and deprecate/delete badly defined matchers, and reorganise matchers for collections, strings, etc. into a more consistent structure.
 

 JUnit uses all three APIs.  It calls out to API 1 in the assertThat and assumeThat methods. It stores a reference to a Matcher in the AssumptionViolatedException. It uses API 2 to define its own matcher classes. And it uses matchers from API 3 internally.
 

 The hamcrest-junit library reduces coupling between Hamcrest and JUnit.  It only uses public JUnit classes and it doesn't pass any Hamcrest types to those classes (only Strings).  JUnit's public API has been very stable over the years, and hamcrest-junit should therefore remain compatible with future versions of JUnit 4 with no further changes.
 

 So the main worry is the compatibility with future versions of Hamcrest.  Similarly, I plan to reduce how much hamcrest-junit uses API 3 & 2 and try to use mostly the Matcher interface.
 

 If JUnit then removes hamcrest from its internal implementation, then hopefully we end up with two libraries that can work together, but with a much smaller, more stable interface between them.
 

 As soon as it is required (when Hamcrest 2.0.0.0-RC1 or JUnit-4.13 is released) I intend to set up a Travis build matrix to report compatibility among hamcrest, and junit versions.
 

---In [email protected], <stefan@...> wrote :

 Hi,
 
 I'm not a developer of junit nor hamcrest and I don't feel the pain of the tight integration of junit and hamcrest that "prevents both from moving on" but I'm a heavy user of both.
 I don't think it's a good idea to separate the hamcrest integration from junit into it's own library.
 
 At the moment JUnit dictates the hamcrest version to be used but also guarantees compatibility with this version.
 With the new library hamcrest developers will dictate the junit version that is compatible with a specific hamcrest release. This is only a change in responsibility but has no benefits.
 
 Of course there is also the opportunity to provide a broader range of compatible versions. But this opportunity also means more work for the maintainers and slower adoption by users. JUnit 4.12 uses hamcrest 1.3. What if JUnit moves on to 4.13, 4.14 and hamcrest releases 2.0 and 2.1 respectively. Will there be a version which is compatible with hamcrest 2.1 and JUnit 4.13? Will there be a version which is compatible with JUnit 4.14 and hamcrest 1.3?
 
 As a developer who want's to use JUnit 4.14 - how do I know which hamcrest-junit-integration version to use? What will stop me from using a wrong version? For example I might be tempted to update JUnit to 4.14 but forget to update hamcrest-junit-integration. There might be changes of the behaviour of JUnit that might cause some of my tests to pass always although they should fail. On the other hand: JUnit 4.14 might be binary incompatible to JUnit 4.12 - where to look for the right version of hamcrest-junit-integration?
 
 If hamcrest moves on to 2.0 - which could be binary incompatible to 1.3 due to the major version change (haven't checked) - how long will hamcrest 1.3 be supported with latest JUnit versions by hamcrest-junit-integration? I'm asking because we also use JMock which depends on hamcrest as well. If I update to an incompatible 2.0 I need also an update of JMock....
 (( Actually I cannot update JMock without big effort because there was an incompatible change from 2.5.1 to 2.6 .... ))
 
 On the other hand this will slow down speed for adoption of new JUnit versions because we have to wait until a new hamcrest-junit-integration version is out or at least someone has built the appropriate version with latest JUnit release and verified unit tests are still passing. It will also increase the effort necessary to try JUnit release candidates or snapshots in real projects (because I also have to checkout and build the integration library myself to be sure there is no problem with that... and if there is a problem I need to fix it myself or stop using latest JUnit release candidate).
 
 ----
 IMHO decoupling JUnit and hamcrest has more drawbacks than benefits. Although I see it can be a chance for hamcrest to move on. I don't think JUnit as a project will profit that much. JUnit users might have a broader choice of compatible hamcrest versions but this requires some effort (of the maintainers of hamcrest-junit-integration). I think this might only work well for JUnit users if the JUnit team commits to that integration project and is able to push out new releases of the hamcrest-junit-integration together with new JUnit releases.
 
 
 Regards,
 Stefan
 
 
 Am 07.01.2015 um 08:31 schrieb Stefan Birkner mail@... mailto:mail@... [junit]:

   FYI: Nat Pryce took a first step for decoupling JUnit and Hamcrest:
 http://natpryce.com/articles/000806.html http://natpryce.com/articles/000806.html