Android单元测试

       关于Android的单元测试,不仅仅可以确保某个模块的正确性,在比较大的项目当中,也可以保证整个项目的合理运行。其单元测试小到可以应用于一个Application,大到一个Activity中的内容。单元测试是否通过,在于给出一系列的输入,看输出的结果是否是我们所期望的。


       网上有许多关于单元测试的博客,大多都以demo的形式来呈现的,我们也不例外,这里只是简单介绍下有关于单元测试的一些基本内容,其实还有许多可以深入的地方,但我们这个例子只是对一些浅显内容的说明,辅助以一些注释。


首先最主要的是对配置文件的一些说明,在android工程中的AndroidMainFest.xml文件里,在<application 标签中加入<uses-library android:name="android.test.runner"这一句,相当于注册了相关的测试环境

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.cheng.myapplication" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".ResultActivity">
        </activity>

        <uses-library android:name="android.test.runner" />
    </application>

</manifest>

我们先从一个小的Application开始,就简单弄个加法运算的函数吧,放在一个类之中

public class UnitTestApplication extends Application{

    @Override
    public void onCreate(){
        super.onCreate();
    }

    @Override
    public void onTerminate(){
        super.onTerminate();
    }

    public int add(int firstNumber, int secondNumber){
        return firstNumber + secondNumber;
    }
}


其add函数就是我们所定义的函数了,接下来为这个函数写一个单元测试的类


public class UnitTestApplicationTest extends ApplicationTestCase<UnitTestApplication> {

    private UnitTestApplication unitTestApplication;

    public UnitTestApplicationTest() {
        //在构造函数中调用父类构造函数,参数为被测试的类
        super(UnitTestApplication.class);
    }

    @Override
    protected void setUp() throws Exception{
        super.setUp();
        createApplication();
        //获取待测试的UnitTestApplication
        unitTestApplication = getApplication();
    }

    //测试UnitTestApplication类中的add函数(注意测试函数的命名必须以test开头)
    public void testadd(){
        assertEquals(3, unitTestApplication.add(1, 2));
    }
}
这个类需要注意的几点:

1、测试类的构造函数调用父类的构造函数,其参数为被测试的类

2、在setUp函数中获取待测试的类

3、测试函数的命名必须以test开头





以上就是一个简单的application的测试类,下面我们来看看Activity的

我们这个Activity的功能十分简单,就一个输入用户名,密码的登录操作,界面截图过几天贴上

先来看看我们的xml布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <EditText
        android:id="@+id/user_name_et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入用户名"/>
    <EditText
        android:id="@+id/pass_word_et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入密码"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        
        <Button
            android:id="@+id/login_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="登录"/>

        <Button
            android:id="@+id/clear_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="清空"/>

    </LinearLayout>
    
</LinearLayout>


再来看看我们的主类MainActivity.java

public class MainActivity extends ActionBarActivity implements View.OnClickListener{

    private EditText mUserNameEt;
    private EditText mPassWordEt;
    private Button mLoginBtn;
    private Button mClearBtn;

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

        findView();
        setListener();
    }

    private void findView(){
        mUserNameEt = (EditText)findViewById(R.id.user_name_et);
        mPassWordEt = (EditText)findViewById(R.id.pass_word_et);
        mLoginBtn = (Button)findViewById(R.id.login_btn);
        mClearBtn = (Button)findViewById(R.id.clear_btn);
    }

    private void setListener(){
        mLoginBtn.setOnClickListener(this);
        mClearBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view){
        int id = view.getId();
        switch (id){
            case R.id.login_btn:
                Intent intent = new Intent(this, ResultActivity.class);
                intent.putExtra("userName", mUserNameEt.getText().toString());
                intent.putExtra("passWord", mPassWordEt.getText().toString());
                startActivity(intent);
                break;
            case R.id.clear_btn:
                mUserNameEt.setText("");
                mPassWordEt.setText("");
                break;
            default:
                break;
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}


主类其实就是只做了三件事:1、绑定控件  2、设置点击响应事件  3、实现响应事件的具体操作

输入用户名和密码,点击登录,就会跳到下个页面ResultActivity.java,显示输入过的用户名和密码,点击清空,就会清空输入的用户名和密码


再来看看ResultActivity.java类和其xml文件吧

public class ResultActivity extends Activity{

    private TextView mResultTv;
    private String mUserName;
    private String mPassWord;

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

        findView();

        //获取从MainActivity传来的intent信息
        Intent intent = getIntent();
        mUserName = intent.getStringExtra("userName");
        mPassWord = intent.getStringExtra("passWord");

        mResultTv.setText(mUserName+ " "+mPassWord);
    }

    private void findView(){
        mResultTv = (TextView)findViewById(R.id.result_tv);
    }

}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</LinearLayout>


好了,接下来可以实现我们对这个MainActivity的测试类了

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity>{

    private Instrumentation mInstrumentation;
    private MainActivity mMainActivity;

    private EditText mUserNameEt;
    private EditText mPassWordEt;
    private Button mLoginBtn;
    private Button mClearBtn;

    public MainActivityTest(){
        super(MainActivity.class);
    }

    @Override
    protected void setUp() throws Exception{
        super.setUp();
        setActivityInitialTouchMode(false);
        mInstrumentation = getInstrumentation();
        mMainActivity = getActivity();

        mUserNameEt = (EditText)mMainActivity.findViewById(R.id.user_name_et);
        mPassWordEt = (EditText)mMainActivity.findViewById(R.id.pass_word_et);
        mLoginBtn = (Button)mMainActivity.findViewById(R.id.login_btn);
        mClearBtn = (Button)mMainActivity.findViewById(R.id.clear_btn);
    }

    //输入相关信息
    public void input(){
        //用户名操作
        mMainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mUserNameEt.requestFocus();
                mUserNameEt.performClick();
            }
        });

        mInstrumentation.waitForIdleSync();

        //输入用户名
        sendKeys(KeyEvent.KEYCODE_1, KeyEvent.KEYCODE_2, KeyEvent.KEYCODE_3);

        //密码操作
        mMainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mPassWordEt.requestFocus();
                mPassWordEt.performClick();
            }
        });

        //输入密码
        sendKeys(KeyEvent.KEYCODE_1, KeyEvent.KEYCODE_2, KeyEvent.KEYCODE_3);
    }

    //测试输入信息
    public void testInput(){
        input();
        assertEquals("123", mUserNameEt.getText().toString());
        assertEquals("123", mPassWordEt.getText().toString());
    }

    //测试登录按钮
    public void testLogin(){
        input();
        mInstrumentation.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                mLoginBtn.requestFocus();
                mLoginBtn.performClick();
            }
        });
    }

    //测试清空按钮
    public void testClear(){
        input();
        mInstrumentation.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                mClearBtn.requestFocus();
                mClearBtn.performClick();
            }
        });

        assertEquals("", mUserNameEt.getText().toString());
        assertEquals("", mPassWordEt.getText().toString());
    }
}

其测试流程都按照我们实际的操作流程来进行,首先肯定是输入用户名和密码的操作,在input函数中,我调用了sendKeys函数,让系统测试的时候自动输入函数中的参数内容。

一共有三个测试函数,分别测试了输入的信息testInput,登录按钮testLogin,清空按钮testClear。

如果全部测试通过的话,那么系统的进度条会显示的是绿色样式,如果有其中一个不过,就说明输出的结果并不是正确的期望结果,进度条为红色样式。


此篇文章只浅显的讲了单元测试的一些基本流程,以后本人还会更加深入探索。






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值