Skip to main content

Posts

Showing posts from 2015

Writing ViewHolder Matcher with Espresso for Android.

Recently I had a need to adapt my Espresso tests to operate on RecyclerView after migration from ListViews. The current actions that are available for RecyclerView based on item position working fine but I don't like to be dependent on position since data in my tests is created dynamically. I've googled the ViewHolder matchers and found only this link without any practical examples -  RecyclerViewActions . Then based on already created Matcher<Object> used in onData(...) I've created Matcher<VH> which was not so difficult. Let's assume each item in RecyclerView adapter has subject, represented by TextView. The below matcher will search for item in RecylerView with unique subject which I provide into matcher. Feel free to use it: public static Matcher<RecyclerView.ViewHolder> withItemSubjectInViewHolder(final String itemSubject) { Checks.checkNotNull(itemSubject); return new BoundedMatcher (RecyclerView.ViewHolder, MyListRecyclerViewIt

Espresso & UIAutomator - the perfect tandem

Espresso for Android is perfect and fast test automation framework, but it has one important limitation - you are allowed to operate only inside your app under test context. That means that it is not possible to automate tests for such app features like: application push notifications contact synchronization navigating from another app to your app under test, since you have to deal with other apps from the mobile device - Notification Bar, Contacts or People app, etc.  In fact it wasn't  possible until the release of UIAutomator 2.0. As stated in Android Developers blog post  - "... Most importantly, UI Automator is now based on Android Instrumentation... ".  And because of that we can run UIAutomator tests as well as Espresso tests using Instrumentation test runner. In addition to that we can combine UIAutomator tests together with Espresso tests and this gives us the real power and control over the phone and application under test. In the below exampl

Discovering Espresso for Android: wading through the hierarchical thicket

The Android Lollipop update brought a hard nut to crack for the testers who use Espresso, represented by RecyclerView. So far the app I'm testing contains this element in couple of places. While I was writing tests for them I found out that it was not so easy and obvious. Thanks to Espresso authors, version 2.0 has the basic RecyclerView actions support which is honestly not enough and is not convenient sometimes. The example of RecyclerView action: import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; . . @Test public void testSomething() { onView(withId(R.id.recycler_view_id)).perform(actionOnItemAtPosition(1, click())); } The activity under test has the following structure - it contains the RecyclerView element which is populated with some data. Let's call it the Feed. Each element in Feed is the Feed Post represented by FrameLayout. Of course every FrameLayout has the same layout elements inside as it's

Discovering Espresso for Android: Espresso 2.0 and 'Class ref in pre-verified class resolved to unexpected implementation' error

This time I would like to share with you solution for 'Class ref in pre-verified class resolved to unexpected implementation' issue I got while I was testing my multi-module project. Espresso tests were failing with below issue when I wanted to operate on RecyclerView from com.android.support:appcompat-v7. In my case RecyclerView dependency was defined not in the core-app module (the core module of the app) but in the other one which is set as a library. java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation at com.my.app.fragments.MyFragment.onCreateView(MyFragment.java:190) at android.support.v4.app.Fragment.performCreateView(Fragment.java:1786) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739) at android.support.v4.app.FragmentManagerImpl.

Discovering Espresso for Android: Espresso 2.0 and java.lang.NoClassDefFoundError

Currently I'm moving all my tests to Espresso 2.0 and Junit4. And today I was struggling with one nasty issue that you can face with as well and found the solution. So, the problem was noticed on pre-Lollipop devices/emulators. My app under test is configured to target the current latest API level 21. And after adapting some tests to Espresso 2.0 and JUnit4 I was able to successfully run it on emulator with Lollipop but trying to run it on devices/emulators lower then API 21 was failing with below issue: java.lang.NoClassDefFoundError: com.my.app.activities.MyActivity at com.my.app.test.instrumentation.TestMyActivity. (MyActivity.java:52) at java.lang.reflect.Constructor.constructNative(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:417) . . . And solution is to add below peace of code into your build.gradle: configurations { androidTestCompile.exclude group: 'com.android.support', module: 'support-v4' } :)