¹È¸èµÄAndroidÉú̬ϵͳÕýÔÚ²»¶ÏµØÑ¸ËÙÀ©ÕÅ¡£ÓÐÖ¤¾Ý±íÃ÷£¬ÐµÄÒÆ¶¯OEMÕýÔÚ¹¥ÏÝÊÀ½çµÄÿһ¸ö½ÇÂ䣬²»Í¬µÄÆÁÄ»³ß´ç¡¢ROM /¹Ì¼þ¡¢Ð¾Æ¬×éÒÔ¼°µÈµÈµÈµÈ£¬²ã³ö²»Çî¡£ÓÚÊǺõ£¬¶ÔÓÚAndroid¿ª·¢ÈËÔ±¶øÑÔ£¬´¦Àí´æ´¢Ë鯬±äµÃÔ½À´Ô½À§¾½¡£
²»¹ýÐÒÔ˵ÄÊÇ£¬Android£¨»¹ÓÐiOS£©¿ª·¢ÈËÔ±¿ÉÒÔÎÞÏÞÖÆµØ·ÃÎÊһЩÏȽøµÄ»ùÓÚÔÆµÄ½â¾ö·½°¸£¬ÈçTestdroid Cloud£¬¾Í¿ÉÒÔÔÚ´ó¹æÄ£µÄÕæÊµÉ豸ÉÏÖ´ÐÐ×Ô¶¯»¯²âÊÔÒÔÈ·±£ÖÊÁ¿£¬ÔÞ°É¡£´ËÍ⣬²»Í¬µÄAndroid²âÊÔ¿ò¼ÜµÄ³öÏÖÒ²´ó´ó¼õÇáÁËAndroid¿ª·¢ÈËÔ±µÄ¸ºµ£¡£
½ñÌ죬ÎÒÃǾÍҪ˵˵5¿î×î³£ÓõÄAndroid²âÊÔ¿ò¼Ü£¬²¢ÇÒÿ¸ö¿ò¼Ü¶¼¸ø³öÁË»ù±¾µÄ´úÂëʾÀý¡£
1.Robotium
²»¿É·ñÈÏ£¬RobotiumÔøÊÇAndroidÊÀ½çÖ®³õʹÓÃ×î¹ã·ºµÄAndroid²âÊÔ¿ò¼Ü£¬·çÃÒһʱ¡£ÓÉÓÚËüÓëAndroidÓÐ×ÅÏàËÆµÄSelenium£¬ËùÒÔËüÄܹ»Ê¹µÃAPIµÄ²âÊÔ±äµÃ¼òµ¥ÆðÀ´¡£
RobotiumÊÇÒ»¸öÀ©Õ¹ÓÚJUnitµÄ¿ªÔ´¿â£¬ÔËÓöàÖÖÓÐÓõķ½·¨À´Ö§³ÖAndroid UI²âÊÔ¡£ËüÌṩµÄÇ¿´óµÄ×Ô¶¯»¯ºÚÏä²âÊÔ·¶Àý£¬¿ÉÓÃÓÚAndroidÓ¦Óã¨ÔÉúµÄºÍ»ìºÏµÄ£©ºÍweb²âÊÔ¡£Ö»ÒªÔ´´úÂëÔÊÐí£¬Äã¾Í¿ÉÒÔͨ¹ýRobotiumд¹¦ÄÜ¡¢ÏµÍ³ºÍÑéÊÕ²âÊÔ·½°¸£¬ÒÔ¼°²âÊÔÓ¦Óá£
RobotiumµÄ´úÂëʾÀý£º
// Public void for the operation public void testRecorded() throws Exception { // Wait for the text 'Hello!' to be shown for newbie if (solo.waitForText("Hello!")) { // R class ID identifier for 'Sign in' - and click it solo.clickOnView(solo.findViewById("com.twitter.android.R.id.sign_in")); // R class ID identifier for entering username solo.enterText((EditText)solo.findViewById("com.twitter.android.R.id.login_username"),"username"); // R class ID identifier for entering password solo.enterText((EditText)solo.findViewById("com.twitter.android.R.id.login_password"),"password"); // R class ID identifier for clicking log in solo.clickOnView(solo.findViewById("com.twitter.android.R.id.login_login")); // Wait until log in is done solo.waitForActivity("HomeTabActivity"); } // Activate the text field to compose a tweet solo.clickOnView(solo.findViewById("com.twitter.android.R.id.menu_compose_tweet")); // Type the tweet solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.edit"), "Testdroid"); // Tweeting! solo.clickOnView(solo.findViewById("com.twitter.android.R.id.composer_post")); } |
ΪÁ˸ø´ó¼ÒÌṩ±ã½Ý£¬»¹ÓÐÒ»¸öÓÃRobotium¹¹½¨µÄÓÃÓÚ²âÊԽű¾´´½¨µÄÒ»¸ö·Ç³£°ôµÄ¼Ç¼¹¤¾ß¡ª¡ªTestdroid Recorder¡£µ±ÄãÔÚÕæÊµÉ豸ÉÏÖ´ÐÐʵ¼ÊÐж¯Ê±£¬Ëü¿ÉÒԼǼÄãµÄÿһ¸ö²½ÖèºÍÿһ¸öÐÐΪ£¬²¢×ª»»³ÉJavaScript£¬ÒÔ±ãÓÚÄã½øÒ»²½µÄÐ޸ġ£
²¢ÇÒ£¬Ä㻹¿ÉÒÔȫȨÏÂÔØºÍʹÓÃËüµÄÀ©Õ¹¿â¡ª¡ªExtSolo£¬ËüÀïÃæ°üº¬Á˶àÖÖ»¹Ã»Óб»ÄÉÈëµ½RobotiumÖеÄʵÓ÷½·¨£¬ÀýÈ磺
Ö§³ÖÈÎÒâ·Ö±æÂʵÄx¡¢Yµã»÷×Ô¶¯Ëõ·Å
¶à·¾¶Í϶¯
²âÊÔ¹ÊÕÏʱ×Ô¶¯½ØÍ¼
Ä£ÄâµØµã
¸ü¸ÄÉ豸ÓïÑÔ
¿ØÖÆWiFiÁ¬½Ó
¹Ù·½ÍøÕ¾£ºhttps://code.google.com/p/robotium/
2.uiautomator
ËäÈ»RobotiumÊÇÒ»¸öºÜºÃµÄ²âÊÔ¿ò¼Ü£¬µ«ÊÇuiautomatorÄÜÈÃÄãÔÚ²âÊÔAndroidÓ¦ÓúÍAndroidÓÎϷʱ×öµÃ¸ü¶à¡£¹È¸èµÄ²âÊÔ¿ò¼ÜÔÊÐíÄãÔÚÒ»¸ö»ò¶à¸öÉ豸ÉϲâÊÔÔÉúAndroidÓ¦ÓõÄÓû§½çÃæ£¨UI£©¡£UiautomatorµÄÁíÒ»¸öÓŵãÊÇ£¬ËüÔËÐеÄJUnit²âÊÔÓÃÀýÊÇÓÐÌØÊâȨÏ޵ģ¬ÕâÒâζ×ŲâÊÔÓÃÀý¿ÉÒÔ¿çÔ½²»Í¬µÄ½ø³Ì¡£Ëü»¹ÌṩÁËÎåÖÖ²»Í¬µÄÀà¸ø¿ª·¢ÈËԱʹÓãº
com.android.uiautomator.core.UiCollection; com.android.uiautomator.core.UiDevice; com.android.uiautomator.core.UiObject; com.android.uiautomator.core.UiScrollable; com.android.uiautomator.core.UiSelector |
Òź¶µÄÊÇ£¬uiautomatorÖ»Äܹ¤×÷ÓÚAPI16»ò¸ü¸ß¼¶±ðµÄAndroidÉ豸ÉÏ¡£ËüµÄÁíÒ»¸öȱµãÊDz»Ö§³ÖwebÊÓͼ£¬Ò²Ã»Óа취ֱ½Ó·ÃÎÊAndroid¶ÔÏó¡£
uiautomatorµÄ´úÂëʾÀý£º
// Public void for the operation public void testSignInAndTweet() throws Exception { // Starting application: getUiDevice().wakeUp(); // Press Home button to ensure we're on homescreen getUiDevice().pressHome(); // Select 'Apps' and click button new UiObject(new UiSelector().description("Apps")).click(); // Select 'Twitter' and click new UiObject(new UiSelector().text("Twitter")).click(); // Locate and select 'Sign in' UiSelector signIn = new UiSelector().text("Sign In"); // If button is available, click UiObject signInButton = new UiObject(signIn); if (signInButton.exists()) { signInButton.click(); // Set the username new UiObject(new UiSelector().className("android.widget.EditText").instance(0)).setText("username"); new UiObject(new UiSelector().className("android.widget.EditText").instance(1)).setText("password"); new UiObject(new UiSelector().className("android.widget.Button"). text("Sign In").instance(0)).click(); // Wait Sign in progress window getUiDevice().waitForWindowUpdate(null, 2000); // Wait for main window getUiDevice().waitForWindowUpdate(null, 30000); } new UiObject(new UiSelector().description("New tweet")).click(); // Typing text for a tweet new UiObject(new UiSelector().className("android.widget.LinearLayout").instance(8)). setText("Awesome #Testdroid!"); // Tweeting! new UiObject(new UiSelector().text("Tweet")).click(); |
¹Ù·½ÍøÕ¾£ºhttp://developer.android.com/tools/help/uiautomator/index.html
3.Espresso
EspressoÊÇÓÉGoogle¿ªÔ´µÄÒ»¿î×îеÄAndroid×Ô¶¯»¯²âÊÔ¿ò¼Ü£¬ÓÐÖúÓÚÓÚ¿ª·¢ÈËÔ±ºÍ²âÊÔÈËÔ±´¸Á¶³öÖÐÒâµÄÓû§½çÃæ¡£EspressoµÄAPIÌå»ýС¡¢¿ÉÔ¤¼û¡¢¼òµ¥Ò×ѧ£¬¹¹½¨ÔÚAndroidÒDZí¿ò¼ÜµÄ»ù´¡ÉÏ¡£Ê¹ÓÃËü£¬ÄÜÈÃÄã¿ìËÙ±àд³ö¼ò½à¿É¿¿µÄAndroid UI²âÊÔ¡£ËüÖ§³ÖAPI level 8¼¶£¨Froyo£©¡¢10£¨Gingerbread£©£¬ºÍ15£¨Ice Cream Sandwich£©¼°ºóÐø¡£
Ò»·½ÃæËüÏ൱¿É¿¿£¬ÒòΪºÍUIÏß³ÌÊÇͬ²½µÄ£¬ÁíÒ»·½ÃæÓַdz£Ö®¿ì£¬ÒòΪûÓÐÈκÎ˯ÃߵıØÒª£¨µ±Ä³¸öºÁÃ룬ӦÓóÌÐò¿Õתʱ£¬ÔËÐвâÊÔ£©¡£²»¹ýËüͬÑù²»Ö§³ÖwebÊÓͼ¡£
EspressoµÄ´úÂëʾÀý£º
public void testEspresso() { // Check if view with the text 'Hello.' is shown onView(withText("Hello.")).check(matches(isDisplayed())); // R class ID identifier for 'Sign in' - and click it onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/sign_in", null, null))).perform(click()); // R class ID identifier for entering username onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/login_username", null, null))).perform((typeText("username"))); // R class ID identifier for entering password onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/login_password", null, null))).perform((typeText("password"))); // R class ID identifier for clicking log in onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/login_login", null, null))).perform(click()); // Activate the text field to compose a tweet onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/menu_compose_tweet", null, null))).perform(click()); // Type the tweet onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/edit", null, null))).perform((typeText(¡±#Testdroid"))); // Tweeting! onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.twitter.android:id/composer_post", null, null))).perform(click()); } |
¹Ù·½ÍøÕ¾£ºhttps://code.google.com/p/android-test-kit/wiki/Espresso
4.Calabash
CalabashÊÇÒ»¿î¿çƽ̨µÄ×Ô¶¯»¯²âÊÔ¿ò¼Ü£¬Ö§³ÖAndroidºÍiOSÔÉúºÍ»ìºÏµÄÓ¦ÓóÌÐò¡£CalabashÒ×ÓÚÀí½âµÄÓï·¨£¬Ê¹µÃ¼´Ê¹ÊǷǼ¼ÊõÈËÔ±Ò²¿ÉÒÔÔÚÕâÁ½¸öÒÆ¶¯Æ½Ì¨ÉÏΪapp´´½¨ºÍÖ´ÐÐ×Ô¶¯»¯ÑéÊÕ²âÊÔ¡£CalabashµÄ²âÊÔÃèÊöÓÚCucumber£¬È»ºóÔÚÔËÐÐʱת»¯ÎªRobotium»òFrank¡£ËüÖ§³ÖÔ¼80ÖÖ²»Í¬µÄ×ÔÈ»ÓïÑÔÖ¸Á¿ØÖÆÆ÷£©£¬²¢ÇÒ¿ÉÒÔʹÓÃRubyºÍJavaʵÏÖеĿØÖÆÆ÷¡£
CalabashµÄ´úÂëʾÀý£º
Feature: Login feature Scenario: As a valid user I can log into my app I wait for text "Hello" Then I press view with id "Sign in" Then I enter text "username" into "login_username" Then I enter text "password" into "login_password" Then I wait for activity "HomeTabActivity" Then I press view with id "menu_compose_tweet" Then I enter text "Testdroid" into field with id "edit" Then I press view with id "composer_post"=16 |
¹Ù·½ÍøÕ¾£ºhttp://calaba.sh/
5.Appium
AppiumÊÇÒ»¿îÒÆ¶¯µÄ×Ô¶¯»¯²âÊÔ¿ò¼Ü£¨ºÍ¹¤¾ß£©£¬Ö§³ÖiOSºÍAndroidÔÉúºÍ»ìºÏµÄÒÆ¶¯WebÓ¦ÓóÌÐò¡£ËüÄÚ²¿Ê¹ÓõÄJSONWireProtocolͨ¹ýSeleniumµÄWebDriver£¬À´ÓëiOSºÍAndroidÓ¦ÓýøÐн»»¥¡£Ëüͨ¹ýuiautomator£¨API level 16»ò¸ü¸ß£©ºÍSeledroid£¨API level µÍÓÚ16£©Ö§³ÖAndroid£¬Í¨¹ýUI AutomationÖ§³ÖiOS£¬»¹ÓÐAndroidºÍiOS¶¼Ö§³ÖµÄÒÆ¶¯webÈçSelenium driver¡£
AppiumµÄ×î´óÓŵãÔÚÓÚÄ㼸ºõ¿ÉÒÔÓÃÈÎÒâÒ»ÖÖ±à³ÌÓïÑÔ£¨ÀýÈ磬Java¡¢Objective-C¡¢JavaScript¡¢PHP¡¢Ruby¡¢PythonºÍC££µÈ£©À´±àдAppium½Å±¾¶ø²»±ØÑ¡Ôñ¹¤¾ß£¬¼æÈÝ×îÖØÒªµÄƽ̨£¨AndroidºÍiOS£©¶ø²»±Ø°²×°ºÍÅäÖÃÉ豸ÊÊÓ¦²âÊԵȵȡ£²¢ÇÒ£¬Èç¹ûÄãÊìϤSeleniumµÄ»°£¬ÄÇôʹÓÃAppiumÓÃÓÚÒÆ¶¯app²âÊÔ¶ÔÄã¶øÑÔ½«ÊÇÇá¶øÒ×¾ÙµÄÒ»¼þÊ¡£ÒòΪËüÃÇʹÓÃÏàͬµÄWebDriver£¬²¢ÇÒÒÔͬÑùµÄ·½Ê½Ê¹ÓÃDesiredCapabilities¡£ËùÒÔAppiumÓëSeleniumÔÚÅäÖÃÓ¦ÓóÌÐòÔËÐÐʱÓÐÖî¶àÏàËÆÖ®´¦¡£
AppiumµÄ´úÂëʾÀý£º
# wait for hello sleep(3) textFields = driver.find_elements_by_tag_name('textField') assertEqual(textFields[0].get_attribute("value"), "Hello") # click sign-in button driver.find_elements_by_name('Sign in')[0].click() # find the text fields again, and enter username and password textFields = driver.find_elements_by_tag_name('textField') textFields[0].send_keys("twitter_username") textFields[1].send_keys("passw0rd") # click the Login button (the first button in the view) driver.find_elements_by_tag_name('button')[0].click() # sleep sleep(3) # click the first button with name "Compose" driver.find_elements_by_name('Compose')[0].click() # type in the tweet message driver.find_elements_by_tag_name('textField')[0].send_keys(¡±#Testdroid is awesome!") # press the Send button driver.find_elements_by_name('Send')[0].click() # exit driver.quit() |
¹Ù·½ÍøÕ¾£ºhttp://appium.io/

×ܽá
ÒÔÉϾÍÊÇÎÒÃÇÁгöµÄ5¿î×î°ôµÄ²âÊÔ¿ò¼Ü£¬¿ÉÓÃÓÚÈÕ³£µÄAndroid¹¹½¨£¬´´Á¢ºÍÐ޸ġ£µ±È»£¬Ã¿Ò»ÖÖ¿ò¼Ü¶¼ÓÐÆäÓÅÊÆºÍȱÏÝ¡£Appium¿ÉÒÔͬʱ²âÊÔÄãµÄAndroidºÍiOS°æ±¾¡£µ«Èç¹ûÄãÊÇÒ»¸öÖÒʵµÄAndroid¿ª·¢ÈËÔ±Ö»¿ª·¢°²×¿°æ±¾µÄapp£¬ÄÇô£¬Ê¹ÓÃRobotium¾ÍºÜ²»´íµÄ¡£Testdroid Recorder»¹¿ÉΪÎÒÃÇÔÚÉú³É²âÊԽű¾½ÚÊ¡´óÁ¿µÄʱ¼äºÍ½ðÇ®£¨ÕâÊÇÃâ·ÑµÄŶ£¡£©¡£Òò´Ë£¬ºÃºÃ˼¿¼ÏÂÄãµÄ²âÊÔÐèÇ󡪡ª¹¦ÄܲâÊÔ¡¢¼æÈÝÐÔ²âÊÔ¡¢UI²âÊԵȵȡª¡ªÈ»ºóΪ×Ô¼ºÑ¡È¡×îÊʺϺÍ×î¼ÑµÄAndroid²âÊÔ¿ò¼Ü¡£ |