Android Espresso

时间:2020-02-23 14:28:54  来源:igfitidea点击:

在本教程中,我们将讨论用于测试Android应用程序UI的Espresso测试框架。
我们将创建一个基本的登录应用程序,并进行一些Espresso测试。

Android Espresso

之前我们已经讨论过Android单元测试。

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

它可以帮助我们:

  • 检测我们的代码未涵盖的错误/案例。

  • 尽量减少手动用户测试。
    无需一次又一次地测试较早的功能。

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

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

  • 单元测试
  • 仪器测试

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

让我们看一下Espresso工具测试框架的组成部分。

ViewMatchers,ViewActions,ViewAssertions

  • ViewMatchers –允许我们在视图层次结构中查找视图。

  • ViewActions –允许我们对视图执行自动操作。
    例如点击次数等

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

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

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

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

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

  • withId()–传递唯一的ID
  • withText()-传递视图的文本。
    它搜索具有指定文本的视图。

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

  • click()–单击在onView中传递的视图。

  • typeText()–传递要在View中输入的字符串。
    特别是在EditText中使用。

  • replaceText()–用传递的字符串替换当前文本。

  • closeSoftKeyboard()–关闭键盘。

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

  • matches
  • doesNotExist

我们也可以使用Espresso测试来测试视图层次。

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

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

位置声明的其他方法有:

isLeftAlignedWith isAbove isTopAlignedWith

Hamcrest Matchers是非常强大的Matchers。
以下示例显示:

onView(withText(startsWith("Hello"))).perform(click()); 
onView(allOf(withId(R.id.textView),isDisplayed()));
onView(allOf(withId(R.id.textView),hasLinks()));

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

在以下部分中,我们将创建一个android应用程序并编写我们的第一个意式浓缩咖啡测试。

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

Espresso测试入门

在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'

在defaultConfig块中添加以下内容:

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

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

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

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

代码

下面给出了" 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>

MainActivity.java类的代码如下:

package com.theitroad.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());

          }
      });
  }
}

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

编写Espresso测试

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

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

package com.theitroad.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.theitroad.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批注用于启动MainActivity。
在" loginClickedSuccess"内部,我们编写了一个成功的登录测试用例。

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

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

@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()));
  }

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

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

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

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

Espresso测试记录

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

它将使用Espresso测试自动创建一个新文件,其中包含您在设备中执行的手动单击和操作。