2014年4月3日木曜日

promote_singleton_appium_methodsが何をやっているか?

common.rbの中に書かれているこのメソッドが気になったので調査してみた。
Appium.promote_singleton_appium_methods UICatalog
pathはここです。
appium_lib/lib/appium_lib/driver.rb
def self.promote_singleton_appium_methods main_module
  raise 'Driver is nil' if $driver.nil?
  main_module.constants.each do |sub_module|
    #noinspection RubyResolve
    $driver.public_methods(false).each do |m|
      const = main_module.const_get(sub_module)
      const.send(:define_singleton_method, m) do |*args, &block|
        begin
          super(*args, &block) # promote.rb
        rescue NoMethodError, ArgumentError
          $driver.send m, *args, &block if $driver.respond_to?(m)
        end
        # override unless there's an existing method with matching arity
      end unless const.respond_to?(m) &&
          const.method(m).arity == $driver.method(m).arity
    end
  end
end
何のためのメソッドか?
自分で作成したmoduleの中でappiumのメソッドを使えるようにするためです。
サンプルでは自分でmoduleを作成しているのですが、
普通に実装しては、その中でappiumのメソッドは使えません。
module UICatalog
  module ButtonUses
    class << self
      def assert_exists
        s_text_exact resolve_id 'ButtonsTitle'
      end
      
      def assert
        wait { self.assert_exists }
      end
    end
  end
end
Appium.promote_singleton_appium_methods UICatalog←これをコメントすれば
NoMethodError: undefined method `wait' for UICatalog::Home:Module
というエラーが出ます。
もう少し、詳細にメソッドを見ていきます。
main_module.constants
これはサンプルでは、下記の内容になります。
UICatalog.constants
戻り値です。
[
    [0] :ButtonUses,
    [1] :ControlUses,
    [2] :Home
]
ここでは$driverに含まれているクラスのメソッドが返ります。
$driver.public_methods(false)
  main_module.const_get(sub_module)
戻り値の一つはこうなります。
UICatalog::ButtonUses
上記の値に対してsendで動的にメソッドを定義します。
define_singleton_methodメソッドは、レシーバのオブジェクトに特異メソッドを定義します。
特異メソッドとはインスタンスから呼び出させるメソッドを定義します。
それで、これがどういう意味なるか?
const.send(:define_singleton_method, m)
下記のような感じでappiumのメソッドの全てをUICatalog::ButtonUsesに追加していきます。
UICatalog::ButtonUses.define_singleton_method(:wait)
UICatalog::ButtonUses.define_singleton_method(:back)
UICatalog::ButtonUses.define_singleton_method(:xpath)

0 件のコメント: