I actually tried to setup some unit test with Espresso and after some hours of research the app do only the click and get focus by the EditText but after that there is nothing
Caused by: android.support.test.espresso.AppNotIdleException: Looped for 1996 iterations over 60 SECONDS. The following Idle Conditions failed .
i've removed all animation & SwipeRefreshLayout cause i saw there is a bug with the swiperefresh
I actually use some callback for replace the current fragment in the Activity
if someone have some tips i'm out after 4 hours of searching u_u
Thanks you :)
My Gradle dependencies :
// App dependencies
compile 'com.android.support:support-annotations:23.3.0'
compile 'com.google.guava:guava:18.0'
// Testing-only dependencies
// Force usage of support annotations in the test app, since it is internally used by the runner module.
androidTestCompile 'com.android.support:support-annotations:23.3.0'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
I've added this on the defaultConfig :
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
There is my test :
@RunWith(AndroidJUnit4.class)
@LargeTest
public class HelloWorldEspressoTest {
public static final String USERNAME = "do_f";
@Rule
public ActivityTestRule<LoginActivity> mActivityRule = new ActivityTestRule(LoginActivity.class);
private LoginActivity mActivity = null;
@Before
public void setActivity() {
mActivity = mActivityRule.getActivity();
}
@Test
public void login_LoginActivity() {
onView(withId(R.id.menu_login)).perform(click());
onView(withId(R.id.login_username))
.perform(typeText(USERNAME), closeSoftKeyboard());
}
}
There is my activity :
public class LoginActivity extends AppCompatActivity
implements MenuFragment.OnFragmentInteractionListener {
private FragmentManager fm;
public static void newActivity(Activity activity)
{
Intent i = new Intent(activity, LoginActivity.class);
activity.startActivity(i);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
SharedPreferences sp = getSharedPreferences(Utils.SP, Context.MODE_PRIVATE);
if (!sp.getString(Utils.TOKEN, "null").equals("null"))
{
MainActivity.newActivity(this);
finish();
}
fm = getFragmentManager();
fm.beginTransaction()
.replace(R.id.container, MenuFragment.newInstance())
.addToBackStack(null)
.commit();
}
@Override
public void onBackPressed()
{
if (getFragmentManager().getBackStackEntryCount() > 1)
getFragmentManager().popBackStack();
else
super.onBackPressed();
}
@Override
public void showLogin() {
fm.beginTransaction()
.replace(R.id.container, LoginFragment.newInstance())
.addToBackStack(null)
.commit();
}
@Override
public void showRegister() {
fm.beginTransaction()
.replace(R.id.container, RegisterFragment.newInstance())
.addToBackStack(null)
.commit();
}
}
And my LoginFragment :
private static final String TAG = "LoginFragment";
@Bind(R.id.loading_spinner)
ProgressBar loading;
@Bind(R.id.content)
LinearLayout content;
@Bind(R.id.login_username)
EditText username;
@Bind(R.id.login_password)
EditText password;
public LoginFragment() {
}
public static LoginFragment newInstance() {
return new LoginFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.login_fragment_login, container, false);
ButterKnife.bind(this, v);
return v;
}
@Override
public void onActivityCreated(Bundle saveInstanceState) {
super.onActivityCreated(saveInstanceState);
}
@OnClick(R.id.login_submit)
public void onSubmit(View v)
{
if (username.getText().length() == 0
|| password.getText().length() == 0)
{
Snackbar.make(getView(), "blabla", Snackbar.LENGTH_SHORT).show();
return ;
}
//hideContent();
LoginPost p = new LoginPost(username.getText().toString(), password.getText().toString());
Call<LoginResponse> call = RestClient.get().login(p);
call.enqueue(new Callback<LoginResponse>() {
@Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
if (response.body() == null) {
String msg = getResources().getString(R.string.login_error_bad_credentials);
Snackbar.make(getView(), msg, Snackbar.LENGTH_SHORT).show();
//showContent();
} else {
SharedPreferences sp = getActivity().getSharedPreferences(Utils.SP, Context.MODE_PRIVATE);
sp.edit().putString(Utils.TOKEN, response.body().getToken()).apply();
sp.edit().putString(Utils.USERNAME, username.getText().toString()).apply();
MainActivity.newActivity(getActivity());
getActivity().finish();
}
}
@Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
Snackbar.make(getView(), "onFailure", Snackbar.LENGTH_SHORT).show();
//showContent();
}
});
}
I found the solution, the looped iterations was caused by this
<ProgressBar
android:id="@+id/loading_spinner"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:indeterminateTintMode="src_atop"
android:indeterminateTint="@color/ganjify"
android:alpha="0"
android:layout_gravity="center" />
Because i've not set the visibility to GONE when i don't use it !
loading.setVisibility(View.GONE);
Espresso is designed to wait until there are no pending UI animations or AsyncTasks in your application before proceeding with tests. From the docs, emphasis mine:
Espresso provides a sophisticated set of synchronization capabilities. This characteristic of the framework, however, applies only to operations that post messages on the MessageQueue, such as a subclass of View that's drawing its contents on the screen.
The most likely cause for the android.support.test.espresso.AppNotIdleException
is that there is an ongoing UI animation or AsyncTask which Espresso is waiting to finish.
For example if you have a ProgressBar element in your layout, you would need to set the visibility loading.setVisibility(View.GONE);
because Espresso interprets the element as an ongoing UI animation and there will wait for it to go away to proceed with testing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With