Comments (13)
more assertion libs to compare with:
from truth.
Dumping a couple scraps of information:
First, on multiplatform:
KMP support
No KMP support
Second, a series (still in progress) that compares Kotlin assertion libraries:
from truth.
Hey everyone, I did an analysis a while ago comparing some of the assertion libraries that could be used in Kotlin projects. Browsing on GitHub I was surprised to see that this is exactly what people in this thread are looking for π
Here is the repository link. I was not as granular as @cpovirk in some topics, but hope you can find something useful there.
from truth.
I should note that I've been ignoring HamKrest for some of the reasons discussed in https://truth.dev/comparison#vs-hamcrest. Mainly, I still worry about its less effective autocompletion. My second possible concern would be that the failure messages may still be complex, but it's possible that that's been improved, and I haven't checked. The one concern that doesn't carry over is that, as the HamKrest site notes, generics for Matcher
types work better in Kotlin than in Java: "Kotlin's type system means that developers don't have to worry about getting the variance of generic signatures right."
On that note: I got worried because I saw Kotest assertions written in a Hamcrest style: message should contain("foo")
, with the expected poor autocompletion. However, Kotest also supports message shouldContain "foo"
: The Matcher
style is merely an additional option, similar to what's provided by AssertJ and probably numerous Kotlin libraries.
from truth.
It's also worth noting (though veering slightly off-topic) that the built-in kotlin.test provides a richer set of assertion functions than some of us are used to from the JUnit 4 world (and probably even the JUnit 5 world, since the JUnit 5 developers are trying not to go too far down the road of providing assertions).
from truth.
More scattered thoughts from looking into parts of the "KMP support" libraries:
Assertions as extension methods
I confirmed that assertions are implemented with extension methods. (For AssertK and Atrium, you define the extension on Assert<Foo>
or Expect<Foo>
; for Kotest, you define it on Foo
.) This is what I had assumed that Kotlin libraries would do, and it unlocks some fun like assertThat(futureOfOptionalOfMyProto).result().value().longitude().isWithin(...).of(...)
that Java can't support.
[edit: I should note that Kotest does seem to nudge people toward the Hamcrest-style Matcher
approach, even as it obviously still supports the more autocomplete-friendly style on top of that.]
Failure messages
The only one that immediately concerned me was the Kotest failure message...
java.lang.AssertionError: Map should contain key x
...with no information about the map contents. On the one hand, this is easily fixable. On the other hand, Kotest has been around a while, and no one has fixed it yet. And if the easiest way to produce a failure message is the way that omits the value under test, then I imagine this isn't the only such failure message in Kotest, and authors of custom assertions are likely to fall into the same trap.
At the opposite side of the spectrum, we have these Atrium examples. I applaud the inclusion of lots of information, but several lines with information like (kotlin.Int <1234789>)
is a bit much for a simple "What does this Iterable
contain?" assertion.
Docs
AssertK and Kotest look pretty reasonable at first glance. Atrium is kind of scary:
val <E, T> IterableLikeContains.EntryPointStep<E, T, InAnyOrderSearchBehaviour>.only: IterableLikeContains.EntryPointStep<E, T, InAnyOrderOnlySearchBehaviour>
Defines that the constraint "only the specified entries exist in the IterableLike" shall be applied to this sophisticated contains IterableLike assertion.
But to be fair, the bigger question is what the experience of using these is like in an IDE, since an IDE is (from what I hear) basically a necessity for writing significant Kotlin already.
Evolution
I wonder if the biggest concern is going to be how the various libraries are maintained over time.
First, of course, we want them simply to be maintained :) The 3 I've been looking at have all been around at least a few years, so that's encouraging. All have one dominant contributor, but it's most extreme with Atrium (vs. AssertK, Kotest). We might also look to current popularity. Based just on GitHub watches/stars/forks, I see Kotest well above AssertK and Atrium. It's worth noting that Kotest offers more than just assertions, so that doesn't mean that Kotest assertions are getting a ton of specific attention, just that the project is (hopefully) less likely to be abandoned.
Another thing to watch for is breaking changes. Yes, we have been known to make breaking changes, we see value in making them judiciously, and we have tools to keep up with them. Still, we might not want to build our own extensions on an ecosystem that is changing a lot, since our users might not be in the same position.
- Atrium seems very much pre-1.0, so it may be a little early to adopt it unless you're up for that. (Conversely, if you're looking for a project to deeply influence, it might be a good pick for the same reason!)
- AssertK is also pre-1.0 but seems much less in flux.
- Kotest has had some multiple major releases (and has removed APIs in minor releases, like 3.3.0), but my impression is that it may be the most stable at this point. [edit: Or maybe not: I see a report that it relies on experimental/unstable APIs and thus breaks during Kotlin upgradesβthough it sounds like the owners are trying to avoid that nowadays.]
I wish people didn't have a method named "containsAll"
...given our experience with that method. But AssertK and Kotest both do, and Atrium has a varargs contains
method that sounds like it will lead to the same mistakes :(
from truth.
Anyway:
- This thread is not nominally about "What should I do if I want something like Truth but for KMP?"
- I have written zero lines of code using any of the assertion libraries here.
So no one should take the following too seriously. But if you have no idea which to pick and you're going to try one first, I'm kind of liking my early impression of AssertK:
- Atrium looks like it's still in flux, its APIs look a bit complex, and it looks committed to some failure messages that are too detailed for my taste.
- Kotest looks more stable, but the "Map should contain key x" failure message concerns me, and I worry that we'll see autocomplete-unfriendly Hamcrest-style
Matcher
objects mixed in with the extension functions.
AssertK, while probably still a bit in flux itself and arguably lacking the API coverage of Kotest (but that claim seems out of date, as I see assertions for Optional
and for floating-point numbers), looks likely to be stable "enough" and looks most likely to be helpful when your tests fail and you really need the help.
As a more conservative alternative, it sounds like the built-in kotlin.test assertions will get you pretty far, too, with failure messages that likely contain what you need to know but without AssertK's nicer formatting.
I'd be happy to hear about others' hands-on experiences, especially if there are features that could translate well to Truth or important features that just can't translate to Truth.
from truth.
One thing that's not entirely clear to me is how well the various libraries support collection assertions:
AssertK:
- doesn't have
containsExactly
on aMap
(though that sounds easy enough to add) - doesn't have
containsExactlyElementsIn
-style (i.e.,Iterable
-accepting) methods (aside fromcontainsSubList
, an unusual case) -- though there looks to be a relevant feature request that lays out some of the design questions
Kotest:
- also essentially doesn't have
containsExactlyElementsIn
-style methods, with exceptions for unusual casesshouldContainInOrder
,shouldStartWith
,shouldEndWith
, andshouldContainAnyOf
Atrium probably offers a lot ("sophisticated contains assertions"), though I noted my worry about complexity.
Anyway: Maybe the theory for the containsExactlyElementsIn
family is that you just use isEqualTo
/shouldBe
? I wonder if people find that option as easily, though. I also wonder if the failure messages are as good as the failure messages for collection-specific assertions.
from truth.
I like the assertAll {}
block that AssertK offers. It reports all assertion failures, not just the first one that fails.
from truth.
and it unlocks some fun like
assertThat(futureOfOptionalOfMyProto).result().value().longitude().isWithin(...).of(...)
that Java can't support.
FYI that's one of the awesome things that truth-generator unlocks for Java π€
E.g.: confluentinc/parallel-consumer@0f993dd
assertWithMessage("The only incomplete record now is offset zero, which we are blocked on")
.that(partitionState)
.getAllIncompleteOffsets()
.containsExactlyElementsIn(blockedOffsets);
assertTruth(employee).hasBoss().hasCard().hasName().ignoringTrailingWhiteSpace().equals("Tom");
from truth.
Related Issues (20)
- Consider reducing ImmutableList array copying HOT 1
- Wanted: Truth8Junit to support Java 8 types with assume() HOT 3
- Compatibility with gradle 7.6 HOT 2
- UsingCorrespondence should fail on use of equals(), like Subject does
- 1.1.4, Guava update leads to java.lang.UnsupportedOperationException at WindowsSecurityDescriptor.java:358 HOT 2
- Add StringSubject isNotBlank or hasText HOT 2
- If matches(x) fails but containsMatch(x) would have passed, suggest containsMatch in the failure message HOT 1
- Compilation error when running maven tests HOT 4
- Could not find com.google.truth.truth:1.1.2:. HOT 1
- Protobuf: allow unpopulated required fields when `comparingExpectedFieldsOnly` HOT 5
- Truth 1.1+ depends on Java 8 bytecode HOT 3
- FAQ entry: Why we don't support multiple chained calls to assertion methods on the same Subject HOT 3
- Port a core set of unit tests to kotlin HOT 2
- JUnit5 support for the existing soft-assertions support (Expect.create JUnit4 Rule) HOT 5
- Document when arrays are compared by their contents vs. their object identity HOT 3
- New extension for Gradle's TestKit HOT 1
- Asymmetric matchers like Jest's expect.stringContaining("") ? HOT 3
- Add MapSubject#containsAnyOf HOT 2
- Allow logical operations on assertions HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from truth.