Truth - Fluent assertions for Java and Android

What is Truth?

Truth is a library for performing assertions in tests:

assertThat(notificationText).contains("testuser@google.com");

Truth is owned and maintained by the Guava team. It is used in the majority of the tests in Google’s own codebase.

Why use an assertion library?

In other words, why depend on a new library when you can use the methods built into your testing framework, like assertEquals?

assertEquals(
    ImmutableMultiset.of("guava", "dagger", "truth", "auto", "caliper"),
    HashMultiset.create(projectsByTeam().get("corelibs")));

Here’s the equivalent using Truth:

assertThat(projectsByTeam())
    .valuesForKey("corelibs")
    .containsExactly("guava", "dagger", "truth", "auto", "caliper");

Consider also the failure message:

java.lang.AssertionError: expected:<[guava, dagger, truth, auto, caliper]> but was:<[dagger, auto, caliper, guava]>
  at org.junit.Assert.failNotEquals(Assert.java:835) <2 internal calls>
  at com.google.common.truth.example.DemoTest.testBuiltin(DemoTest.java:64) <19 internal calls>

This is fine for a simple assertion, but consider:

Here’s the message generated by Truth:

value of    : projectsByTeam().valuesForKey(corelibs)
missing (1) : truth
───
expected    : [guava, dagger, truth, auto, caliper]
but was     : [guava, auto, dagger, caliper]
multimap was: {corelibs=[guava, auto, dagger, caliper]}
  at com.google.common.truth.example.DemoTest.testTruth(DemoTest.java:71)

Truth vs. AssertJ

Truth and AssertJ are very similar. This raises the question: Why did we create Truth? The reason is historical: AssertJ didn’t exist when we started Truth. By the time it was created, we’d begun using Truth widely at Google, and we’d made some decisions that would be difficult to retrofit onto AssertJ.

Both Truth and AssertJ have their advantages. We prefer Truth for its simpler API:

We also usually prefer Truth’s failure messages (though we find AssertJ’s to often be similar and, in some cases we’re still working on, to even be better).

Additionally, Truth works on Android devices by default, without requiring users to use an older version or import a different class than usual.

Truth vs. Hamcrest

Truth and Hamcrest differ significantly. We prefer Truth because:

How to use Truth

1. Add the appropriate dependency to your build file:

Maven:

<dependency>
  <groupId>com.google.truth</groupId>
  <artifactId>truth</artifactId>
  <version>1.0</version>
  <scope>test</scope>
</dependency>

Gradle:

repositories {
  mavenCentral()
}
dependencies {
  testImplementation "com.google.truth:truth:1.0"
}

To use the Java 8 extensions, also include com.google.truth.extensions:truth-java8-extension:1.0.

To further enhance failure messages in some cases, also include org.ow2.asm:asm:someversion. (ASM is what lets Truth output projectsByTeam().valuesForKey(corelibs) above instead of just multimap.valuesForKey(corelibs).)

One warning: Truth depends on the “Android” version of Guava, a subset of the “JRE” version. If your project uses the JRE version, be aware that your build system might select the Android version instead. If so, you may see “missing symbol” errors. The easiest fix is usually to add a direct dependency on the newest JRE version of Guava.

2. Add static imports for Truth’s entry points:

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

// for assertions on Java 8 types
import static com.google.common.truth.Truth8.assertThat;

3. Write a test assertion:

String string = "awesome";
assertThat(string).startsWith("awe");
assertWithMessage("Without me, it's just aweso").that(string).contains("me");

Iterable<Color> googleColors = googleLogo.getColors();
assertThat(googleColors)
    .containsExactly(BLUE, RED, YELLOW, BLUE, GREEN, RED)
    .inOrder();

If you’re using an IDE with autocompletion, it will suggest a list of assertions you can make about the given type. If not, consult the API docs. For example, if you’re looking for assertions about a Map, look at the documentation for MapSubject.

More information