question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Intruduce BiMatcher hierarchy

See original GitHub issue

A good feature would be introducing BiMatcher hierarchy (analog of org.hamcrest.Matcher, but consuming 2 args). Alternatively standard Comparator can be used for this purpose. Also BiPredicate can be used (this will tie JUnit to Java-8, but will add out-of-the-box AND/OR/NOT logic). A couple of notes for all further code:

  • BiMatcher, BiPredicate and Comparator names will be used interchangeably.
  • All the code is not final and just a general idea.

Main methods to add in Assert class:

  • assertThat(T expected, T actual, Comparator<T> biMatcher);
  • assertThat(String message, T expected, T actual, Comparator<T> biMatcher); (maybe not necessary, see below).
  • Multiple assertArray() methods (see below).

The motivation: sometimes you need to do a lot of similar checks against batch of objects. Existing functionality allows it, but with a lot of additional code (loops and conditions). With Comparator it can be done with less code and with higher flexibility.

Real example (from which I actually started to think about this feature): need to test all objects in the array are the same or not the same (depending on a boolean flag).

With current JUnit abilities it will look like: shorter:

for (int i = 0; i < elements.length - 1; i++) {
  if (checkSame) { // Same
    assertSame("elements must be the same.", elements[i], elements[i + 1]);
  } else { // Not same
    assertNotSame("elements must be not the same.", elements[i], elements[i + 1]);
  }
}

better performance (but who cares about performance in tests):

if (checkSame) { // Same
  for (int i = 0; i < elements.length - 1; i++) {
    assertSame("elements must be the same.", elements[i], elements[i + 1]);
  }
else { // Not same
  for (int i = 0; i < elements.length - 1; i++) {
    assertNotSame("elements must be not the same.", elements[i], elements[i + 1]);
  }
}

Also we can implement own Comparator and use assertTrue()/assertFalse(), but the code for creating comparators will also be big (unless we use lambdas).

With new approach code will look much shorter and cleaner as for me, like this:

Comparator<T> comparator = checkSame ? BiMatchers.same() : BiMatchers.notSame();
String message = checkSame ? "elements must be the same." : "elements must be not the same.";
for (int i = 0; i < elements.length - 1; i++) {
  assertThat(message, elements[i], elements[i + 1], comparator);
}

To make it even shorter, we can extend Comparator to MessagedComparator with optional message property, so JUnit will take it from there somehow. Like this:

MessagedComparator<T> comparator = checkSame ? BiMatchers.same("elements must be the same.") : BiMatchers.notSame("elements must be not the same.");
for (int i = 0; i < elements.length - 1; i++) {
  assertThat(message, elements[i], elements[i + 1], comparator);
}

Consequences are very far-reaching:

  1. The Assert class will be very flexible in general, because you can use any standard or own comparator without much code.
  2. As a result of previous, lambdas can be used more easily to inject any conditions.
  3. Additional logic cascading (AND, OR, NOT) can be added out-of-the-box (something similar to org.hamcrest.CoreMatchers). Currently for any new mini-feature a new method required, e.g. assertNotSame() next to assertSame() etc. Or again we need assertTrue()/assertFalse() methods.
  4. The whole Assert class can be refactored to unified form. Just one example:
public static void assertSame(String message, Object expected, Object actual) {
  assertThat(message, expected, actual, BiMatchers.same())
}

public static void assertThat(String message, T expected, T actual, Comparator<T> biMatcher) {
...
}

or as already mentioned:

public static void assertSame(String message, Object expected, Object actual) {
  assertThat(expected, actual, BiMatchers.same(message))
}

public static void assertThat(T expected, T actual, MessagedComparator<T> biMatcher) {
...
}
  1. assertArray() methods can be added (thus old methods refactored). E.g.:
public static void assertArrayEquals(boolean[] expecteds, boolean[] actuals) {
  assertArray(expecteds, actuals, BiMatchers.equals());
}

public static void assertArray(boolean[] expecteds, boolean[] actuals, Comparator<Boolean>) {
...
}

So for example you can check all elements in 2 arrays are same as easy as:

Assert.assertArray(array1, array2, BiMatchers.same());

Also array-length or other checks can be controlled separately. Pseudocode:

Assert.assertArray(array1, array2, and(sameLength(), same()));

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:9 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
kcooneycommented, Feb 9, 2018

@gitIvanB JUnit’s philosophy is to provide a good, extensible framework for writing tests for Java in Java. Being an extensible framework, we often see other open source projects extend the framework and/or provide rich testing libraries that can be used with JUnit.

For assertions, there are several projects that provide a richer set of assertions, sometimes in a way that is extensible. For example, there is Google Truth (https://github.com/google/truth), FEST (https://github.com/alexruiz/fest-assert-2.x), AssertJ (http://joel-costigliola.github.io/assertj/) and Hamcrest (http://hamcrest.org/JavaHamcrest/).

Because there are so many amazing assertion libraries out there I have been reluctant to accept new feature requests for org.junit.Assert. I wouldn’t consider it frozen (though I would consider junit.framework.Assert frozen). In fact, 4.13 will introduce assertThrows. But since we will never have as rich a set of assertions as those projects we feel comfortable providing the basics.

Put another way, heathy communities have formed around the use and maintenance of those projects, so I think we should embrace and support them.

I can’t speak for JUnit5, but I imagine the original developers felt they couldn’t release the next generation of JUnit without a good foundation of assertion methods (or perhaps they felt like the best way to ensure that the new framework was functional and polished was to test JUnit5 using JUnit5). New programming practices caused them to make different decisions on what a basic assertion API would look like than Kent, Erich and David did, so you will see some differences. But you will likely never see in JUnit as rich a set of assertions as with Hamcrest or an extensible DSL like Truth.

I leave it to the JUnit5 team to decide what types of changes they will consider. If you feel strongly that the methods you are proposing are important as a foundation of writing good tests feel free to create an issue there.

1reaction
marcphilippcommented, Feb 8, 2018

@gitIvanB Thanks for opening the issue. Like @kcooney, I also think this would best be addressed by an assertion library, e.g. AssertJ.

Read more comments on GitHub >

github_iconTop Results From Across the Web

An Introduction to Hierarchy - Web Design TutsPlus
Ensuring that your designs present a clear hierarchy is very important, and something that you should aim for in every one of your...
Read more >
Hierarchy - Wikipedia
A hierarchy is an arrangement of items that are represented as being "above", "below", or "at the same level as" one another. Hierarchy...
Read more >
Harmonizing Full and Partial Matching in Geospatial ... - MDPI
Thirdly, existing conflation models may introduce conflicting directional matches. This paper presents a new model that captures both full and partial ...
Read more >
Whoosh Documentation - Read the Docs
Added functionality to index and search hierarchical documents. ... Introduction to Whoosh ... BiMatcher (class in whoosh.matching), 137.
Read more >
Improving and Measuring the Effectiveness of Decision Analysis
This chapter discusses how to re-establish the connection between the disciplines in two ... Decision Maker; Analytic Hierarchy Process; Decision Analysis ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found