Reduce noise of flaky test.

This commit is contained in:
Greyson Parrelli 2024-08-15 09:29:43 -04:00 committed by mtang-signal
parent 627b939326
commit 630875dae2
4 changed files with 97 additions and 0 deletions

View file

@ -0,0 +1,32 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.backup.v2
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.thoughtcrime.securesms.testing.SignalFlakyTest
import org.thoughtcrime.securesms.testing.SignalFlakyTestRule
@RunWith(AndroidJUnit4::class)
class FlakyTestAnnotationTest {
@get:Rule
val flakyTestRule = SignalFlakyTestRule()
companion object {
private var count = 0
}
@SignalFlakyTest
@Test
fun purposelyFlaky() {
count++
assertEquals(3, count)
}
}

View file

@ -4,9 +4,12 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.signal.core.util.concurrent.SignalExecutors
import org.thoughtcrime.securesms.testing.SignalFlakyTest
import org.thoughtcrime.securesms.testing.SignalFlakyTestRule
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicBoolean
@ -18,6 +21,9 @@ class SQLiteDatabaseTest {
private lateinit var db: SQLiteDatabase
@get:Rule
val flakyTestRule = SignalFlakyTestRule()
@Before
fun setup() {
db = SignalDatabase.instance!!.signalWritableDatabase
@ -181,6 +187,7 @@ class SQLiteDatabaseTest {
assertTrue(hasRun2.get())
}
@SignalFlakyTest
@Test
fun runPostSuccessfulTransaction_runsAfterMainTransactionInNestedTransaction() {
val hasRun1 = AtomicBoolean(false)

View file

@ -0,0 +1,9 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.testing
@Retention(AnnotationRetention.RUNTIME)
annotation class SignalFlakyTest(val allowedAttempts: Int = 3)

View file

@ -0,0 +1,49 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.testing
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.signal.core.util.logging.Log
/**
* A JUnit rule that retries tests annotated with [SignalFlakyTest] before considering them to be a failure.
* As the name implies, this is useful for known-flaky tests.
*/
class SignalFlakyTestRule : TestRule {
override fun apply(base: Statement, description: Description): Statement {
val flakyAnnotation = description.getAnnotation(SignalFlakyTest::class.java)
return if (flakyAnnotation != null) {
FlakyStatement(
base = base,
description = description,
allowedAttempts = flakyAnnotation.allowedAttempts
)
} else {
base
}
}
private class FlakyStatement(private val base: Statement, private val description: Description, private val allowedAttempts: Int) : Statement() {
override fun evaluate() {
var attemptsRemaining = allowedAttempts
while (attemptsRemaining > 0) {
try {
base.evaluate()
return
} catch (t: Throwable) {
attemptsRemaining--
if (attemptsRemaining <= 0) {
throw t
}
Log.w(description.testClass.simpleName, "[${description.methodName}] Flaky test failed! $attemptsRemaining attempt(s) remaining.", t)
}
}
}
}
}