Android Espresso Testing - Checking Buttons - android

So I've written a basic test for my homescreen right now that checks if the three buttons on the homescreen are clickable. I was wondering how I would check to see if each of the buttons go to the right activity when they are clicked.
#RunWith(AndroidJUnit4.class)
#SmallTest
public class HomeScreenTest {
#Rule
public ActivityTestRule<StartActivity> mActivityRule = new ActivityTestRule<>(StartActivity.class);
#Test
public void testButton() {
Espresso.onView(withId(R.id.event_button)).check(matches(isClickable()));
Espresso.onView(withId(R.id.navigation_button)).check(matches(isClickable()));
Espresso.onView(withId(R.id.alarm_button)).check(matches(isClickable()));
}
}

two options for you.
assert on the next activity component to see it is correctly showing. or,
You probably need to test the Intent that you are sending through button clicks.
see https://google.github.io/android-testing-support-library/docs/espresso/intents/
#Test
public void validateIntentSentToPackage() {
user.clickOnView(system.getView(R.id.callButton));
intended(toPackage("com.android.phone"));
}

Related

Espresso: How do i assert if a particular activity is launched when i click on a item using espresso

How do I assert an activity in Espresso after I click on a view item?
onView(withId(com.example.android.notepad.R.id.XYZ)).perform(click());
You should simulate the process of clicking a button and then test if the activity at the top of the stack is the one you're looking for
#RunWith(AndroidJUnit4.class)
public class YourTestClass{
#Test
public void testButton() {
Espresso.onView(ViewMatchers.withId(R.id.yourButtonId)).perform(ViewActions.click());
Assert.assertEquals(getActivityInstance().getClass(), YourActivityThatShouldStart.class);
}
private Activity getActivityInstance() {
final Activity[] currentActivity = {null};
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
if (resumedActivities.iterator().hasNext()) {
currentActivity[0] = (Activity) resumedActivities.iterator().next();
}
}
});
return currentActivity[0];
}
}
On the testButton function, there are two lines, the first one to click on your button, the second one is to check the resulting activity
Espresso works on the main thread so your fine
Inside your tests you probably have this:
#Rule
public ActivityTestRule<MyActivity> testRule = new ActivityTestRule<>(MyActivity.class);
Then you can call:
testRule.getActivity()
to obtain instance of Activity.
the just call
testRule.getActivity() instanceof MyActivity

Android, EspressoTesting with Multiple Activity

I want to access multiple Activity in my Instrumental testing.
e.g Login -> Search-> Listing-> Detail Activity
I have achieved till 'Listing activity' but i want to go for Listing Activity Element[1]'s Detail page.
Below is my code for
#RunWith(AndroidJUnit4.class)
public class ContactSearchScreeenTest extends ActivityInstrumentationTestCase2<ContactSearchScreen> {
public ContactSearchScreeenTest() {
super(ContactSearchScreen.class);
}
#Rule
public ActivityTestRule<ContactSearchScreen> mActivityRule =
new ActivityTestRule<>(ContactSearchScreen.class);
#Override
protected void setUp() throws Exception {
super.setUp();
}
#Test
public void sendToSearchResultActivity()
{
onView(withId(R.id.etSearchName))
.perform(typeText("ssasa"), pressKey(KeyEvent.KEYCODE_SEARCH));
GlobalClass globalVariable = (GlobalClass) mActivityRule.getActivity().getApplicationContext();
globalVariable.setSearchStr("ssasa");
mActivityRule.getActivity().callForNextSearchActivity();
}
}
Additional Functional
#Override
public void callForNextSearchActivity() {
Intent intent = new Intent(getBaseContext(), SearchResultsActivity.class);
final GlobalClass globalVariable = (GlobalClass) getApplicationContext();
globalVariable.setSearchStr(getSearchStringFromSearchEditText());
startActivity(intent);
overridePendingTransition(R.anim.pull_in_right, R.anim.push_out_left);
}
Is it possible to have multi activity layer in Espresso testing?
If Yes .. How?
Yes, it is possible. In one of the samples they have demoed this.
https://code.google.com/p/android-test-kit/source/browse/testapp_test/src/main/java/com/google/android/apps/common/testing/ui/testapp/BasicTest.java#52][1]
public void testTypingAndPressBack() {
// Close soft keyboard after type to avoid issues on devices with soft keyboard.
onView(withId(R.id.sendtext_simple))
.perform(typeText("Have a cup of Espresso."), closeSoftKeyboard());
onView(withId(R.id.send_simple))
.perform(click());
// Clicking launches a new activity that shows the text entered above. You don't need to do
// anything special to handle the activity transitions. Espresso takes care of waiting for the
// new activity to be resumed and its view hierarchy to be laid out.
onView(withId(R.id.display_data))
.check(matches(withText(("Have a cup of Espresso."))));
// Going back to the previous activity - lets make sure our text was perserved.
pressBack();
onView(withId(R.id.sendtext_simple))
.check(matches(withText(containsString("Espresso"))));
}
Read the inline comment.

