Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How open tab in Espresso

How can i open tab in Espresso test? I tried to do Espresso.onView(ViewMatchers.withId(R.id.practice_results_tab)).perform(ViewActions.click());, but that doesn't working. In that code i opened Layout of this tab. There is the XML file:

    <TabHost
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/practice_tabHost">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
            </TabWidget>

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">

                <LinearLayout
                    android:id="@+id/practice_settings_tab"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:orientation="vertical">

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/practice_results_tab"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:orientation="vertical">

                </LinearLayout>
            </FrameLayout>
        </LinearLayout>
    </TabHost>

What ID should I use to open tab?

Error in logcat:

Caused by: java.lang.RuntimeException: Action will not be performed because the target     view does not match one or more of the following constraints:
at least 90 percent of the view's area is displayed to the user.
Target view: "LinearLayout{id=2131296384, res-name=practice_results_tab, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}"
like image 398
Drake Avatar asked Jul 29 '14 13:07

Drake


People also ask

What is the Espresso recording tool?

The Espresso Test Recorder tool lets you create UI tests for your app without writing any test code. By recording a test scenario, you can record your interactions with a device and add assertions to verify UI elements in particular snapshots of your app.

What is Espresso testing?

Espresso is an open source android user interface (UI) testing framework developed by Google. The term Espresso is of Italian origin, meaning Coffee. Espresso is a simple, efficient and flexible testing framework.

How do you assert espresso?

check is a method which accepts an argument of type ViewAssertion and do assertion using passed in ViewAssertion object. matches(withText(“Hello”)) returns a view assertion, which will do the real job of asserting that both actual view (found using withId) and expected view (found using withText) are one and the same.


3 Answers

Completed Code

You really need to add code for us to give a proper answer. I'm guessing here that you used a TabHost and TabWidget in the way this example does: https://maxalley.wordpress.com/2012/10/25/android-creating-a-tab-layout-with-tabhost-and-tabwidget/

I've created a sample project at https://github.com/hanscappelle/SO-25016397

Your Activity could then look like this:

public class MainActivity extends TabActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TabHost tabHost = getTabHost();

        // setNewTab(context, tabHost, tag, title, icon, contentID);
        this.setNewTab(this, tabHost, "tab1", R.string.textTabTitle1, R.drawable.ic_tab_settings, R.id.practice_settings_tab);
        this.setNewTab(this, tabHost, "tab2", R.string.textTabTitle2, R.drawable.ic_tab_results, R.id.practice_results_tab);

    }

    private void setNewTab(Context context, TabHost tabHost, String tag, int title, int icon, int contentID ){
        TabSpec tabSpec = tabHost.newTabSpec(tag);
        String titleString = getString(title);
        tabSpec.setIndicator(titleString, context.getResources().getDrawable(android.R.drawable.star_on));
        tabSpec.setContent(contentID);
        tabHost.addTab(tabSpec);
    }
}

I found another code example at https://maxalley.wordpress.com/2012/10/27/android-styling-the-tabs-in-a-tabwidget/ with a helper method that injects an ImageView for the tabs.

private View getTabIndicator(Context context, int title, int icon) {
        View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
        ImageView iv = (ImageView) view.findViewById(R.id.imageView);
        iv.setImageResource(icon);
        TextView tv = (TextView) view.findViewById(R.id.textView);
        tv.setText(title);
        return view;
    }

Now it gets interesting cause this way we can easily set an ID or a tag on these injected View objects and use these in Espresso.

A solution: Tag the view

If you adapt that helper to accept a tag for each view helper code will look something like this:

private View getTabIndicator(Context context, int title, int icon, int viewId, String viewTag) {
        View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
        ImageView iv = (ImageView) view.findViewById(R.id.image_view);
        iv.setImageResource(icon);
        TextView tv = (TextView) view.findViewById(R.id.text_view);
        tv.setText(title);
        tv.setTag(viewTag);
        return view;
    }

If you use only icons you can set the ID on the ImageView also.

And the Espresso code to click these tabs:

Espresso.onView(ViewMatchers.withTagValue(Matchers.is((Object)"tab1"))).perform(ViewActions.click());

Alternative Solution: using View IDs

If you go for IDs you need these IDs to be defined somewhere. Use a simple Android resource file with some ID definitions.

The view ID resource file, named /values/ids.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="tab1" type="id" />
</resources>

The adapted helper:

private View getTabIndicator(Context context, int title, int icon, int viewId, String viewTag) {
    View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
    ImageView iv = (ImageView) view.findViewById(R.id.image_view);
    iv.setImageResource(icon);
    TextView tv = (TextView) view.findViewById(R.id.text_view);
    tv.setText(title);
    tv.setId(viewId);
    return view;
}

If you use only icons you can set the ID on the ImageView also.

And the Espresso code to click these tabs:

Espresso.onView(ViewMatchers.withId(R.id.tab1)).perform(ViewActions.click());

About TabHosts in general

Why did you use this TabHost in the first place? Note that this class is deprecated by now. A ViewPager with tabs or the ActionBar might be better options depending on your use case.

Use the ViewHierarchy tool

In cases like this the first problem is often to find the proper view. For this use the View Hierarchy tool. It's part of the android SDK and lives in the tools directory.

You can start it from command line like this:

cd ANDROID_SDK_LOCATION/tools
hierarchyviewer

Or use Android Studio menu: Tools > Android > Android Device Monitor. Then open the Hierarchy View perspective from the menu in the device monitor: Window > Open Perspective > Hierarchy View .

I prefer the first option just because the Device Monitor does way too much for our intentions.

Now use the Layout View in combination with the View Properties view to find the ID and tags of the view you want.

Some instructions on this tool: http://developer.android.com/tools/debugging/debugging-ui.html

like image 106
hcpl Avatar answered Oct 27 '22 11:10

hcpl


the only thing that works for me is:

public void clickOnTab(String tabText) {    
    Matcher<View> matcher = allOf(withText(tabText),
                                  isDescendantOfA(withId(R.id.ll_tab_container)));
    onView(matcher).perform(click());    
}

where ll_tab_container is the linearlayout for my custom tab layout. and if you had a tab called "shopping" then you would pass that as the tabText.

like image 40
j2emanue Avatar answered Oct 27 '22 11:10

j2emanue


onView(withText("Your tab label")).perform(click())

like image 20
Ivo Stoyanov Avatar answered Oct 27 '22 12:10

Ivo Stoyanov