2014年8月12日火曜日

AppiumでAndroidのChromeを動かすための二つの方法

AppiumでAndroidのChromeを動かす時に、portlait、landscapeを変更したいという要望があると思います。
それはやり方によっては可能なのですが、その方法をappiumの仕組みと共に考えていきます。
AppiumでAndroidのChromeを動かす際に、二つの方法があります。
  • Chromeをアプリとして動かす方法
  • Chromeをブラウザとして動かす方法
それはどう違うのか。

まずはアプリとして動かす方法から説明します。

appium.txtの中身
./chrome.apkはダウンロードしてきたchromeアプリです。
端末はGalaxy Nexusです。
[caps]
platformName = "android"
platformVersion = "4.3"
deviceName = "Nexus"
app = "./chrome.apk"
#appの変わりにこの二つでも動きます。
appPackage = "com.android.chrome"
appActivity = "com.google.android.apps.chrome.Main"

[appium_lib]
debug = true
wait = 30
export_session = true
appiumサーバーの起動
node .
appium/lib/server/main.jsが読み込まれて、サーバーがListen状態になります。 実行されているのがこれです。
var main = function (args, readyCb, doneCb) {}
別ターミナルで、clientを動かします。
arc
その時のappium server側の動作です。 appium/lib/appium.jsが読みこまれます。
Appium.prototype.start = function (desiredCaps, cb) {
  console.log("start in appium.js");
  console.log(desiredCaps);
  this.desiredCapabilities = new Capabilities(desiredCaps);
  this.updateResetArgsFromCaps();

  this.args.webSocket = this.webSocket; // allow to persist over many sessions
  if (this.sessionId === null || this.sessionOverride) {
    this.configure(this.args, this.desiredCapabilities, function (err) {
      if (err) {
        logger.debug("Got configuration error, not starting session");
        this.cleanupSession();
        cb(err, null);
      } else {
        this.invoke(cb);
      }
    }.bind(this));
  } else {
    return cb(new Error("Requested a new session but one was in progress"));
  }
};
configureで何をやっているか。
Appium.prototype.configure = function (args, desiredCaps, cb) {
  var deviceType;

  try {
    deviceType = this.getDeviceType(args, desiredCaps);
    if (!args.launch) desiredCaps.checkValidity(deviceType, args.enforceStrictCaps);
  } catch (e) {
    logger.error(e.message);
    return cb(e);
  }

  if (!this.deviceIsRegistered(deviceType)) {
    logger.error("Trying to run a session for device '" + deviceType + "' " +
                 "but that device hasn't been configured. Run config");
    return cb(new Error("Device " + deviceType + " not configured yet"));
  }
  this.device = this.getNewDevice(deviceType);
  console.log("configure in appium.js");
  console.log(deviceType);
  this.device.configure(args, desiredCaps, cb);
  // TODO: better collaboration between the Appium and Device objects
  this.device.onResetTimeout = function () { this.resetTimeout(); }.bind(this);
};
deviceTypeには「android」が入っています。 このメソッドでオブジェクトを生成しています。 deviceTypeによって、生成されるオブジェクトが変わります。
Appium.prototype.getNewDevice = function (deviceType) {
  console.log("prototype.getNewDevice");
  console.log(deviceType);
  var DeviceClass = (function () {
    switch (deviceType) {
      case DT_IOS:
        return IOS;
      case DT_SAFARI:
        return Safari;
      case DT_ANDROID:
        return Android;
      case DT_CHROME:
        return Chrome;
      case DT_SELENDROID:
        return Selendroid;
      case DT_FIREFOX_OS:
        return FirefoxOs;
      default:
        throw new Error("Tried to start a device that doesn't exist: " +
                        deviceType);
    }
  })();
  return new DeviceClass();
};
次に呼び出されるのは appium/lib/devices/android/android.js
Android.prototype.start = function (cb, onDie) {}
この中でuiautomator.jsが呼び出されています。
UiAutomator = require('./uiautomator.js')
uiautomatorを通してChromeアプリを動かす流れになります。
この場合は、このメソッドが使えます。
pry(main)>driver.rotation = :portlait
pry(main)>driver.rotation = :landscape
この場合は、このメソッドは使えません!
pry(main)>driver.get("http://google.co.jp")

次にブラウザで動かす方法です。

[caps]
platformName = "android"
platformVersion = "4.3"
deviceName = "Nexus"
browserName = "Chrome"

[appium_lib]
debug = true
wait = 30
export_session = true
この流れは同じ
Appium.prototype.start = function (desiredCaps, cb) {}
};
configureで何をやっているか。
Appium.prototype.configure = function (args, desiredCaps, cb) {
  var deviceType;

  try {
    deviceType = this.getDeviceType(args, desiredCaps);
    if (!args.launch) desiredCaps.checkValidity(deviceType, args.enforceStrictCaps);
  } catch (e) {
    logger.error(e.message);
    return cb(e);
  }

  if (!this.deviceIsRegistered(deviceType)) {
    logger.error("Trying to run a session for device '" + deviceType + "' " +
                 "but that device hasn't been configured. Run config");
    return cb(new Error("Device " + deviceType + " not configured yet"));
  }
  this.device = this.getNewDevice(deviceType);
  console.log("configure in appium.js");
  console.log(deviceType);
  this.device.configure(args, desiredCaps, cb);
  // TODO: better collaboration between the Appium and Device objects
  this.device.onResetTimeout = function () { this.resetTimeout(); }.bind(this);
};
deviceTypeには「chrome」が入っています。 次に呼び出されるのが上記のファイルとは異なります。 appium/lib/devices/android/chrome.js
ChromeAndroid.prototype.start = function (cb, onDie) {}
この中ではchromedriverが呼び出されています。
Chromedriver = require('./chromedriver.js');
この場合は、このメソッドが使えます。
pry(main)>driver.get("http://google.co.jp")
この場合は、このメソッドは使えません!
pry(main)>driver.rotation = :portlait
pry(main)>driver.rotation = :landscape 
 
基本的にはchromedriverで動かす方がわかりやすいし、chromeのバージョンアップにも強いので 後者の方がいいと思います。でも、どうしても縦横を変えたいという時は前者の方法でやればいいのかと思います。

0 件のコメント: