Expressive Java utilities from ayeseeem.org. Designed to make code clearer.
For help with dates and times, see spectime
.
Use static imports and you can write like this:
List<Month> latinNumberedPeriod = listOf(SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER);
Set<Month> latinNumberedMonths = setOf(SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER);
Use listOf()
instead of Arrays.asList()
. There was no equivalent for
setOf()
.
If you want to emphasize the nature of the collection, you can use
unmodifiableListOf()
and unmodifiableSetOf()
.
These are like Java's Collections.unmodifiableList()
, and
Collections.unmodifiableSet()
, but they take varargs, not a collection.
There are modifiable equivalents: modifiableListOf()
and modifiableSetOf()
.
If you want an empty list, use emptyList()
, which is clearer than writing
listOf()
with no arguments.
If modifiability is significant, use initiallyEmptyList()
or
alwaysEmptyList()
.
There are set equivalents: emptySet()
, initiallyEmptySet()
, and
alwaysEmptySet()
.
Now with Java 9+ you can now use List.of()
and Set.of()
, so perhaps some of these
are no longer needed. But note that the details of mutability and modifiability
might be different.
(See
ListSupport.java
,
SetSupport.java
,
ListSupportExamplesTest.java
,
and
SetSupportExamplesTest.java
for more details.
)
Clearer ways of expressing why you have chosen a particular Map
implementation. Which expresses more clearly and directly what is being done?:
supportedCodes = keySortedMap();
latestCodes = insertionOrderedMap();
supportedCodes = new TreeMap<>(); // key-sorted
latestCodes = new LinkedHashMap<>(); // insertion-ordered
(See
MapSupport.java
and
MapSupportExamplesTest.java
for more details.
)
Use firstOf(list)
and lastOf(list)
to get the first and last item of a list,
wrapped as an Optional
, by analogy with Java Stream's findFirst()
.
See
ListSupport.java
for more details.
Allows clearer, more expressive if
statements testing whether an item is in a
group of items. Which of these do you prefer? Which expresses more clearly
and directly what is being asked?:
if (the(month).isOneOf(SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER) {
// its name derives from its Latin ordinal in the Roman calendar
}
if (Arrays.asList(SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER).contains(month)) {
// ...
}
if (the(month).isIn(myFavouriteMonths) {
// ...
}
if (myFavouriteMonths.contains(month)) {
// ...
}
Note that this can also be used to avoid certain types of errors that are hard
to spot, often caused by copy-and-paste with repeated tests in long if
statements. For example, you can replace the (broken)
if (longComplicatedlyNamedThing1 == 1 || longComplicatedlyNamedThing2 == 3 || longComplicatedlyNamedThing1 == 7)
with the less error-prone
if (the(longComplicatedlyNamedThing1).isOneOf(1, 3, 7))
Although this appears to sacrifice the "short-circuit" behaviour of ||
,
List.contains()
presumably acts similarly, at least if the values are simple
values, not expressions to be evaluated.
Works for a Collection
, an array of objects, or individual items listed
directly (using varargs).
See
ContainedItem.java
and
ContainedItemExamplesTest.java
for more details.
Marks unit tests (whole test classes, or individual test methods) as characterization tests. That is, tests that characterize (capture, or describe, or document) the behaviour of the code, but without necessarily specifying the behaviour. For example,
@Characterization
@Test
public void testDefaultResponseIsNull() {
// ...
}
Note that a reason can be specified if wanted (using the value
attribute,
which does not need to be specified explicitly):
@Characterization("Currently null not empty - don't know why")
@Test
public void testDefaultResponse() {
assertThat(defaultResponse, is(nullValue()));
}
See
Characterization.java
for more details.
Write a characterization test that both shows what the current behaviour is, and what it should be. If the behaviour is ever corrected, the test will start failing, highlighting the fix, so you can consider the implications.
For example, instead of writing
assertThat(findBooks("unknown author"),
is(nullValue())); // should be empty
you can write
assertThat(findBooks("unknown author"),
ideally(is(empty()))
.butCurrently(is(nullValue())));
The terms "ideally" and "currently" are chosen to be expressive, and to avoid confusion with the terms "expected" and "actual" that are used in normal tests.
See
CharacterizationMatcher.java
and
CharacterizationMatcherExampleTest.java
for more details.
-
Extend methods: allow
listOf(aCollection, andItem1, andItem2)
and similar forsetOf()
. -
Helpers
- Is there a way to write a helper that has no JUnit dependency, so our code is dependency free? Is it worth it - we use JUnit for our tests anyway, so live with it?
-
"Test Invariant": repeat an action until some invariant is true - for example, year is the same before and after - and then use the result in a test?
- Something like
do(...).until(...).isConstant().then(...)
ordo(...).until(...).then(...)
. Something like this:
do( before = now(); result = getThing(); after = now(); ).until( before.year == after.year; ).then( assertThat(result.year, is(after.year)); );
do( result1 = getTime(); result2 = getTime(); ).until( now().year ).isConstant().then( assertThat(result1.year, is(result2.year)); );
- Something like
Basic standard is icm-java-style.