32

I 've got a Quiz app using Realm db. Every time the user selects an answer she clicks a button and new text for Question appears. Thats it until she reaches the end where I start a new Activity and display a score based on correct answers.

How should I start/test ( with Espresso I guess ) that activity without having to enter manually every time all the answers and click the button after each answer until I reach the last one?

What I need is to pass some mock data to a variable and make an Intent but I dont know how and cant find anything related with this in Espresso

t0s
  • 1,201
  • 5
  • 19
  • 28
  • What if you make that activity as the launcher activity, so that that activity is the first activity your app shows? – code May 12 '15 at 13:08
  • hmm I guess its possible something like that but I'm not sure if this is a "good" practice and if im allowed to alter my src files structure just for testing. – t0s May 12 '15 at 13:19
  • It is your app. You are testing it. You can alter the src files for the mere purpose of testing and then revert back. – code May 12 '15 at 13:23
  • 1
    It's like saying I won't check if my website is hack-proof or not because Hacking is bad. – code May 12 '15 at 13:23
  • hehe :) ok you are right. What I think will be a problem is that I have to do this every time I change my code - I was thinking that maybe with some framework I wouldnt have to change something from my code. – t0s May 12 '15 at 13:26

5 Answers5

62

You can launch your next activity with a custom intent like this:

@RunWith(AndroidJUnit4.class)
public class NextActivityTest {

  @Rule
  public ActivityTestRule<NextActivity> activityRule 
     = new ActivityTestRule<>(
        NextActivity.class,
        true,     // initialTouchMode
        false);   // launchActivity. False to customize the intent

  @Test
  public void intent() {
    Intent intent = new Intent();
    intent.putExtra("your_key", "your_value");

    activityRule.launchActivity(intent);

    // Continue with your test
  }
}

Full example: https://github.com/chiuki/android-test-demo

Blog post: http://blog.sqisland.com/2015/04/espresso-21-activitytestrule.html

chiuki
  • 14,580
  • 4
  • 40
  • 38
  • Can I use this together with UiAutomator in order to test my notifications? – IgorGanapolsky Oct 25 '16 at 18:10
  • 1
    @chiuki I'm trying same code and it shows green, but when I'm adding `intended(hasComponent(NextActivity.class.getName()));` I got `NullPointerException: Attempt to invoke virtual method 'void android.support.test.espresso.intent.Intents.internalIntended(org.hamcrest.Matcher, android.support.test.espresso.intent.VerificationMode, java.util.List)' on a null object reference` – Roger Alien Dec 05 '17 at 21:40
  • As `ActivityTestRule` is deprecated, this Kotlin example may be helpful: https://stackoverflow.com/a/67929217/3692788 – JCarlosR Jun 10 '21 at 22:39
10

For Devs using AndroidX for testing, things are a bit changed.

This is an example UI Test case for testing whether my intended activity opens after clicking on the textview.

import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.matcher.ViewMatchers.withId
import com.softway.dhananjay.tournamentapp.tournament.TournamentActivity
import org.junit.Test

class MainActivityTest {

    @Test
    fun tournament_activity_starts_onClick_of_textView() {

        Intents.init()

        val activityScenario: ActivityScenario<MainActivity> =
            ActivityScenario.launch(MainActivity::class.java)


        activityScenario.moveToState(Lifecycle.State.RESUMED)

        onView(withId(R.id.startTextView)).perform(ViewActions.click())

        intended(hasComponent(TournamentActivity::class.java.name))

        Intents.release()

        activityScenario.moveToState(Lifecycle.State.DESTROYED)

    }
}
devDeejay
  • 5,494
  • 2
  • 27
  • 38
1

First, see this question : Android Monkey Runner

Then you can see these guides :Monkey Runner

It makesyou usePython to test your android activity outside of your source. So, you can trigger things and get to specific activitiesl like this :

#! /usr/bin/env monkeyrunner

from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
from random import randint

print "get device"
device = MonkeyRunner.waitForConnection()
package = 'my.packaget'
activity = 'my.package.activity'
runComponent = package + '/' + activity
device.startActivity(component=runComponent)

#use commands like device.touch and device.drag to simulate a navigation and open my activity

#with your activity opened start your monkey test
print "start monkey test"
for i in range(1, 1000):
    #here i go emulate only simple touchs, but i can emulate swiper keyevents and more... :D
    device.touch(randint(0, 1000), randint(0, 800), 'DOWN_AND_UP')

print "end monkey test"

save it and then run : monkeyrunner test.py

Community
  • 1
  • 1
code
  • 2,115
  • 1
  • 22
  • 46
1
private void launchApp(){
        // Launch the app
        Context context = InstrumentationRegistry.getContext();
        final Intent intent = context.getPackageManager()
                .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
        // Clear out any previous instances
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);

        // Wait for the app to appear
        device.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)),
                LAUNCH_TIMEOUT);
    }
Mkurbanov
  • 197
  • 3
  • 13
-2

You can use the intent to launch dialer activity using below code.

    @Rule    
public IntentsTestRule<DialerActivity> mActivityRule = new IntentsTestRule<>(
            DialerActivity.class);

    private static final String PHONE_NUMBER = "1234567890";
    private static final Uri INTENT_DATA_PHONE_NUMBER = Uri.parse("tel:" + PHONE_NUMBER);
    private static String PACKAGE_ANDROID_DIALER = "com.android.phone";

    static {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Starting with Android Lollipop the dialer package has changed. 

            PACKAGE_ANDROID_DIALER = "com.android.server.telecom";
        }
    }

    @Test    public void testDialerIntent()throws Exception
    {
        intending(not(isInternal())).respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));
        onView(withId(R.id.edit_text_caller_number)).perform(typeText(PHONE_NUMBER));
        onView(withId(R.id.button_call_number)).perform(click());
        intended(allOf(
                hasAction(Intent.ACTION_CALL),
                hasData(INTENT_DATA_PHONE_NUMBER),
                toPackage(PACKAGE_ANDROID_DIALER)));
    }


}

For more detailed description refer my blog post - http://qaautomated.blogspot.in/2016/02/how-to-test-dialer-activity-with.html

anuja jain
  • 1,367
  • 13
  • 19