Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bitfireAT/davx5-ose.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunik Kupfer <kupfer@bitfire.at>2022-06-03 17:04:47 +0300
committerSunik Kupfer <kupfer@bitfire.at>2022-06-21 13:02:28 +0300
commit2e6ce88c580c1931bb86bb9db37993cbee79d88f (patch)
tree3e1b6bb129cedddb656bc8ab94b2e8ecf0163a65
parent5b0788b2e9e702dbbd14c59029bc4ff7bd5ccddc (diff)
non-flaky tests (#103)
* [WIP] initialization code to make tests non-flaky * init code as junit rule and remove flaky annotations * remove exception for flaky tests in Github test workflow * ensure correct class rule execution order
-rw-r--r--.github/workflows/test-dev.yml2
-rw-r--r--app/build.gradle1
-rw-r--r--app/src/androidTest/java/at/bitfire/davdroid/InitCalendarProviderRule.kt75
-rw-r--r--app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt11
-rw-r--r--app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt38
5 files changed, 103 insertions, 24 deletions
diff --git a/.github/workflows/test-dev.yml b/.github/workflows/test-dev.yml
index f73f8089..503eeb7c 100644
--- a/.github/workflows/test-dev.yml
+++ b/.github/workflows/test-dev.yml
@@ -51,7 +51,7 @@ jobs:
- name: Start emulator
run: start-emulator.sh
- name: Run connected tests
- run: ./gradlew app:connectedCheck -Pandroid.testInstrumentationRunnerArguments.notAnnotation=androidx.test.filters.FlakyTest
+ run: ./gradlew app:connectedCheck
- name: Archive results
if: always()
uses: actions/upload-artifact@v2
diff --git a/app/build.gradle b/app/build.gradle
index 632ccd22..c1702b86 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,7 +27,6 @@ android {
buildConfigField "String", "userAgent", "\"DAVx5\""
testInstrumentationRunner "at.bitfire.davdroid.CustomTestRunner"
- //testInstrumentationRunnerArgument "notAnnotation", "androidx.test.filters.FlakyTest"
kapt {
arguments {
diff --git a/app/src/androidTest/java/at/bitfire/davdroid/InitCalendarProviderRule.kt b/app/src/androidTest/java/at/bitfire/davdroid/InitCalendarProviderRule.kt
new file mode 100644
index 00000000..bcbe1e1b
--- /dev/null
+++ b/app/src/androidTest/java/at/bitfire/davdroid/InitCalendarProviderRule.kt
@@ -0,0 +1,75 @@
+/***************************************************************************************************
+ * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
+ **************************************************************************************************/
+
+package at.bitfire.davdroid
+
+import android.accounts.Account
+import android.content.ContentUris
+import android.content.ContentValues
+import android.provider.CalendarContract
+import androidx.test.platform.app.InstrumentationRegistry
+import at.bitfire.davdroid.log.Logger
+import at.bitfire.davdroid.resource.LocalCalendar
+import at.bitfire.davdroid.resource.LocalEvent
+import at.bitfire.ical4android.AndroidCalendar
+import at.bitfire.ical4android.Event
+import net.fortuna.ical4j.model.property.DtStart
+import net.fortuna.ical4j.model.property.RRule
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * JUnit ClassRule which initializes the AOSP CalendarProvider
+ * Needed for some "flaky" tests which would otherwise only succeed on second run
+ */
+class InitCalendarProviderRule : TestRule {
+
+ companion object {
+ private val account = Account("LocalCalendarTest", CalendarContract.ACCOUNT_TYPE_LOCAL)
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!!
+ private val uri = AndroidCalendar.create(account, provider, ContentValues())
+ private val calendar = AndroidCalendar.findByID(account, provider, LocalCalendar.Factory, ContentUris.parseId(uri))
+ }
+
+ override fun apply(base: Statement, description: Description): Statement {
+ Logger.log.info("Before test: ${description.displayName}")
+
+ Logger.log.info("Initializing CalendarProvider (InitCalendarProviderRule)")
+
+ // single event init
+ val normalEvent = Event().apply {
+ dtStart = DtStart("20220120T010203Z")
+ summary = "Event with 1 instance"
+ }
+ val normalLocalEvent = LocalEvent(calendar, normalEvent, null, null, null, 0)
+ normalLocalEvent.add()
+ LocalEvent.numInstances(provider, account, normalLocalEvent.id!!)
+
+ // recurring event init
+ val recurringEvent = Event().apply {
+ dtStart = DtStart("20220120T010203Z")
+ summary = "Event over 22 years"
+ rRules.add(RRule("FREQ=YEARLY;UNTIL=20740119T010203Z")) // year needs to be >2074 (not supported by Android <11 Calendar Storage)
+ }
+ val localRecurringEvent = LocalEvent(calendar, recurringEvent, null, null, null, 0)
+ localRecurringEvent.add()
+ LocalEvent.numInstances(provider, account, localRecurringEvent.id!!)
+
+ // Run test
+ Logger.log.info("Evaluating test..")
+ return try {
+ object : Statement() {
+ @Throws(Throwable::class)
+ override fun evaluate() {
+ base.evaluate()
+ }
+ }
+ } finally {
+ Logger.log.info("After test: $description")
+ calendar.delete()
+ }
+ }
+}
diff --git a/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt b/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt
index 730a7e8c..a92cc256 100644
--- a/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt
+++ b/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt
@@ -12,9 +12,9 @@ import android.content.ContentValues
import android.provider.CalendarContract
import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL
import android.provider.CalendarContract.Events
-import androidx.test.filters.FlakyTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
+import at.bitfire.davdroid.InitCalendarProviderRule
import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.Event
import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat
@@ -25,14 +25,19 @@ import net.fortuna.ical4j.model.property.RecurrenceId
import net.fortuna.ical4j.model.property.Status
import org.junit.*
import org.junit.Assert.assertEquals
+import org.junit.rules.TestRule
class LocalCalendarTest {
companion object {
@JvmField
- @ClassRule
+ @ClassRule(order = 0)
val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)!!
+ @JvmField
+ @ClassRule(order = 1)
+ val initCalendarProviderRule: TestRule = InitCalendarProviderRule()
+
private lateinit var provider: ContentProviderClient
@BeforeClass
@@ -114,7 +119,7 @@ class LocalCalendarTest {
}
@Test
- @FlakyTest(detail = "Fails when calendar storage is accessed the first time; probably some initialization thread")
+ // Flaky, Needs single or rec init of CalendarProvider (InitCalendarProviderRule)
fun testDeleteDirtyEventsWithoutInstances_Recurring_Instances() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
diff --git a/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt b/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt
index 4c3d4bd8..e3e43bf4 100644
--- a/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt
+++ b/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt
@@ -6,16 +6,14 @@ package at.bitfire.davdroid.resource
import android.Manifest
import android.accounts.Account
-import android.content.ContentProviderClient
-import android.content.ContentUris
-import android.content.ContentValues
+import android.content.*
import android.os.Build
import android.provider.CalendarContract
import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL
import android.provider.CalendarContract.Events
-import androidx.test.filters.FlakyTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
+import at.bitfire.davdroid.InitCalendarProviderRule
import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.Event
import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat
@@ -26,14 +24,19 @@ import net.fortuna.ical4j.model.parameter.Value
import net.fortuna.ical4j.model.property.*
import org.junit.*
import org.junit.Assert.*
+import org.junit.rules.TestRule
class LocalEventTest {
companion object {
@JvmField
- @ClassRule
+ @ClassRule(order = 0)
val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)!!
+ @JvmField
+ @ClassRule(order = 1)
+ val initCalendarProviderRule: TestRule = InitCalendarProviderRule()
+
private val account = Account("LocalCalendarTest", ACCOUNT_TYPE_LOCAL)
private lateinit var provider: ContentProviderClient
@@ -51,7 +54,6 @@ class LocalEventTest {
fun disconnect() {
provider.closeCompat()
}
-
}
@Before
@@ -67,7 +69,6 @@ class LocalEventTest {
@Test
- @FlakyTest(detail = "Fails when calendar storage is accessed the first time; probably some initialization thread")
fun testNumDirectInstances_SingleInstance() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
@@ -106,6 +107,7 @@ class LocalEventTest {
}
@Test
+ // Flaky, Needs rec event init of CalendarProvider
fun testNumDirectInstances_Recurring_LateEnd() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
@@ -122,6 +124,7 @@ class LocalEventTest {
}
@Test
+ // Flaky, Needs rec event init of CalendarProvider
fun testNumDirectInstances_Recurring_ManyInstances() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
@@ -130,21 +133,15 @@ class LocalEventTest {
}
val localEvent = LocalEvent(calendar, event, null, null, null, 0)
localEvent.add()
-
val number = LocalEvent.numDirectInstances(provider, account, localEvent.id!!)
- // Doesn't work immediately after the Calendar Provider has been started the first time.
- // It then retursn 42 instead of 2*365 instances. As soon as the test is run the second time,
- // it works. However it doesn't matter as soon as there is at least one instance.
- /*assertEquals(
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q)
- 365*2 // early Android: does not include UNTIL (incorrect!)
- else
- 365*2 + 1, // current Android: includes UNTIL (correct)
- number)*/
- assertTrue(number != null && number > 1)
+
+ // Some android versions (i.e. <=Q and S) return 365*2 instances (wrong, 365*2+1 => correct),
+ // but we are satisfied with either result for now
+ assertTrue(number == 365*2 || number == 365*2+1)
}
@Test
+ // Flaky, Needs single event init of CalendarProvider
fun testNumDirectInstances_RecurringWithExdate() {
val event = Event().apply {
dtStart = DtStart(Date("20220120T010203Z"))
@@ -183,6 +180,7 @@ class LocalEventTest {
@Test
+ // Flaky, Needs single or rec event init of CalendarProvider
fun testNumInstances_SingleInstance() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
@@ -221,6 +219,7 @@ class LocalEventTest {
}
@Test
+ // Flaky, Needs rec event init of CalendarProvider
fun testNumInstances_Recurring_LateEnd() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
@@ -237,6 +236,7 @@ class LocalEventTest {
}
@Test
+ // Flaky, Needs rec event init of CalendarProvider
fun testNumInstances_Recurring_ManyInstances() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
@@ -360,7 +360,7 @@ class LocalEventTest {
}
@Test
- @FlakyTest(detail = "Fails when calendar storage is accessed the first time; probably some initialization thread")
+ // Flaky, Needs single event init OR rec event init of CalendarProvider
fun testDeleteDirtyEventsWithoutInstances_Recurring_Instances() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")