How to test swiping between Activities in Espresso?

I am creating a test in Espresso that calls swipeRight() to go to the MainActivity where behavior is set before returning to ConsumerSettingsActivity to test Views. However, the issue is that after calling the swipe, I get a NoActivityResumedException that points to the second tested line with R.id.mode_text.
#RunWith(AndroidJUnit4.class)
public class ConsumerSettingsActivityTest {
private ConsumerSettingsActivity mConsumerSettingsActivity;
#Rule
public ActivityTestRule<ConsumerSettingsActivity> mActivityTestRule =
new ActivityTestRule<>(ConsumerSettingsActivity.class);
#Before
public void initialize() {
mConsumerSettingsActivity = mActivityTestRule.getActivity();
}
#Test
public void checkCorrectButtonsAreClickableInPhotoModeThenReturnToMainActivity() {
// swipe to MainActivity and set behavior
onView(allOf(withId(R.id.settings_top_bar), isDisplayed())).perform(swipeRight());
onView(withId(R.id.mode_text)).perform(click());
onView(withId(R.id.photo_mode)).perform(click());
// test ratio Views
onView(withId(R.id.ratio_full)).check(matches(isClickable()));
onView(withId(R.id.ratio_full)).perform(click());
onView(withId(R.id.ratio_square)).check(matches(isClickable()));
onView(withId(R.id.ratio_square)).perform(click());
...
}
}
Short answer: MainActivity was called without being created.
Long answer: When ConsumerSettingsActivity called swipe to change to MainActivity, the actual swiping called finish(). Since MainActivity was not created, a NoActivityResumedException was thrown. To solve this, the test was changed to start with MainActivity, where it would then swipe to ConsumerSettingsActivity. Also, I did not need to make the thread sleep to be able to swipe between Activities.

two robotium test case, but the second hang there not responding(in JUnit View)

