1 package com.android.onboarding.testing
2
3 import com.google.common.truth.Fact.fact
4 import com.google.common.truth.Fact.simpleFact
5 import com.google.common.truth.FailureMetadata
6 import com.google.common.truth.StandardSubjectBuilder
7 import com.google.common.truth.Subject
8 import com.google.common.truth.ThrowableSubject
9 import com.google.common.truth.Truth
10 import com.google.common.truth.Truth.assertAbout
11 import com.google.common.truth.Truth.assertThat
12 import com.google.errorprone.annotations.CanIgnoreReturnValue
13
14 /** A [Truth] [Subject] to assert that no [Throwable]s were thrown failing lazily otherwise. */
15 class SuccessSubject
16 private constructor(metadata: FailureMetadata, private val actual: (() -> Any?)?) :
17 Subject(metadata, actual) {
18
19 @CanIgnoreReturnValue
doesNotFailnull20 fun doesNotFail(): Subject {
21 if (actual == null) {
22 failWithoutActual(
23 simpleFact("expected to not fail"),
24 simpleFact("but no action was provided"),
25 )
26 return assertThat(null as Any?)
27 }
28 val result =
29 runCatching(actual).onFailure {
30 failWithoutActual(
31 simpleFact("expected to not fail"),
32 fact("but failed with", it::class.qualifiedName),
33 )
34 }
35 return assertThat(result.getOrNull())
36 }
37
38 companion object : Factory<SuccessSubject, () -> Any?> {
createSubjectnull39 override fun createSubject(metadata: FailureMetadata, actual: (() -> Any?)?): SuccessSubject =
40 SuccessSubject(metadata, actual)
41 }
42 }
43
44 /** @see assertDoesNotFail */
45 fun StandardSubjectBuilder.doesNotFail(action: () -> Any?) {
46 about(SuccessSubject).that(action).doesNotFail()
47 }
48
49 /**
50 * Asserts that a given [action] does not throw an exception. If the [action] does throw an
51 * exception, it is registered lazily to the [StandardSubjectBuilder] allowing the rest of the test
52 * assertions to continue.
53 *
54 * Unfortunately @[CanIgnoreReturnValue] is not supported on inline library functions and as such
55 * this utility function is not returning [ThrowableSubject] for further assertions. If you need
56 * further assertions consider using one of the more verbose forms:
57 * ```
58 * @get:Rule val expect: Expect = Expect.create()
59 * expect.about(SuccessSubject).that { functionUnderTest() }.doesNotFail().isNotNull()
60 *
61 * assertAbout(SuccessSubject).that { functionUnderTest() }.doesNotFail().isNotNull()
62 * ```
63 */
assertDoesNotFailnull64 fun assertDoesNotFail(action: () -> Any?) {
65 assertAbout(SuccessSubject).that(action).doesNotFail()
66 }
67