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测试框架。 我们将使用一些意式浓缩咖啡测试来创建一个基本的登录应用程序。
We’ve already discussed Android Unit Testing before.
我们已经讨论了Android的单元测试之前 。
Testing is an important area for building any product.
测试是制造任何产品的重要领域。
It helps us in:
它可以帮助我们:
Testing in Android majorly involves two types:
Android中的测试主要涉及两种类型:
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测试框架的组件。
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
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向用户推荐。
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设备中的“动画”。
否则,默认的屏幕动画可能会干扰测试。 您可以从“开发人员选项”中禁用它们,如下所示:
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文件的代码:
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测试运行时控制台中的输出:
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:
本教程到此结束。 您可以从下面的链接下载项目: