From 119f9f4f1309fb84d91938bae5748691d5218df8 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Dec 2019 21:37:09 +0100 Subject: [PATCH] test improvements, bug fixes --- .../nightscout/androidaps/EspressoHelper.kt | 16 ++++- .../androidaps/SetupWizardActivityTest.kt | 61 ++++++++++++++----- .../objectives/ObjectivesFragment.kt | 7 +++ .../plugins/source/RandomBgPlugin.kt | 3 +- .../androidaps/setupwizard/SWDefinition.java | 6 +- .../setupwizard/SetupWizardActivity.java | 4 +- .../androidaps/utils/EspressoTestHelper.kt | 2 +- .../main/res/layout/activity_setupwizard.xml | 1 + 8 files changed, 76 insertions(+), 24 deletions(-) diff --git a/app/src/androidTest/java/info/nightscout/androidaps/EspressoHelper.kt b/app/src/androidTest/java/info/nightscout/androidaps/EspressoHelper.kt index 4bd0c15bf8..b50bb746fb 100644 --- a/app/src/androidTest/java/info/nightscout/androidaps/EspressoHelper.kt +++ b/app/src/androidTest/java/info/nightscout/androidaps/EspressoHelper.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps -import androidx.test.espresso.NoMatchingViewException +import androidx.test.espresso.ViewAction import androidx.test.espresso.ViewInteraction import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers @@ -9,7 +9,19 @@ fun ViewInteraction.isDisplayed(): Boolean { try { check(matches(ViewMatchers.isDisplayed())) return true - } catch (e: NoMatchingViewException) { + } catch (e: Throwable) { return false } } + +fun ViewInteraction.waitAndPerform(viewActions: ViewAction): ViewInteraction? { + val startTime = System.currentTimeMillis() + while (!isDisplayed()) { + Thread.sleep(100) + if (System.currentTimeMillis() - startTime >= 5000) { + throw AssertionError("View not visible after 5000 milliseconds") + } + } + return perform(viewActions) +} + diff --git a/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt b/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt index c7be5ac255..dd1c0b12bc 100644 --- a/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt +++ b/app/src/androidTest/java/info/nightscout/androidaps/SetupWizardActivityTest.kt @@ -14,14 +14,26 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.rule.ActivityTestRule import androidx.test.rule.GrantPermissionRule +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin +import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin +import info.nightscout.androidaps.plugins.source.RandomBgPlugin import info.nightscout.androidaps.setupwizard.SetupWizardActivity +import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.SP +import info.nightscout.androidaps.utils.isRunningTest import org.hamcrest.CoreMatchers.allOf import org.hamcrest.Description import org.hamcrest.Matcher import org.hamcrest.Matchers import org.hamcrest.TypeSafeMatcher +import org.junit.Assert import org.junit.Before import org.junit.Rule import org.junit.Test @@ -65,26 +77,27 @@ adb shell settings put global animator_duration_scale 0 & @Test fun setupWizardActivityTest() { + Assert.assertTrue(isRunningTest()) // Welcome page onView(withId(R.id.next_button)).perform(click()) // Language selection onView(withText("English")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Agreement page onView(withText("I UNDERSTAND AND AGREE")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Loction permission var askButton = onView(withText("Ask for permission")) if (askButton.isDisplayed()) { askButton.perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) } // Store permission askButton = onView(withText("Ask for permission")) if (askButton.isDisplayed()) { askButton.perform(scrollTo(), click()) onView(withText("OK")).perform(click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) } // Units selection onView(withText("mmol/L")).perform(scrollTo(), click()) @@ -97,16 +110,16 @@ adb shell settings put global animator_duration_scale 0 & onView(withId(R.id.next_button)).perform(click()) // Age selection onView(withText("Adult")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Insulin selection onView(withText("Ultra-Rapid Oref")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // BG source selection onView(withText("Random BG")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Profile selection onView(withText("Local Profile")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Local profile - DIA onView(withTagValue(Matchers.`is`("LP_DIA"))).perform(scrollTo(), ViewActions.replaceText("6.0")) // Local profile - IC @@ -140,7 +153,7 @@ adb shell settings put global animator_duration_scale 0 & .perform(scrollTo(), click()) onView(allOf(withId(R.id.ok), isDisplayed())).perform(click()) onView(Matchers.allOf(withText("OK"), isDisplayed())).perform(click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Profile switch askButton = onView(withText("Do Profile Switch")) if (askButton.isDisplayed()) { @@ -148,28 +161,46 @@ adb shell settings put global animator_duration_scale 0 & onView(allOf(withId(R.id.ok), isDisplayed())).perform(click()) onView(Matchers.allOf(withText("OK"), isDisplayed())).perform(click()) while (ProfileFunctions.getInstance().profile == null) SystemClock.sleep(100) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) } // Pump onView(withText("Virtual Pump")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // APS onView(withText("OpenAPS SMB")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Open Closed Loop onView(withText("Closed Loop")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Loop askButton = onView(withText("Enable loop")) if (askButton.isDisplayed()) { askButton.perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) } // Sensitivity onView(withText("Sensitivity Oref1")).perform(scrollTo(), click()) - onView(withId(R.id.next_button)).perform(click()) + onView(withId(R.id.next_button)).waitAndPerform(click()) // Objectives onView(allOf(withText("Start"), isDisplayed())).perform(scrollTo(), click()) + onView(withId(R.id.finish_button)).waitAndPerform(click()) + + // Verify settings + Assert.assertEquals(Constants.MMOL, ProfileFunctions.getSystemUnits()) + Assert.assertEquals(17.0, HardLimits.maxBolus(), 0.0001) // Adult + Assert.assertTrue(RandomBgPlugin.isEnabled(PluginType.BGSOURCE)) + Assert.assertTrue(LocalProfilePlugin.isEnabled(PluginType.PROFILE)) + val p = ProfileFunctions.getInstance().profile + Assert.assertNotNull(p) + Assert.assertEquals(2.0, p!!.ic, 0.0001) + Assert.assertEquals(3.0 * Constants.MMOLL_TO_MGDL, p.isfMgdl, 0.0001) + Assert.assertEquals(1.1, p.getBasalTimeFromMidnight(0), 0.0001) + Assert.assertEquals(6.0 * Constants.MMOLL_TO_MGDL, p.targetLowMgdl, 0.0001) + Assert.assertTrue(VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP)) + Assert.assertTrue(OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) + Assert.assertTrue(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) + Assert.assertTrue(SensitivityOref1Plugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) + Assert.assertTrue(ObjectivesPlugin.objectives[0].isStarted) } private fun childAtPosition( diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt index 34aadf84c6..9864f875e4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt @@ -28,6 +28,7 @@ import info.nightscout.androidaps.plugins.constraints.objectives.events.EventNtp import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask import info.nightscout.androidaps.receivers.NetworkChangeReceiver +import info.nightscout.androidaps.setupwizard.events.EventSWUpdate import info.nightscout.androidaps.utils.* import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -217,6 +218,7 @@ class ObjectivesFragment : Fragment() { scrollToCurrentObjective() startUpdateTimer() RxBus.send(EventObjectivesUpdateGui()) + RxBus.send(EventSWUpdate(false)) } else { // move out of UI thread Thread { @@ -234,6 +236,7 @@ class ObjectivesFragment : Fragment() { RxBus.send(EventNtpStatus(MainApp.gs(R.string.success), 100)) SystemClock.sleep(1000) RxBus.send(EventObjectivesUpdateGui()) + RxBus.send(EventSWUpdate(false)) SystemClock.sleep(100) scrollToCurrentObjective() } else { @@ -254,6 +257,7 @@ class ObjectivesFragment : Fragment() { scrollToCurrentObjective() startUpdateTimer() RxBus.send(EventObjectivesUpdateGui()) + RxBus.send(EventSWUpdate(false)) } else // move out of UI thread Thread { @@ -270,6 +274,7 @@ class ObjectivesFragment : Fragment() { RxBus.send(EventNtpStatus(MainApp.gs(R.string.success), 100)) SystemClock.sleep(1000) RxBus.send(EventObjectivesUpdateGui()) + RxBus.send(EventSWUpdate(false)) SystemClock.sleep(100) scrollToCurrentObjective() } else { @@ -284,12 +289,14 @@ class ObjectivesFragment : Fragment() { objective.startedOn = 0 scrollToCurrentObjective() RxBus.send(EventObjectivesUpdateGui()) + RxBus.send(EventSWUpdate(false)) } } holder.unFinish.setOnClickListener { objective.accomplishedOn = 0 scrollToCurrentObjective() RxBus.send(EventObjectivesUpdateGui()) + RxBus.send(EventSWUpdate(false)) } if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted && objective.specialActionEnabled()) { // generate random request code if none exists diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt index bf58c1aa91..ea6731ca60 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.isRunningTest import org.slf4j.LoggerFactory import java.util.* import kotlin.math.PI @@ -54,7 +55,7 @@ object RandomBgPlugin : PluginBase(PluginDescription() } override fun specialEnableCondition(): Boolean { - return VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP) && MainApp.engineeringMode + return VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP) && (MainApp.engineeringMode || isRunningTest()) } override fun handleNewData(intent: Intent) { diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java index 5d93195f36..45ab985fce 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java @@ -434,7 +434,7 @@ public class SWDefinition { add(screenSetupWizard) .add(screenLanguage) .add(screenEula) - .add(isRunningTest() ? screenPermissionBattery : null) // cannot mock ask battery optimalization + .add(isRunningTest() ? null : screenPermissionBattery) // cannot mock ask battery optimalization .add(screenPermissionBt) .add(screenPermissionStore) .add(screenImport) @@ -462,7 +462,7 @@ public class SWDefinition { add(screenSetupWizard) .add(screenLanguage) .add(screenEula) - .add(isRunningTest() ? screenPermissionBattery : null) + .add(isRunningTest() ? null : screenPermissionBattery) // cannot mock ask battery optimalization .add(screenPermissionBt) .add(screenPermissionStore) .add(screenImport) @@ -486,7 +486,7 @@ public class SWDefinition { add(screenSetupWizard) .add(screenLanguage) .add(screenEula) - .add(isRunningTest() ? screenPermissionBattery : null) + .add(isRunningTest() ? null : screenPermissionBattery) // cannot mock ask battery optimalization .add(screenPermissionStore) .add(screenImport) .add(screenUnits) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java index 603292d3cc..8d0d37e003 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -187,7 +187,7 @@ public class SetupWizardActivity extends NoSplashAppCompatActivity { return page; page++; } - return currentWizardPage; + return Math.min(currentWizardPage, screens.size() -1); } private int previousPage() { @@ -197,7 +197,7 @@ public class SetupWizardActivity extends NoSplashAppCompatActivity { return page; page--; } - return currentWizardPage; + return Math.max(currentWizardPage, 0); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/utils/EspressoTestHelper.kt b/app/src/main/java/info/nightscout/androidaps/utils/EspressoTestHelper.kt index 55c7b7c20f..7288e6679f 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/EspressoTestHelper.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/EspressoTestHelper.kt @@ -3,7 +3,7 @@ package info.nightscout.androidaps.utils @Synchronized fun isRunningTest(): Boolean { return try { - Class.forName("android.support.test.espresso.Espresso") + Class.forName("androidx.test.espresso.Espresso") true } catch (e: ClassNotFoundException) { false diff --git a/app/src/main/res/layout/activity_setupwizard.xml b/app/src/main/res/layout/activity_setupwizard.xml index 2c2930b827..1a9a7aad94 100644 --- a/app/src/main/res/layout/activity_setupwizard.xml +++ b/app/src/main/res/layout/activity_setupwizard.xml @@ -13,6 +13,7 @@ android:orientation="horizontal">