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.
Related
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"));
}
I am using a LoaderManager to get some data and when it finishes a child fragment should be shown. In some cases this happens when the activity is already in paused state and can not perform the fragment transaction.
Is there a way to get the current state of the activity (seems to have a mResume flag)? Or do I have to maintain my own boolean?
The new Architecture Components allow you to do it with:
this.getLifecycle().getCurrentState()
A quick look in the Activity source code indicates that the Activity class does keep track on the resume state with the member mResumed. But since mResume is not public and isResumed() is hidden, we can't use them.
You can have a simple solution to provide you with that information for all your classes. Simply create a base Activity class that store the state. For example:
public class ActivityBase extends Activity {
private boolean mIsResumed = false;
#Override
public void onResume() {
super.onResume()
mIsResumed = true;
}
#Override
public void onPaused() {
super.onPaused()
mIsResumed = false;
}
public boolean isResumed() {
return mIsResumed
}
}
Simply extend this class with your class:
public class MyActivity extends ActivityBase {
private void onLoadDone() {
if (isResumed()) {
// Show the fragment
}
}
}
One way it could be achieved is by using breakpoints on your Activity (for instance, putting a breakpoint in your onResume method), and using the Evaluate Expression window that you can open by clicking a right click on your Debug menu window, and selecting it from there (OR SHIFT + F8) for mac. Once opened, you can intercept the current state (depending where your breakpoint is) using this line in your Evaluate Expression Window:
getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
If it returns true, that means your Activity is currently in the resume state.
If false, it's in another state.
They have plenty of other states you can play with, just check here
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 :)
I have tried almost all the solutions from SO but no success :(.
I have a simple myJavaClass.java with a couple of functions.
One of the functions in myJavaClass : startActivity() starts MyCustomActivity
public startActivity(Context context)
{
Intent intent = new Intent(context, MyCustomActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
}
This launches MyCustomActivity() as expected.
Now I have another function in myJavaClass.java to close/finish MyCustomActivity but it is not able to do so!
I have tried
Making MyCustomActivity SingleTop in manifest and creating the activity via an intent as above
Passing an activity instance to "this" in onCreate() of MyCustomActivity and calling MyCustomActivity.activity.finish() from myJava.class but that doesnt work as well
Please help me. I have been stuck here for hours now. I know the solution is very simple and conceptual but I am a newbie. Just building Java/Android concepts!
EDIT
MyCustomActivity
public Activity activity;
OnCreate()
{
...
this = activity;
}
MyJavaClass
public closeActivity(Context context)
{
Activity customActivity = MyCustomActivity.activity;
customActivity.finish();
}
I think that what you are trying to do is fundamentally bad. For a start, outside of the Activity code, there are no guarantees that the activity still exists - the memory manager may have cleaned it up, the user may have pressed Back etc. Think of Activities as independent entities - you can start them, and you can optionally get a result back when they finish what they're doing, but that's it.
Think about whether you really have to programmatically close the activity from outside it - I'd say this is an unusual design, but there are circumstances where it may be appropriate.
If so, what I think you want is a publish/subscribe system whereby MyCustomActivity can register a listener with MyJavaClass, and then receive a callback whereupon it can 'finish' itself.
public Activity activity implements FinishListener
{
public void onCreate(...)
{
//where does MyJavaClass come from? see in a minute
MyJavaClass myjava = getMyJavaclass();
myJava.addFinishListener( this );
}
public void onFinishCallback()
{
this.finish();
}
}
and
public class MyJavaClass
{
private List<FinishListener> finishListeners = ...;
public void addFinishListener( FinishListener fl )
{
this.finishListeners.add(fl);
}
public closeActivity(Context context)
{
for ( FinishListener fl : finishListeners )
{
fl.onFinishCallback();
}
}
}
and
public interface FinishListener
{
void onFinishCallback();
}
Now the only remaining issue is how to get MyJavaClass from the Activity. That's up to you - you may already know how, you may be able to put it in your Application implementation, it could be a singleton (bad), the listeners could be static (bad) or various other options.
Oh, and don't forget to remove the listener again in the Activity's onDestroy() method!
Just try this....
public closeActivity(Activity _activity)
{
_activity.finish();
}
you can't finish activity from other class until you have the reference of instance of Activity in that class, give the reference in that class and call finish() method to stop the activity.
activity.finish();
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.