Android Espresso

In this tutorial, we’ll be discussing Espresso Testing Framework for Testing the UI of Android Applications. We’ll be creating a basic login application with a few espresso tests.

在本教程中,我们将讨论用于测试Android应用程序UI的Espresso测试框架。 我们将使用一些意式浓缩咖啡测试来创建一个基本的登录应用程序。

Android Espresso (Android Espresso)

We’ve already discussed Android Unit Testing before.

我们已经讨论了Android的单元测试之前

Testing is an important area for building any product.

测试是制造任何产品的重要领域。

It helps us in:

它可以帮助我们:

  • Detecting bugs/cases not covered by our code.

    检测我们的代码未涵盖的错误/案例。
  • Keep manual user testing to minimal. No need to test the earlier features again and again manually.

    尽量减少手动用户测试。 无需一次又一次地测试早期功能。
  • Building robust applications with end cases covered.

    构建涵盖最终案例的强大应用程序。

Testing in Android majorly involves two types:

Android中的测试主要涉及两种类型:

  • Unit Tests

    单元测试
  • Instrumentation Tests

    仪器测试

Espresso comes under the second type. It is used to do automated UI testing by writing short and concise Android UI tests.

浓缩咖啡属于第二种类型。 它通过编写简短的Android UI测试来进行自动UI测试。

Let’s look at the components of the Espresso Instrumentation Testing Framework.

让我们看一下Espresso Instrumentation测试框架的组件。

ViewMatchers,ViewActions,ViewAssertions (ViewMatchers, ViewActions, ViewAssertions)

  • ViewMatchers – allows us to find a view in the view hierarchy.

    ViewMatchers –允许我们在视图层次结构中查找视图。
  • ViewActions – allows us to perform automated actions on the view. Such as clicks etc.

    ViewActions –允许我们对视图执行自动操作。 例如点击次数等
  • ViewAssertions – allows us to assert the state of the view.

    ViewAssertions –允许我们声明视图的状态。

A basic skeleton code of an Espresso Test is:

浓咖啡测试的基本框架代码是:

onView(ViewMatcher)
.perform(ViewAction)
.check(ViewAssertion)

Inside the onView we look for the id of the View.

onView内部,我们寻找View的ID。

It can be done using methods like:

可以使用以下方法来完成:

  • withId() – Pass the unique id

    withId() –传递唯一ID
  • withText() – Pass the text of the view. It searches for a view with the specified text.

    withText() –传递视图的文本。 它搜索具有指定文本的视图。

Inside perform we pass the action to be done on the View. Example:

perform内部,我们传递要在View上完成的操作。 例:

  • click() – Clicks the view passed in onView.

    click()click()在onView中传递的视图。
  • typeText() – Pass the string to be entered in the View. This is especially used in EditText.

    typeText() –传递要在视图中输入的字符串。 特别是在EditText中使用。
  • replaceText() – Replaces the current text with the string that’s passed.

    replaceText() –用传递的字符串替换当前文本。
  • closeSoftKeyboard() – Dismisses the keyboard.

    closeSoftKeyboard()closeSoftKeyboard()键盘。

Inside check we assert the states mainly using methods:

在内部check我们主要使用以下方法来声明状态:

  • matches

    matches
  • doesNotExist

    doesNotExist

For example we can Position View Assertions in the following ways:

例如,我们可以通过以下方式定位视图断言:

onView(withId(R.id.textView)).check(isRightOf(withText("Hello World")));
onView(withId(R.id.textView)).check(isBelow(withText("Hello World")));

Other methods for position assertions are:

位置声明的其他方法是:

isLeftAlignedWith
isAbove
isTopAlignedWith

isLeftAlignedWith
上面
isTopAlignedWith

Hamcrest Matchers are very powerful matchers. Hamcrest Matchers是非常强大的Matchers。
The following examples show that:
以下示例显示:
onView(withText(startsWith("Hello"))).perform(click()); 
onView(allOf(withId(R.id.textView),isDisplayed()));
onView(allOf(withId(R.id.textView),hasLinks()));

The last one checks whether the whole TextView is a link.

最后一个检查整个TextView是否为链接。

In the following section, we’ll create an android application and write our first espresso tests.

在以下部分中,我们将创建一个android应用程序并编写我们的第一个espresso测试。

Our android application would contain a basic login form with a username, phone number and confirm number fields. On pressing the Login Button, if the phone number fields don’t match we will show a Toast message.
If everything is fine, we’ll great the user with a Hello.

我们的android应用程序将包含一个基本的登录表单,其中包含用户名,电话号码和确认号码字段。 按下登录按钮后,如果电话号码字段不匹配,我们将显示一条Toast消息。
如果一切正常,我们将通过Hello向用户推荐。

浓咖啡测试入门 (Getting Started With Espresso Tests)

Add the following dependencies in the build.gradle file:

在build.gradle文件中添加以下依赖项:

androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

Add the following in the defaultConfig block :

在defaultConfig块中添加以下内容:

