使用 uiautomator2.0 一段时间,总结一下一些使用。比如如何使用 android api 来加强自动化测试的效率和正确性。

首先看一下项目的目录结构:

红框为 uiautomator2.0 的项目结构。而 com.meizu.ltemtbf 实际其实就是一个 apk 工程。
所以我们可以在 uiautomator2.0 中直接调用 android api 来服务自动化测试。

初始化测试:

//@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
public class ApplicationTest {

    private static final String TEST_PACKAGE = "com.android.dialer";
    private static final int TIMEOUT = 5000;
    private static final String TAG = "benlee";
    private Context mContext;
    private Context appContext;
    private UiDevice mDevice;
    private TelephonyManager telephonyManager;

    //    @Before
    @Before
    public void before() {
        Log.i(TAG, "before");
        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        mContext = InstrumentationRegistry.getContext();
        appContext = InstrumentationRegistry.getTargetContext().getApplicationContext();
        //返回到桌面
        mDevice.pressHome();
    }

    @After
    public void after() throws IOException {
        Log.i(TAG, "after");
        mDevice.pressHome();
        //退出app
//        mDevice.executeShellCommand("am force-stop " + TEST_PACKAGE);
    }

其中:
appContext = InstrumentationRegistry.getTargetContext().getApplicationContext();
该行代码可以让 uiautomator2.0 获取当前 apk 的 Context 来调用相关 android api 方法。
要注意的是,这里获取的 Context 其实是测试 apk 本身的 Context,而非被测 apk 的 Context。

以下是使用 android api 的方式查询 uri 为"content://sms/sent"和"content://sms/inbox"对应字段,来确认短信是否成功发送/接收

public String getMessageStatus(String uri,String phonenum,String smstext) {
    //使用appContext
    ContentResolver cr = appContext.getContentResolver();
    Cursor cursor = cr.query(Uri.parse(uri), null, null, null, null);
    while(cursor.moveToNext()) {
        //根据发送/接收地址(手机号码)和短信内容,查询获取其短信的发送/接收状态
        int phoneColumn = cursor.getColumnIndex("address");
        int infoColumn = cursor.getColumnIndex("body");
        String num = cursor.getString(phoneColumn);
        String smsText = cursor.getString(infoColumn);
        if(num.contains(phonenum)&&smsText.equals(smstext)){
            int typeColumn = cursor.getColumnIndex("type");
            return cursor.getString(typeColumn);
        }
        else{
            Log.i(TAG,phonenum+":"+num+":"+smsText);
        }
    }
    cursor.close();
    return null;
}

然后我们就可以使用上述的方法在测试用例中应用:

@Test
    public void test003SMS() throws InstantiationException, IllegalAccessException {
        startApp("com.android.mms");
        findObjById("com.android.mms:id/create_new_btn").click();
        String num = getPhoneNumber();
        findObjById("com.android.mms:id/mz_recipient_edit").setText(num);
        mDevice.pressBack();
        SystemClock.sleep(1000);
        findObjById("com.android.mms:id/embedded_text_editor").setText("test003SMS");
        if (findObjById("com.android.mms:id/right_btn").isEnabled()) {
            findObjById("com.android.mms:id/right_btn").click();
        }
        //判断短信是否发送成功,返回为2,即发送成功
        boolean res = checkSmsStatus("content://sms/sent",getPhoneNumber(),"test003SMS","2");
        Assert.assertTrue(res);
        //判断短信是否接收成功,返回为1,即接收成功
        boolean inboxres = checkSmsStatus("content://sms/inbox",getPhoneNumber(),"test003SMS","1");
        Assert.assertTrue(inboxres);

        int count = mDevice.wait(Until.findObjects(By.text("test003SMS")), TIMEOUT).size();
        Assert.assertEquals(count,2);
    }

P.S:代码写的不怎么样,有些方法自己封装的。大家大概看得懂就好。: )

当然也要在 AndroidManifest.xml 上添加相应的权限。

<uses-permission android:name="android.permission.READ_SMS" />

后续:
会尝试应用 broadcast、service、多线程、aidl、binder 等的方式来提高自动化测试的效率和正确性。

有人可能觉得这样做自动化成本太高,但其实在实践的过程中是完全可以提升自己对 android 开发的理解,
这样也未尝是另一种提升的方式。


↙↙↙阅读原文可查看相关链接,并与作者交流