尝试使用espresso实现Android的测试驱动开发

本文介绍如何使用Espresso进行Android UI测试驱动开发。通过具体示例,从搭建环境到实现测试案例,逐步引导读者掌握Espresso的基本用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

辛苦堆砌,转载请注明出处,谢谢!

espresso是google官方提供的测试框架,可以用来对Android的UI行为进行测试,详细的可以从espresso的官网查看相关的文档,地址如下:

https://google.github.io/android-testing-support-library/docs/espresso/intents/index.html


本文主要借助于espresso,主要提供一种Android进行测试驱动开发的思路,本人也是刚刚开始尝试使用测试驱动开发,不足之处还请见谅。使用espresso,注意build.gradle(module::app)的dependencies

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'

    androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
}

Demo很简单,MainActivity上有一个TextView,文本为Hello World,默认不可见的,点击一个Button,上有文本“点击”,可以切换TextView的可见性。我们先给出MainActivity的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center"
    tools:context="com.yjp.espressodemo.MainActivity">

    <TextView
        android:id="@+id/helloWorldTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/clickButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>
可以看到布局很基础,没有加入任何功能,只是给控件赋值了id,然后我们在androidTest测试目录添加一个类,内容如下:

package com.yjp.espressodemo;

import android.content.res.Resources;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
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.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {

    @Rule
    public IntentsTestRule<MainActivity> mIntentsRule=
            new IntentsTestRule<>(MainActivity.class);

    @Test
    public void viewTextTest() {
        Resources resources = mIntentsRule.getActivity().getResources();
        checkText(R.id.helloWorldTextView,  resources.getString(R.string.hello_world));
        checkText(R.id.clickButton, resources.getString(R.string.click));
    }

    private void checkText(int id, String text) {
        onView(withId(id)).check(matches(withText(text)));
    }
}
我们只有一个测试任务,viewTextTest,用来测试View上的文本是否符合要求,现在的话编译无法通过,我们在strings.xml中添加字符串资源。

<resources>
    <string name="app_name">EspressoDemo</string>
    <string name="hello_world">Hello World</string>
    <string name="click">点击</string>
</resources>
这个时候编译可以通过了,然后在该类的类文件上点击右键,单击Run 'MainActivityTest',运行测试,注意:该测试要有设备或者虚拟机才能正常运行。可以想到,测试不会通过,因为我们的文本不对。我们给控件添加文本,此时,布局变为

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center"
    tools:context="com.yjp.espressodemo.MainActivity">

    <TextView
        android:id="@+id/helloWorldTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"/>

    <Button
        android:id="@+id/clickButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/click"/>
</LinearLayout>
测试通过,然后我们添加新的测试方法

@Test
public void helloWorldTextViewGoneWhenStart() {
	checkVisibility(R.id.helloWorldTextView, ViewMatchers.Visibility.GONE);
}

private void checkVisibility(int id, ViewMatchers.Visibility visibility) {
	onView(withId(id))
			.check(matches(withEffectiveVisibility(visibility)));
}
我们要保证开始时候TextView不可见,是GONE的状态,运行测试,不会通过,我们为了使测试通过,在布局文件中给helloWorldTextView添加属性

android:visibility="gone"
再次运行测试,很好,通过了。再添加一个测试用例,看看点击一下clickButton的效果

@Test
public void clickClickButtonOnce() {
	clickButton(R.id.clickButton);
	checkVisibility(R.id.helloWorldTextView, ViewMatchers.Visibility.VISIBLE);
}

private void clickButton(int id) {
	onView(withId(id)).perform(click());
}
我们点击了一下按钮,判断TextView的可见性是否变化,运行测试无法通过,我们在MainActivity中onCreate中添加代码如下

final TextView helloWorldTextView = (TextView) findViewById(R.id.helloWorldTextView);
Button clickButton = (Button) findViewById(R.id.clickButton);
clickButton.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		helloWorldTextView.setVisibility(View.VISIBLE);
	}
});
运行测试,测试通过。你可能会有疑问,这样的代码,我们点击两次按钮不就不对了,的确如此,不过有点想多了,我们只要保证每一个测试用例通过就好了,我们添加新的测试用例

@Test
public void clickClickButtonTwice() {
	clickButton(R.id.clickButton);
	clickButton(R.id.clickButton);
	checkVisibility(R.id.helloWorldTextView, ViewMatchers.Visibility.GONE);
}
点击两下按钮,测试当然又不能通过,我们修改onClick的代码

@Override
public void onClick(View v) {
	if (helloWorldTextView.getVisibility() == View.GONE) {
		helloWorldTextView.setVisibility(View.VISIBLE);
	} else {
		helloWorldTextView.setVisibility(View.GONE);
	}
}

好了,我们的代码又通过测试了XD。至此,我们满足了开发需求。不过通过测试驱动开发的学习,个人感觉也有一定的负担,那就是对测试框架的学习,如果对测试框架不熟悉,可能导致在编写测试用例上花费很多的时间,项目被拖延很长时间,但是测试用例带来后续回归测试的好处是不言而喻的。















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值