使用 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 开发的理解,
这样也未尝是另一种提升的方式。