在工作中需要在沒有項(xiàng)目源碼的情況下直接使用robotium測試目標(biāo)android平臺launcher,平臺的版本基于當(dāng)前最新的android 4.4.2。之前在驗(yàn)證可行性的時(shí)候使用本人同樣使用android4.4.2的測試手機(jī)htc incredable s針對一個(gè)只有apk的notepad應(yīng)用做過同樣的驗(yàn)證,在測試手機(jī)上運(yùn)行完全沒有問題。該測試代碼如下:
成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的河池網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
package com.example.android.notepad.tryout; import com.robotium.solo.Solo; import android.test.ActivityInstrumentationTestCase2; import android.widget.TextView; import android.app.Activity; @SuppressWarnings("rawtypes") public class NotePadTest extends ActivityInstrumentationTestCase2{ private static Solo solo = null; public Activity activity; private static final int NUMBER_TOTAL_CASES = 2; private static int run = 0; private static Class> launchActivityClass; //對應(yīng)re-sign.jar生成出來的信息框里的兩個(gè)值 private static String mainActiviy = "com.example.android.notepad.NotesList"; private static String packageName = "com.example.android.notepad"; static { try { launchActivityClass = Class.forName(mainActiviy); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public NotePadTest() { super(packageName, launchActivityClass); } @Override public void setUp() throws Exception { //setUp() is run before a test case is started. //This is where the solo object is created. super.setUp(); //The variable solo has to be static, since every time after a case's finished, this class TCCreateNote would be re-instantiated // which would lead to soto to re-instantiated to be null if it's not set as static //TextView title = (TextView)getActivity().findViewById(Ref.id.title); if(solo == null) { NotePadTest.solo = new Solo(getInstrumentation(),getActivity()); } } @Override public void tearDown() throws Exception { //Check whether it's the last case executed. run += countTestCases(); if(run >= NUMBER_TOTAL_CASES) { solo.finishOpenedActivities(); } } public void testAddNoteCNTitle() throws Exception { //Thread.sleep(5000); solo.clickOnMenuItem("Add note"); solo.enterText(0, "中文標(biāo)簽筆記"); solo.clickOnMenuItem("Save"); solo.clickInList(0); solo.clearEditText(0); solo.enterText(0, "Text 1"); solo.clickOnMenuItem("Save"); solo.assertCurrentActivity("Expected NotesList Activity", "NotesList"); solo.clickLongOnText("中文標(biāo)簽筆記"); solo.clickOnText("Delete"); } public void testAddNoteEngTitle() throws Exception { solo.clickOnMenuItem("Add note"); solo.enterText(0, "English Title Note"); solo.clickOnMenuItem("Save"); solo.clickInList(0); solo.clearEditText(0); solo.enterText(0, "Text 1"); solo.clickOnMenuItem("Save"); solo.assertCurrentActivity("Expected NotesList Activity", "NotesList"); solo.clickLongOnText("English Title Note"); solo.clickOnText("Delete"); } }
@Override public void setUp() throws Exception { //setUp() is run before a test case is started. //This is where the solo object is created. super.setUp(); //The variable solo has to be static, since every time after a case's finished, this class TCCreateNote would be re-instantiated // which would lead to soto to re-instantiated to be null if it's not set as static if(solo == null) { NotePadTest.solo = new Solo(getInstrumentation(),getActivity()); } }
/** * Utility method for launching an activity with a specific Intent. * *NOTE: The parameter pkg must refer to the package identifier of the * package hosting the activity to be launched, which is specified in the AndroidManifest.xml * file. This is not necessarily the same as the java package name. * * @param pkg The package hosting the activity to be launched. * @param activityCls The activity class to launch. * @param intent The intent to launch with * @return The activity, or null if non launched. */ @SuppressWarnings("unchecked") public final
T launchActivityWithIntent( String pkg, Class activityCls, Intent intent) { intent.setClassName(pkg, activityCls.getName()); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); T activity = (T) getInstrumentation().startActivitySync(intent); getInstrumentation().waitForIdleSync(); return activity; }
/** * Synchronously wait for the application to be idle. Can not be called * from the main application thread -- use {@link #start} to execute * instrumentation in its own thread. */ public void waitForIdleSync() { validateNotAppThread(); Idler idler = new Idler(null); mMessageQueue.addIdleHandler(idler); mThread.getHandler().post(new EmptyRunnable()); idler.waitForIdle(); }這里按照本人的理解做的事情大概如下:
solo = new Solo(getInstrumentation());因?yàn)槲覀兊膌auncher在robotium在kill掉原來的launcher進(jìn)程的時(shí)候就會自動(dòng)起來,所以并不需要手動(dòng)的去getActivity()去啟動(dòng)。這種方法在不能啟動(dòng)起來的apk如notepad上面就不行,不信你去掉getActivity()的調(diào)用,保證notepad不會啟動(dòng)或者放到前臺。但是如果你在開始測試前先把notepad手動(dòng)起來并放到前臺,測試還是會正常進(jìn)行的。比如以下的驗(yàn)證性代碼:
package com.example.android.notepad.tryout; import com.robotium.solo.Solo; import android.test.ActivityInstrumentationTestCase2; import android.widget.TextView; import android.app.Activity; @SuppressWarnings("rawtypes") public class NotePadTest extends ActivityInstrumentationTestCase2{ private static Solo solo = null; public Activity activity; private static final int NUMBER_TOTAL_CASES = 2; private static int run = 0; private static Class> launchActivityClass; //對應(yīng)re-sign.jar生成出來的信息框里的兩個(gè)值 private static String mainActiviy = "com.example.android.notepad.NotesList"; private static String packageName = "com.example.android.notepad"; static { try { launchActivityClass = Class.forName(mainActiviy); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public NotePadTest() { super(packageName, launchActivityClass); } @Override public void setUp() throws Exception { //setUp() is run before a test case is started. //This is where the solo object is created. super.setUp(); //The variable solo has to be static, since every time after a case's finished, this class TCCreateNote would be re-instantiated // which would lead to soto to re-instantiated to be null if it's not set as static //TextView title = (TextView)getActivity().findViewById(Ref.id.title); if(solo == null) { NotePadTest.solo = new Solo(getInstrumentation());//, getActivity()); } } @Override public void tearDown() throws Exception { //Check whether it's the last case executed. run += countTestCases(); if(run >= NUMBER_TOTAL_CASES) { solo.finishOpenedActivities(); } } public void testAddNoteCNTitle() throws Exception { //getActivity(); Thread.sleep(5000); solo.clickOnMenuItem("Add note"); solo.enterText(0, "中文標(biāo)簽筆記"); solo.clickOnMenuItem("Save"); solo.clickInList(0); solo.clearEditText(0); solo.enterText(0, "Text 1"); solo.clickOnMenuItem("Save"); solo.assertCurrentActivity("Expected NotesList Activity", "NotesList"); solo.clickLongOnText("中文標(biāo)簽筆記"); solo.clickOnText("Delete"); } }初始化solo的時(shí)候和testcase里面都沒有去調(diào)用getActivity(),但是在testcase開始前先睡眠5秒,如果在這5秒的過程中你手動(dòng)把notepad給啟動(dòng)起來,那么睡眠時(shí)間過后測試會繼續(xù)正常運(yùn)行。
@Override public MyActivity getActivity() { if (mActivity == null) { Intent intent = new Intent(getInstrumentation().getTargetContext(), MyActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // register activity that need to be monitored. monitor = getInstrumentation().addMonitor(MyActivity.class.getName(), null, false); getInstrumentation().getTargetContext().startActivity(intent); mActivity = (MyActivity) getInstrumentation().waitForMonitor(monitor); setActivity(mActivity); } return mActivity; }鑒于本人現(xiàn)在只是做前期的可行×××,夠用就好,且周末手頭上也沒有目標(biāo)機(jī)器在手進(jìn)行驗(yàn)證,所以有興趣的朋友就自己去嘗試下吧,
作者 | 自主博客 | 微信 | CSDN |
天地會珠海分舵 | http://techgogogo.com | 服務(wù)號:TechGoGoGo 掃描碼: | http://weahome.cn/article/jdcgjs.html 其他資訊 |