android{
...
defaultConfig{
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
...
}

AndroidJUnitRunner is the instrumentation runner. It is the entry point into running the Android Tests.

AndroidJUnitRunner是工具运行器。 这是运行Android测试的切入点。

Following is how our app’s build.gradle file looks :

以下是我们应用程序的build.gradle文件的外观:

Make sure you disable the Animations in your Android device before running Espresso tests.
Otherwise, the default screen animations may interfere with the tests. You can disable them from the Developer Options as shown below:

确保在运行Espresso测试之前禁用Android设备中的“动画”。
否则,默认的屏幕动画可能会干扰测试。 您可以从“开发人员选项”中禁用它们,如下所示:

项目结构 (Project Structure)

(Code)

The code for the activity_main.xml layout is given below:

下面给出了activity_main.xml布局的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:layout_margin="8dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/inUsername"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Username" />


    <EditText
        android:id="@+id/inNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Number"
        android:inputType="number" />

    <EditText
        android:id="@+id/inConfirmNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Confirm Number"
        android:inputType="number" />


    <Button
        android:id="@+id/btnLogin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="LOGIN" />


    <TextView
        android:id="@+id/txtLoginResult"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:gravity="center" />

</LinearLayout>

The code for the MainActivity.java class is given below:

MainActivity.java类的代码如下:

package com.journaldev.androidexpressobasics;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {


    EditText inUsername, inNumber, inConfirmNumber;
    Button btnLogin;
    TextView txtLoginResult;

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

        inUsername = findViewById(R.id.inUsername);
        inNumber = findViewById(R.id.inNumber);
        inConfirmNumber = findViewById(R.id.inConfirmNumber);

        btnLogin = findViewById(R.id.btnLogin);
        txtLoginResult = findViewById(R.id.txtLoginResult);


        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                if (TextUtils.isEmpty(inNumber.getText()))
                    Toast.makeText(getApplicationContext(), R.string.number_empty, Toast.LENGTH_SHORT).show();
                else if (!(inNumber.getText().toString().equals(inConfirmNumber.getText().toString())))
                    Toast.makeText(getApplicationContext(), R.string.toast_error, Toast.LENGTH_SHORT).show();
                else if (inUsername.getText().toString().trim().length() == 0)
                    Toast.makeText(getApplicationContext(), R.string.username_empty, Toast.LENGTH_SHORT).show();
                else
                    txtLoginResult.setText("Hello " + inUsername.getText().toString().trim());

            }
        });
    }
}

The code for the strings.xml file is given below:

下面给出了strings.xml文件的代码:

编写咖啡测试 (Writing Espresso Tests)

Espresso tests are written inside src | androidTest folder files.
By default, ExampleInstrumentedTest.java is created with a default test.

Espresso测试写在src中| androidTest文件夹文件。
默认情况下,使用默认测试创建ExampleInstrumentedTest.java

Let’s write one test inside it:

让我们在其中编写一个测试:

package com.journaldev.androidexpressobasics;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static android.support.test.espresso.Espresso.onView;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.*;

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {


    public static final String USERNAME_TYPED = "Anupam";

    public static final String LOGIN_TEXT = "Hello Anupam";

    @Test
    public void useAppContext() {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();
        assertEquals("com.journaldev.androidexpressobasics", appContext.getPackageName());
    }

    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
            MainActivity.class);

    @Test
    public void loginClickedSuccess() {
     
        onView(withId(R.id.inUsername))
                .perform(typeText(USERNAME_TYPED));
        onView(withId(R.id.inNumber))
                .perform(typeText("12345"));
        onView(withId(R.id.inConfirmNumber))
                .perform(typeText("12345"));

        onView(withId(R.id.btnLogin)).perform(click());
        onView(withId(R.id.txtLoginResult)).check(matches(withText(LOGIN_TEXT)));
    }
}

@Rule annotation is used to launch the MainActivity.
Inside loginClickedSuccess we wrote a successful login test case.

@Rule批注用于启动MainActivity。
loginClickedSuccess内部,我们编写了一个成功的登录测试用例。

Now let’s write two more tests in which we will test whether the Toast is shown correctly or not.

现在让我们再编写两个测试,其中将测试Toast是否正确显示。

Add the following methods inside the above class:

在上面的类中添加以下方法:

@Test
    public void shouldShowToastError() {
        onView(withId(R.id.inUsername))
                .perform(typeText(USERNAME_TYPED));
        onView(withId(R.id.inNumber))
                .perform(typeText("123456"));
        onView(withId(R.id.inConfirmNumber))
                .perform(typeText("12345"), closeSoftKeyboard());

        onView(withId(R.id.btnLogin)).perform(click());
        onView(withText(R.string.toast_error)).inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView())))).check(matches(isDisplayed()));
    }

    @Test
    public void shouldShowToastUsernameEmpty() {
        onView(withId(R.id.inNumber))
                .perform(typeText("12345"));
        onView(withId(R.id.inConfirmNumber))
                .perform(typeText("12345"));

        onView(withId(R.id.btnLogin)).perform(click());
        onView(withText(R.string.username_empty)).inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView())))).check(matches(isDisplayed()));
    }

The last line is used to check whether Toast is displayed with the correct string or not.

最后一行用于检查Toast是否显示正确的字符串。

To run the espresso test. Right click on the ExampleInstrumentationTest.java and press run to start the automated test on the emulator.

运行浓缩咖啡测试。 右键单击ExampleInstrumentationTest.java,然后按运行以在模拟器上启动自动化测试。

Following is the output of the application in action:

以下是实际应用程序的输出:

Following is the output in the console while the above automated UI test was running:

以下是上述自动化UI测试运行时控制台中的输出:

浓咖啡测试记录 (Espresso Test Recording)

You can record Espresso tests manually as well:

您也可以手动记录Espresso测试:

It will automatically create a new file with the espresso tests containing the manual clicks and actions you did in the device.

它将使用意式浓缩咖啡测试自动创建一个新文件,其中包含您在设备中进行的手动单击和操作。

This brings an end to this tutorial. You can download the project from the link below:

本教程到此结束。 您可以从下面的链接下载项目:

翻译自: https://www.journaldev.com/23067/android-espresso

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值