adding Linphone Rules with retry option

This commit is contained in:
Quentin Monnier 2023-01-24 17:42:59 -06:00 committed by Sylvain Berfini
parent d782422e4d
commit e6a220c5af
5 changed files with 78 additions and 39 deletions

View file

@ -2,7 +2,6 @@ package org.linphone.call
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.rule.GrantPermissionRule
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -20,10 +19,7 @@ class IncomingCallPushUITests {
val methods = CallViewUITestsMethods
@get:Rule
val screenshotsRule = ScreenshotsRule(true)
@get:Rule
var mGrantPermissionRule = GrantPermissionRule.grant(*LinphonePermissions.CALL)
val linphoneUITestRule = LinphoneUITestRule(LinphonePermissions.CALL, true, 2)
@Before
fun setUp() {

View file

@ -7,7 +7,6 @@ import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.rule.GrantPermissionRule
import java.util.*
import org.junit.After
import org.junit.Before
@ -25,13 +24,9 @@ import org.linphone.utils.AppUtils.Companion.getString
class IncomingCallUITests {
val methods = CallViewUITestsMethods
var time = Date().time // to pass time value between setup and test function for call timer check
@get:Rule
val screenshotsRule = ScreenshotsRule(true)
@get:Rule
var mGrantPermissionRule = GrantPermissionRule.grant(*LinphonePermissions.CALL)
val linphoneUITestRule = LinphoneUITestRule(LinphonePermissions.CALL, true, 2)
@Before
fun setUp() {
@ -39,7 +34,6 @@ class IncomingCallUITests {
methods.refreshAccountInfo()
takeScreenshot("dialer_view")
methods.startIncomingCall()
time = Date().time
methods.onPushAction(getString(R.string.incoming_call_notification_title), UITestsView.incomingCallView)
takeScreenshot("incoming_call_view")
}
@ -51,7 +45,7 @@ class IncomingCallUITests {
@Test
fun testViewDisplay() {
methods.checkCallTime(onView(ViewMatchers.withId(R.id.outgoing_call_timer)), time)
methods.checkCallTime(onView(ViewMatchers.withId(R.id.incoming_call_timer)), methods.startCallTime)
methods.endCall(UITestsView.incomingCallView)
takeScreenshot("dialer_view")
}

View file

@ -6,7 +6,6 @@ import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.rule.GrantPermissionRule
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -24,10 +23,7 @@ class OutgoingCallUITests {
val methods = CallViewUITestsMethods
@get:Rule
val screenshotsRule = ScreenshotsRule(true)
@get:Rule
var mGrantPermissionRule = GrantPermissionRule.grant(*LinphonePermissions.CALL)
val linphoneUITestRule = LinphoneUITestRule(LinphonePermissions.CALL, true, 2)
@Before
fun setUp() {
@ -45,7 +41,7 @@ class OutgoingCallUITests {
@Test
fun testViewDisplay() {
methods.checkCallTime(onView(withId(R.id.outgoing_call_timer)))
methods.checkCallTime(onView(withId(R.id.outgoing_call_timer)), methods.startCallTime)
methods.endCall(UITestsView.outgoingCallView)
takeScreenshot("dialer_view", "declined")
}
@ -62,7 +58,7 @@ class OutgoingCallUITests {
takeScreenshot("outgoing_call_view", "mute")
onView(withId(R.id.microphone)).perform(click())
takeScreenshot("outgoing_call_view")
methods.endCall()
methods.endCall(UITestsView.outgoingCallView)
takeScreenshot("dialer_view", "declined")
}
@ -72,7 +68,7 @@ class OutgoingCallUITests {
takeScreenshot("outgoing_call_view", "speaker")
onView(withId(R.id.speaker)).perform(click())
takeScreenshot("outgoing_call_view")
methods.endCall()
methods.endCall(UITestsView.outgoingCallView)
takeScreenshot("dialer_view", "declined")
}

View file

@ -29,6 +29,7 @@ object CallViewUITestsMethods {
val manager = UITestsCoreManager.instance
var appAccountAuthInfo: AuthInfo = UITestsCoreManager.instance.appAccountAuthInfo
var ghostAccount: UITestsRegisteredLinphoneCore = UITestsCoreManager.instance.ghostAccounts[0]
var startCallTime = Date().time // for checkCallTime function
fun refreshAccountInfo() {
appAccountAuthInfo = UITestsCoreManager.instance.appAccountAuthInfo
@ -39,8 +40,9 @@ object CallViewUITestsMethods {
if (ghostAccount.callState != Call.State.Released) { ghostAccount.terminateCall() }
ghostAccount.startCall(manager.createAddress(appAccountAuthInfo))
ghostAccount.waitForCallState(Call.State.OutgoingRinging, 5.0)
startCallTime = Date().time
ghostAccount.waitForCallState(Call.State.OutgoingRinging, 5.0)
waitForCallNotification(true, 5.0)
}
@ -49,8 +51,10 @@ object CallViewUITestsMethods {
onView(withId(R.id.sip_uri_input)).perform(typeText(ghostAccount.mAuthInfo.username))
onView(withContentDescription(R.string.content_description_start_call)).perform(click())
startCallTime = Date().time
UITestsView.outgoingCallView.checkWithTimeout(matches(isDisplayed()), 5.0)
ghostAccount.waitForCallState(Call.State.IncomingReceived, 5.0)
}
fun endCall(currentView: ViewInteraction? = null) {
@ -63,7 +67,7 @@ object CallViewUITestsMethods {
}
fun checkCallTime(view: ViewInteraction, launchTime: Long = Date().time) = runBlocking {
view.checkWithTimeout(matches(isDisplayed()), 2.0)
view.checkWithTimeout(matches(isDisplayed()), 5.0)
val firstValue = ((Date().time - launchTime) / 1000).toInt() + 1
val wait = launch(Dispatchers.Default) {
val timerArray = arrayListOf<Int>()

View file

@ -5,17 +5,22 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.espresso.*
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewAssertion
import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import java.util.*
import kotlinx.coroutines.*
import org.junit.rules.TestWatcher
import org.junit.AssumptionViolatedException
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.MultipleFailureException
import org.junit.runners.model.Statement
import org.linphone.LinphoneApplication
import org.linphone.R
import org.linphone.activities.main.MainActivity
@ -25,18 +30,64 @@ import org.linphone.core.Factory
import org.linphone.core.TransportType
import org.linphone.core.tools.Log
class ScreenshotsRule(active: Boolean) : TestWatcher() {
class LinphoneUITestRule(
private val permissions: Array<String>,
private val screenshots: Boolean,
private val maxAttempts: Int
) : TestRule {
val screenshotComparison = active
// @get: Rule
// var grantPermissionRule = GrantPermissionRule.grant(*permissions)
override fun starting(description: Description) {
super.starting(description)
UITestsScreenshots.screenshotComparison = screenshotComparison
private var attemptNumber = 1
fun onStart(description: Description) {
UITestsScreenshots.screenshotComparison = screenshots
UITestsScreenshots.definePath(description.className, description.methodName, Date().time.toString())
if (screenshotComparison && !UITestsScreenshots.defaultPath.isDirectory) {
if (screenshots && !UITestsScreenshots.defaultPath.isDirectory) {
UITestsScreenshots.defaultPath.mkdirs()
}
}
fun onFailure(
base: Statement,
description: Description,
e: Throwable,
errors: MutableList<Throwable>
) {
if (attemptNumber <= maxAttempts) {
Log.e("[UITests] ${description.displayName} attempt $attemptNumber failed")
Log.e("[UITests] ${description.displayName} $e")
Log.e("[UITests] ${description.displayName} launch of an attempt ${++attemptNumber} ")
onStart(description)
base.evaluate()
} else {
errors.add(e)
}
}
override fun apply(base: Statement, description: Description): Statement {
return object : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
val errors: MutableList<Throwable> = ArrayList()
onStart(description)
try {
base.evaluate()
// on succeed
} catch (e: AssumptionViolatedException) {
errors.add(e)
// on skip
} catch (e: Throwable) {
onFailure(base, description, e, errors)
} finally {
// on finish
}
MultipleFailureException.assertEmpty(errors)
}
}
}
}
object LinphonePermissions {
@ -55,7 +106,7 @@ object LinphonePermissions {
}
object UITestsView {
val dialerView = onView(withId(R.id.incoming_call_layout))
val dialerView = onView(withId(R.id.dialer_layout))
val incomingCallView = onView(withId(R.id.incoming_call_layout))
val outgoingCallView = onView(withId(R.id.outgoing_call_layout))
val singleCallView = onView(withId(R.id.single_call_layout))
@ -69,7 +120,7 @@ object UITestsUtils {
fun testAppSetup() {
// launch app
Log.i("[UITests] Launch Linphone app")
if (!isAppLaunch()) { launchApp() }
launchApp()
try {
onView(withId(R.id.assistant_welcome_layout)).check(doesNotExist())
} catch (e: Throwable) {
@ -80,7 +131,7 @@ object UITestsUtils {
connectAccount()
assert(accountIsConnected()) { "registration state on the Status Bar is still not : Connected after 10 seconds" }
}
onView(withId(R.id.dialer_layout)).checkWithTimeout(matches(isDisplayed()), 5.0)
UITestsView.dialerView.checkWithTimeout(matches(isDisplayed()), 5.0)
}
fun launchApp() {
@ -152,9 +203,8 @@ object UITestsUtils {
}
fun ViewInteraction.checkWithTimeout(viewAssert: ViewAssertion, timeout: Double): ViewInteraction = runBlocking {
val time = Date().time
val wait = launch(Dispatchers.Default) {
repeat((timeout * 10).toInt()) {
repeat((timeout * 10).toInt()) { i ->
try {
check(viewAssert)
cancel()
@ -165,7 +215,6 @@ object UITestsUtils {
}
}
wait.join()
check { view, noViewFoundException -> Log.i("[UITests] $view (found in ${(Date().time - time).toFloat() / 1000} sec)") }
check(viewAssert)
check(viewAssert).withFailureHandler { error, viewMatcher -> throw Exception("[UITests] $error") }
}
}