http://testerhome.com/topics/309 里, @rockchensir 提到了真机上运行 Safari。 于是花了点时间研究了下。

先看下,模拟器上如何启动 Safari

Automating mobile web apps 里讲的很清楚,

{
  app: 'safari'
  , device: 'iPhone Simulator'
  , version: '7.0'
}

只要配置下 cap 的 app 参数就可以了。当然你要确保 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/Applications/MobileSafari.app 是存在的。

看下 sample code,

package com.saucelabs.appium;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.net.URL;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

/**
 *
 * Simple test which demonstrates how a test can be run against Mobile Safari running on an Appium instance.
 *
 * The test is based on https://github.com/appium/appium/blob/master/sample-code/examples/node/safari.js
 *
 * @author Ross Rowe
 */
public class SafariTest {

    private WebDriver driver;

    /**
     * Instantiates the {@link #driver} instance by using DesiredCapabilities which specify the
     * 'iPhone Simulator' device and 'safari' app.
     * @throws Exception
     */
    @Before
    public void setUp() throws Exception {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("device", "iPhone Simulator");
        capabilities.setCapability("version", "7.0");
        capabilities.setCapability("app", "safari");
        driver = new RemoteWebDriver(new URL("http://127.0.0.1:4723/wd/hub"),
                capabilities);
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
    }

    /**
     * Navigates to http://saucelabs.com/test/guinea-pig and interacts with the browser.
     *
     * @throws Exception
     */
    @Test
    public void runTest() throws Exception {
        driver.get("http://saucelabs.com/test/guinea-pig");
        WebElement idElement = driver.findElement(By.id("i_am_an_id"));
        assertNotNull(idElement);
        assertEquals(idElement.getText(), "I am a div");
        WebElement commentElement = driver.findElement(By.id("comments"));
        assertNotNull(commentElement);
        commentElement.sendKeys("This is an awesome comment");
        WebElement submitElement = driver.findElement(By.id("submit"));
        assertNotNull(submitElement);
        submitElement.click();
        WebElement yourCommentsElement = driver.findElement(By.id("your_comments"));
        assertNotNull(yourCommentsElement);
        assertTrue(driver.findElement(By.id("your_comments")).getText().contains("This is an awesome comment"));

    }

    /**
     * Closes the {@link #driver} instance.
     *
     * @throws Exception
     */
    @After
    public void tearDown() throws Exception {
        driver.quit();
    }
}

像普通的 webdriver 测试一样,亲测可以运行。

在真机上运行 Safari

真机上运行 Safari 就没有那么简单了。

https://github.com/appium/appium/issues/1083 里,snevesbarros 提到:

@PavithraNavaneeth, you have two options:

Use the SafariLauncher which navigates to a URL causing Safari to launch.
It needs to have a 20 - 30 seconds delay after launching the app before it navigates to the link or else Appium ?>thinks the app has crashed.
NOTE: In this case you will have to set the app to be the safari launcher app.

Or if you dont want the 20 seconds delay then you can use the webview app.
The downside of this is that the webview isn't as good as safari at rendering certain elements (e.g. canvas).
NOTE: In this case you will have to set the app value to be the webview app.

For both solutions you will have to run the ios-webkit-debug-proxyand build the app using a profile that allows it >to be installed on your device.

In NO case can you set the app to safari or set the bundle id to com.apple.mobilesafari for a real device. This will not work!

按他说的,你是没有办法直接打开 safari 的, 我估计所有没有开发证书的应用我们都无法直接打开。所以只能曲线救国。一般两种方法:

最新的 Automating mobile web apps 里面也介绍了如何配置 SafariLauncher 在真机上运行 Safari。大家可以自行阅读。使用 SafariLauncher 我没能成功运行。不知道什么原因。

不过我成功的启动了 WebViewApp, 并通过 WebViewApp 转到网站。看代码。

   //setup the web driver and launch the webview app.
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability("device", "iPhone Simulator");
desiredCapabilities.setCapability("app", "http://appium.s3.amazonaws.com/WebViewApp6.0.app.zip");  
URL url = new URL("http://127.0.0.1:4723/wd/hub");
RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities);

//switch to the latest web view
for(String winHandle : remoteWebDriver.getWindowHandles()){
  remoteWebDriver.switchTo().window(winHandle);
}

remoteWebDriver.get("http://saucelabs.com/test/guinea-pig");
//Interact with the elements on the guinea-pig page using id.
WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id"));
Assert.assertEquals("I am a div", div.getText()); //check the text retrieved matches expected value
remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //populate the comments field by id.

//leave the webview to go back to native app.
remoteWebDriver.executeScript("mobile: leaveWebView");      

//close the app.
remoteWebDriver.quit();

这里的 WebViewApp 是直接从网上下载的, 你可以用 appium 下面 sample code 里面的 app 下面的 WebViewApp 来运行。

总的来说 WebView 和 Safari 虽然有些许差异,但大部分还是一致的。不过目前而言, Appium 对 真机 iOS 上的 Safari 支持并不好。其实就像 Webdriver 一样, 驱动 Safari 也得费不少功夫。

另外切记一点,无论是哪种方式,都必须使用 ios-webkit-debug-proxy, 并且要打开真机里面 Safari 的 debug 模式。


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