Basically I wanna create an example which is the same to android/testing-samples, except using kotlin and coroutine.
The SimpleIdlingResource.kt would look like
class SimpleIdlingResource : IdlingResource {
@Nullable
@Volatile
private var mCallback: IdlingResource.ResourceCallback? = null
private val mIsIdleNow = AtomicBoolean(true)
override fun getName(): String {
return this.javaClass.name
}
override fun isIdleNow(): Boolean {
return mIsIdleNow.get()
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
mCallback = callback
}
fun setIdleState(isIdleNow: Boolean) {
mIsIdleNow.set(isIdleNow)
if (isIdleNow && mCallback != null) {
mCallback!!.onTransitionToIdle()
}
}
}
Android Studio converted the Java code for me, and I just fixed some syntax errors.
MainActivity.kt would looks like:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
@Nullable
private var mIdlingResource: SimpleIdlingResource? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.changeTextBt.setOnClickListener {
mIdlingResource?.setIdleState(false)
val newText = binding.editTextUserInput.text
GlobalScope.launch {
delay(1000L)
withContext(Dispatchers.Main) {
binding.textToBeChanged.text = newText
mIdlingResource?.setIdleState(true)
}
}
}
}
@VisibleForTesting
fun getIdlingResource(): IdlingResource {
if (mIdlingResource == null) {
mIdlingResource = SimpleIdlingResource()
}
return mIdlingResource as SimpleIdlingResource
}
}
I use Viewbinding to extract the elements on the main app, and use a simple coroutine to simulate the delay.
MainActivityTest.kt looks like:
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
private var mIdlingResource: IdlingResource? = null
@Before
fun registerIdlingResource() {
val activityScenario = ActivityScenario.launch(MainActivity::class.java)
activityScenario.onActivity{ activity ->
mIdlingResource = activity.getIdlingResource()
// To prove that the test fails, omit this call:
IdlingRegistry.getInstance().register(mIdlingResource)
}
}
@Test
fun whenChangeButtonIsPressedAndTextViewIsCorrect() {
ActivityScenario.launch(MainActivity::class.java)
val text2test = "cool!"
onView(withId(R.id.editTextUserInput))
.perform(typeText(text2test))
onView(withId(R.id.changeTextBt))
.perform(click())
onView(withId(R.id.textToBeChanged))
.check(matches(withText(text2test)))
}
@After
fun unregisterIdlingResource() {
if (mIdlingResource != null) {
IdlingRegistry.getInstance().unregister(mIdlingResource)
}
}
}
Once again, Android Studio converted the register and unregister part for me, when I tried to run the test cases, there's an error as follows:
Expected: with text: is "cool!"
Got: ... text=yo world
If I remove the coroutine part from the main app as well the IdlingResource part, the test case works.
Not sure if there's anything that I missed?