I managed to write two test cases in my XXTest.java with robotium-solo-3.2.1.jar included, luckily in JUnit view it shows the first one is done, which the device exactly worked (on emulator too).
Then it proceed to the second one, but it just hanging there forever! sorry I can't attach screen shot with my account.
here are my code:
public class XXTest extends ActivityInstrumentationTestCase2<SignInActivity> {
private Solo solo;
private Activity mActivity;
private static final String account = "someone";
private static final String pwd = "123456";
#SuppressWarnings("deprecation")
public XXTest() {
super("com.acompany.android", SignInActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
this.mActivity = getActivity();
solo = new Solo(getInstrumentation(), mActivity);
}
#Smoke
public void testLogIn() throws Exception {
EditText accountInput = (EditText) solo.getView(R.id.edit_account);
EditText pwdInput = (EditText) solo.getView(R.id.edit_password);
solo.clearEditText(accountInput);
solo.clearEditText(pwdInput);
solo.enterText(accountInput, account);
solo.enterText(pwdInput, pwd);
solo.clickOnButton(mActivity.getResources()
.getString(R.string.text_sign_in));
solo.waitForActivity("MainActivity");
solo.assertCurrentActivity("Expect MainActivity shown...", "MainActivity");
boolean expected = true;
boolean actual = solo.searchButton(mActivity.getResources().getString(
R.string.welcome_dialog_start));
assertEquals("find friend dialog not shown", expected, actual);
}
#Smoke
public void testOpenPref() throws Exception {
solo.goBack();
solo.clickOnMenuItem(mActivity.getResources().getString(
R.string.text_preferences));
solo.assertCurrentActivity("Expected PrefActivity..", "PrefActivity");
solo.goBackToActivity("MainActivity");
solo.assertCurrentActivity("Expected MainActivity..", "MainActivity");
}
protected void tearDown() throws Exception {
super.tearDown();
}
}
I've searched the sample of NotePadTest.java from Robotium tutorial, those 3 test cases in it are just work fine!
Please tell me where goes wrong?? Am I missing something somewhere? why the second test case not running?
btw. Can there be more than one class extends ActivityInstrumentationTestCase2 in a test project? curious!
You need to use solo.finishOpenedActivities() in your tearDown().
#Robert - this is the issue with Activity testing itself , not to robotium specific .
For the first test method:
the basic flow you is like below:
1>in the setUp() method load the main activity (say MainActivity) > do some ops in your testMethod1() - that results to land you in another activity ( say AnotherActivity) > and in tearDown() you kill the launched activity in setUp() method which is MainActivity
note: but AnotherActivity remains live
For the second test method:
the basic flow you is like below:
2>in the setUp() method try loading the main activity (say MainActivity) again ,although the previously launched AnotherActivity is not yet got killed, so it hangs there , It doesnt even enter the testMethod2() fr execution -
note: the eclipse graphical runner shows it hangs while the execution marker points to the testMethod2() , people thinks that it got stuck in testMethod2() - but the problem lies in setUp() for testMethod2() not in testMethod2() itself.
Solution:
1>Just keep a look on your cross activity navigation - at the end of each testMethod() use solo.goBack() to come back to the same main activity MainActivity from your current Activity ( you got landed in because of your actions)
results - at the end of testMethod1() only the main activity which was opened in setUP() remains. So it gets killed successfully .No Activity remains alive and for the testMethod2().The setUP() is able to load the MainActivity again without a hang - and testMethod2() gets executed .
hope it clarifies :)

Is Robolectric able to assert that methods have been invoked?

I've got a button defined in my layout as follows :
<Button
android:id="#+id/speakButton"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="#string/speak"
android:onClick="speak"
/>
The onClick binds to a method in my activity, such as :
public void speak(View v)
{
// Do my stuff here
}
Using Robolectric, I'm able to create a simple test class for that activity, I'd like to know if its possible that I could have a test that invokes the button, and ensures the method in my activity was invoked OK.
(I've got a whole bunch of buttons throughout my app, so intending to have tests to ensure they are wired up correctly, unless anyone has any suggestions as to why I shoudln't bother)
#RunWith(RobolectricTestRunner.class)
public class MyActivityTest
{
private MyActivitymActivity;
private Button speakButton;
#Before
public void setUp() throws Exception
{
mActivity = new MyActivity();
mActivity.onCreate(null);
speakButton = (Button) mActivity.findViewById(com.jameselsey.apps.androidsam.R.id.speakButton);
}
#Test
public void testButtonsVisible()
{
assertThat(speakButton.getVisibility(), equalTo(View.VISIBLE));
}
#Test
public void buttonsInvokeIntendedMethods()
{
// Unsure how to implement this test
}
}
I've never used them but I believe you can do this with the TouchUtils class. Here is a link to the Android TouchUtils docs. In particular you should look at the clickView method.

Categories

Resources