Improved test cases and fixed memory leak in application.

* Previously our test cases were launching the `KiwixMainActivity` twice (firstly it sets the values in preference and then relaunch the activity) before running the test case which was the cause of slow testing and sometimes it caused to memory leak in some api levels so we have refactored our test cases to launch `KiwixMainTest` once per test case.
* `IntroFragmentTest` is failing on api level 24 due to a memory leak because after clicking on getStarted button is going to the LocalLibrary page but somehow `onStart` and `onStop` methods are calling of the `CoreReaderFragment` which stablish the `serviceConnection` but it was happening very quickly so before attaching the binder to `readAloudService` unbindService method called but at this point service was not created but creating was in progress so after going to library screen it allocate memory to `readAloudService` but `ReaderFragment` is no more visible to the user that's why memory leak happened. We have fixed it by unbinding the service in `onDestroyView` method.
This commit is contained in:
MohitMali 2023-08-29 16:56:43 +05:30 committed by Kelson
parent fff9196337
commit 1281c0c795
13 changed files with 67 additions and 13 deletions

View File

@ -21,7 +21,7 @@ package org.kiwix.kiwixmobile
import android.Manifest.permission import android.Manifest.permission
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.rule.GrantPermissionRule import androidx.test.rule.GrantPermissionRule
@ -33,8 +33,7 @@ import org.kiwix.kiwixmobile.main.KiwixMainActivity
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
abstract class BaseActivityTest { abstract class BaseActivityTest {
@get:Rule open lateinit var activityScenario: ActivityScenario<KiwixMainActivity>
open var activityScenarioRule = ActivityScenarioRule(KiwixMainActivity::class.java)
private val permissions = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { private val permissions = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
arrayOf( arrayOf(

View File

@ -19,6 +19,7 @@ package org.kiwix.kiwixmobile.download
import android.util.Log import android.util.Log
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.IdlingPolicies import androidx.test.espresso.IdlingPolicies
@ -73,11 +74,13 @@ class DownloadTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.IS_PLAY_STORE_BUILD, true) putBoolean(SharedPreferenceUtil.IS_PLAY_STORE_BUILD, true)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true) putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun downloadTest() { fun downloadTest() {
ActivityScenario.launch(KiwixMainActivity::class.java)
BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS.toLong()) BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS.toLong())
try { try {
downloadRobot { downloadRobot {

View File

@ -17,6 +17,8 @@
*/ */
package org.kiwix.kiwixmobile.help package org.kiwix.kiwixmobile.help
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiDevice
import leakcanary.LeakAssertions import leakcanary.LeakAssertions
@ -25,6 +27,7 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.BaseActivityTest
import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.RetryRule
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
@ -39,6 +42,9 @@ class HelpFragmentTest : BaseActivityTest() {
} }
waitForIdle() waitForIdle()
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Rule @Rule
@ -47,7 +53,7 @@ class HelpFragmentTest : BaseActivityTest() {
@Test @Test
fun verifyHelpActivity() { fun verifyHelpActivity() {
activityScenarioRule.scenario.onActivity { activityScenario.onActivity {
it.navigate(R.id.helpFragment) it.navigate(R.id.helpFragment)
} }
help { help {

View File

@ -19,6 +19,7 @@
package org.kiwix.kiwixmobile.initial.download package org.kiwix.kiwixmobile.initial.download
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
@ -63,11 +64,13 @@ class InitialDownloadTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.IS_PLAY_STORE_BUILD, true) putBoolean(SharedPreferenceUtil.IS_PLAY_STORE_BUILD, true)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true) putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun initialDownloadTest() { fun initialDownloadTest() {
ActivityScenario.launch(KiwixMainActivity::class.java)
BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_SEARCH_TEST.toLong()) BaristaSleepInteractions.sleep(TestUtils.TEST_PAUSE_MS_FOR_SEARCH_TEST.toLong())
initialDownload { initialDownload {
clickLibraryOnBottomNav() clickLibraryOnBottomNav()

View File

@ -18,7 +18,9 @@
package org.kiwix.kiwixmobile.intro package org.kiwix.kiwixmobile.intro
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiDevice
import leakcanary.LeakAssertions import leakcanary.LeakAssertions
@ -28,6 +30,7 @@ import org.junit.Test
import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.BaseActivityTest
import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.RetryRule
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
@ -40,7 +43,7 @@ class IntroFragmentTest : BaseActivityTest() {
@Test @Test
fun viewIsSwipeableAndNavigatesToMain() { fun viewIsSwipeableAndNavigatesToMain() {
activityScenarioRule.scenario.onActivity { activityScenario.onActivity {
it.navigate(R.id.introFragment) it.navigate(R.id.introFragment)
} }
intro(IntroRobot::swipeLeft) clickGetStarted {} intro(IntroRobot::swipeLeft) clickGetStarted {}
@ -58,5 +61,8 @@ class IntroFragmentTest : BaseActivityTest() {
PreferenceManager.getDefaultSharedPreferences(context).edit { PreferenceManager.getDefaultSharedPreferences(context).edit {
putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, true) putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
} }

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.main package org.kiwix.kiwixmobile.main
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
@ -59,11 +60,13 @@ class TopLevelDestinationTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true) putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
putBoolean(SharedPreferenceUtil.PREF_EXTERNAL_LINK_POPUP, true) putBoolean(SharedPreferenceUtil.PREF_EXTERNAL_LINK_POPUP, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun testTopLevelDestination() { fun testTopLevelDestination() {
ActivityScenario.launch(KiwixMainActivity::class.java)
topLevel { topLevel {
clickReaderOnBottomNav { clickReaderOnBottomNav {
} }

View File

@ -19,7 +19,9 @@
package org.kiwix.kiwixmobile.mimetype package org.kiwix.kiwixmobile.mimetype
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiDevice
import org.junit.Assert import org.junit.Assert
@ -30,6 +32,7 @@ import org.kiwix.kiwixmobile.BaseActivityTest
import org.kiwix.kiwixmobile.core.NightModeConfig import org.kiwix.kiwixmobile.core.NightModeConfig
import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
import java.io.File import java.io.File
@ -50,6 +53,9 @@ class MimeTypeTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, false) putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, false)
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false) putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test

View File

@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.nav.destination.library
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
@ -65,11 +66,14 @@ class LocalLibraryTest : BaseActivityTest() {
// manage external storage permission dialog on android 11 and above // manage external storage permission dialog on android 11 and above
putBoolean(SharedPreferenceUtil.PREF_MANAGE_EXTERNAL_FILES, false) putBoolean(SharedPreferenceUtil.PREF_MANAGE_EXTERNAL_FILES, false)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun testLocalLibrary() { fun testLocalLibrary() {
ActivityScenario.launch(KiwixMainActivity::class.java).onActivity { activityScenario.onActivity {
it.navigate(R.id.libraryFragment) it.navigate(R.id.libraryFragment)
} }
library { library {

View File

@ -18,6 +18,8 @@
package org.kiwix.kiwixmobile.note package org.kiwix.kiwixmobile.note
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiDevice
import leakcanary.LeakAssertions import leakcanary.LeakAssertions
@ -26,6 +28,7 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.BaseActivityTest
import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.RetryRule
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
@ -44,11 +47,14 @@ class NoteFragmentTest : BaseActivityTest() {
} }
waitForIdle() waitForIdle()
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun verifyNoteFragment() { fun verifyNoteFragment() {
activityScenarioRule.scenario.onActivity { activityScenario.onActivity {
it.navigate(R.id.notesFragment) it.navigate(R.id.notesFragment)
} }
note { note {

View File

@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.page.history
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.internal.runner.junit4.statement.UiThreadStatement import androidx.test.internal.runner.junit4.statement.UiThreadStatement
@ -63,11 +64,14 @@ class NavigationHistoryTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false) putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true) putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun navigationHistoryDialogTest() { fun navigationHistoryDialogTest() {
ActivityScenario.launch(KiwixMainActivity::class.java).onActivity { activityScenario.onActivity {
kiwixMainActivity = it kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment) kiwixMainActivity.navigate(R.id.libraryFragment)
} }

View File

@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.reader
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.internal.runner.junit4.statement.UiThreadStatement import androidx.test.internal.runner.junit4.statement.UiThreadStatement
@ -62,11 +63,14 @@ class KiwixReaderFragmentTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false) putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true) putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun testTabClosedDialog() { fun testTabClosedDialog() {
ActivityScenario.launch(KiwixMainActivity::class.java).onActivity { activityScenario.onActivity {
kiwixMainActivity = it kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment) kiwixMainActivity.navigate(R.id.libraryFragment)
} }

View File

@ -19,6 +19,7 @@ package org.kiwix.kiwixmobile.search
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.internal.runner.junit4.statement.UiThreadStatement import androidx.test.internal.runner.junit4.statement.UiThreadStatement
@ -62,11 +63,14 @@ class SearchFragmentTest : BaseActivityTest() {
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false) putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true) putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
} }
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
moveToState(Lifecycle.State.RESUMED)
}
} }
@Test @Test
fun searchFragmentSimple() { fun searchFragmentSimple() {
ActivityScenario.launch(KiwixMainActivity::class.java).onActivity { activityScenario.onActivity {
kiwixMainActivity = it kiwixMainActivity = it
kiwixMainActivity.navigate(R.id.libraryFragment) kiwixMainActivity.navigate(R.id.libraryFragment)
} }

View File

@ -1041,6 +1041,12 @@ abstract class CoreReaderFragment :
tts = null tts = null
} }
tempWebViewForUndo = null tempWebViewForUndo = null
// to fix IntroFragmentTest see https://github.com/kiwix/kiwix-android/pull/3217
try {
requireActivity().unbindService(serviceConnection)
} catch (ignore: IllegalArgumentException) {
// to handle if service is already unbounded
}
readAloudService?.registerCallBack(null) readAloudService?.registerCallBack(null)
readAloudService = null readAloudService = null
storagePermissionForNotesLauncher?.unregister() storagePermissionForNotesLauncher?.unregister()