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.assertFalse
import junit.framework.Assert.assertTrue import junit.framework.Assert.assertTrue
import org.junit.Before import org.junit.Before
import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.signal.core.util.concurrent.SignalExecutors 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.CountDownLatch
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@@ -18,6 +21,9 @@ class SQLiteDatabaseTest {
private lateinit var db: SQLiteDatabase private lateinit var db: SQLiteDatabase
@get:Rule
val flakyTestRule = SignalFlakyTestRule()
@Before @Before
fun setup() { fun setup() {
db = SignalDatabase.instance!!.signalWritableDatabase db = SignalDatabase.instance!!.signalWritableDatabase
@@ -181,6 +187,7 @@ class SQLiteDatabaseTest {
assertTrue(hasRun2.get()) assertTrue(hasRun2.get())
} }
@SignalFlakyTest
@Test @Test
fun runPostSuccessfulTransaction_runsAfterMainTransactionInNestedTransaction() { fun runPostSuccessfulTransaction_runsAfterMainTransactionInNestedTransaction() {
val hasRun1 = AtomicBoolean(false) 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)
}
}
}
}
}