Robot Framework - 将Appium驱动传递给Python脚本
我正在用Python把Robot Framework和Appium结合起来。不过,我不知道怎么把在Robot Framework中创建的Appium驱动传递给一个自定义的Python脚本。
我的环境:
- Mac OS - Mavericks
- Appium 1.2(通过home brew安装)
- 最新的Robot Framework(通过pip安装)
- 最新的Robot Framework的Appium库(通过pip安装)
我有一个可以工作的Appium Python脚本,但我想开始用Robot Framework来处理实际的测试。
这是我工作中的Python脚本的一部分代码:
wd = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
wd.find_element_by_name("Start").click()
wd.find_element_by_xpath("//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIATableCell[1]").click()
wd.execute_script("var vKeyboard = target.frontMostApp().keyboard(); vKeyboard.typeString(\"Test Text\");")
wd.execute_script("var vKeyboard = target.frontMostApp().keyboard(); vKeyboard.buttons()['Return'].tap();")
如你所见,由于应用程序的工作方式,我需要在脚本中使用execute_script。
但是Robot Framework的Appium库没有提供execute_script这个功能,所以我需要在一个Python库中自己写。
这是我开始的Robot测试脚本,它在我需要执行execute_script之前是可以工作的:
TestStart
Open Application ${REMOTE_URL} ${PLATFORM_NAME} ${PLATFORM_VERSION} ${DEVICE_NAME} ${APP}
Click Element name=Start
Click Element xpath=//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIATableCell[1]
我的问题是,如何把在“打开应用程序”中创建的驱动实例传递给Python脚本?
我有一个Python脚本,里面有以下内容:
def KeyboardType(driver):
driver.execute_script("var vKeyboard = target.frontMostApp().keyboard(); vKeyboard.typeString(\"hi there\");")
但是,我似乎无法把Robot Framework脚本中的驱动传递给这个Python脚本。
我尝试通过以下方式把“打开应用程序”的结果设置为一个变量:
${Driver} Open Application ${REMOTE_URL} ${PLATFORM_NAME} ${PLATFORM_VERSION} ${DEVICE_NAME} ${APP}
KeyboardType ${Driver}
但我收到了这个错误:
AttributeError: 'str'对象没有'execute_script'这个属性
我还尝试把“获取当前上下文”的结果传递到Python脚本中,但我得到了:
AttributeError: 'unicode'对象没有'execute_script'这个属性
我该如何把Robot Framework创建的驱动传递到Python脚本中呢?
3 个回答
这是你问题的解决方案 :)
from robot.libraries.BuiltIn import BuiltIn
def get_current_driver():
return BuiltIn().get_library_instance('AppiumLibrary')._current_application()
感谢Bryan Oakley的回复,他给我指明了方向,解决办法是对Appium库进行子类化。
我做了以下修改使其能够正常工作:
我的主要Robot Framework测试文件不再引用Appium框架,而是只引用了我自定义的Python文件。
我的自定义Python文件现在是对Appium库的子类化,这样我就可以访问到_current_application()这个功能。
我的自定义Python类现在看起来是这样的:
from AppiumLibrary import AppiumLibrary
class Custom(AppiumLibrary):
def get_driver_instance(self):
return self._current_application()
def KeyboardType(self, textToType):
self._current_application().execute_script("var vKeyboard = target.frontMostApp().keyboard(); vKeyboard.typeString(\"" + textToType + "\");")
def PressKeyboardButton(self, buttonToPress):
self._current_application().execute_script("var vKeyboard = target.frontMostApp().keyboard(); vKeyboard.buttons()['" + buttonToPress + "'].tap();")
Robot Framework文件现在看起来是这样的:
TestStart
Open Application ${REMOTE_URL} ${PLATFORM_NAME} ${PLATFORM_VERSION} ${DEVICE_NAME} ${APP}
Click Element name=Start
Click Element xpath=//UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIATableCell[1]
KeyboardType Test 123
PressKeyboardButton Return
注意:此时,我不需要将打开的应用程序设置为一个变量,因为子类已经自动可以访问它。不过,如果需要的话,我可以通过“获取驱动实例”轻松地将其设置为变量。
谢谢你的帮助,Bryan!
我现在不使用appium,所以不能给出确切的答案。不过,有人问过一个类似的问题,关于selenium,那个问题是需要实际的webdriver对象。你可以查看这个问题:将现有的Webdriver对象传递给Robot Framework的自定义Python库
简单来说,你可以尝试去扩展appium库,这样你的关键词就能访问appium的内部功能,或者你可以通过调用 BuiltIn().get_library_instance('Selenium2Library
来获取库的句柄。
关于后面这种方法的更多信息,可以查看从Robot Framework获取活动库实例,这个内容在Robot Framework用户指南中。