如何在 Ubuntu 中使用 Appium 进行 Android 单元测试

Posted

技术标签:

【中文标题】如何在 Ubuntu 中使用 Appium 进行 Android 单元测试【英文标题】:How to do Android Unit Test using Appium in Ubuntu 【发布时间】:2013-05-24 12:26:42 【问题描述】:

我想使用 Appium 为 HelloWorld android 应用程序做一个简单的单元测试。我的 Android 应用程序有一个 Activity,在它加载到屏幕上后,它会在 TextView 上显示“Hello World”。我想要的是使用 Python 编写一个单元测试用例,它可以按我的预期工作并使用 Appium 进行测试。

我无法理解的主要是我的 Android 项目、Appium 和 Python 脚本之间的联系。

我想我已经在我的 Ubuntu-12.04 中正确配置了 Appium。当我在终端中给出以下命令时

anuja@anuja-MulTplx:~$ appium &

它给出以下响应

anuja@anuja-MulTplx:~$ info: Appium REST http 接口监听器 开始于 0.0.0.0:4723

我使用 Selenium WebDriver 编写了用于 Web 单元测试的简单 Python 脚本。但我不知道如何编写 Python 脚本来使用 Appium 测试我的 Android 应用程序。需要一个例子或好的文档。

谢谢


我在 @Dan Cuellar 回答之后添加这部分。

使用一个终端启动服务器后,我从另一个包含 python 绑定的终端运行我的 python 脚本。

在 Appium 服务器运行终端上,它会给出以下输出

debug: Appium request initiated at /wd/hub/session

debug: Request received with params: "sessionId":null,"desiredCapabilities":"app-package":"my.app.package","app":"/home/anuja/MobileDev/apks_and_keys/Trickbook.apk","browserName":"","version":"4.0.4","device":"Android","app-activity":"TrickbookSplasher"

info: Using local app from desiredCaps: /home/anuja/MobileDev/apks_and_keys/Trickbook.apk

info: Creating new appium session 4788d549-d39a-4730-9bdb-382418c2b2c9

info: Starting android appium

debug: Using fast reset? true

info: Preparing device for session

info: Checking whether app is actually present

info: Checking whether adb is present

info: [ADB] Using adb from /home/anuja/MobileDev/sdk/platform-tools/adb

info: Trying to find a connected android device

info: [ADB] Getting connected devices...

info: [ADB] 1 device(s) connected

info: [ADB] Setting device id to 4d017b1f209a3f7b

info: Found device, no need to retry

info: [ADB] Waiting for device 4d017b1f209a3f7b to be ready and to respond to shell commands (timeout = 5)

info: Checking whether we need to run fast reset

debug: Checking app cert for /tmp/my.app.package.clean.apk: java -jar "/usr/lib/node_modules/appium/app/android/verify.jar" "/tmp/my.app.package.clean.apk"

debug: App not signed with debug cert.

debug: Checking app cert for /home/anuja/MobileDev/apks_and_keys/Trickbook.apk: java -jar "/usr/lib/node_modules/appium/app/android/verify.jar" "/home/anuja/MobileDev/apks_and_keys/Trickbook.apk"

debug: App not signed with debug cert.

info: Building fast reset

error: uncaughtException date=Thu May 30 2013 11:28:22 GMT+0530 (IST), pid=4466, uid=1000, gid=1000, cwd=/home/anuja, execPath=/usr/bin/nodejs, version=v0.10.8, argv=[node, /usr/bin/appium], rss=27017216, heapTotal=19666944, heapUsed=12400392, loadavg=[0.26318359375, 0.201171875, 0.333984375], uptime=2427.250582503, trace=[column=18, file=fs.js, function=Object.fs.openSync, line=427, method=fs.openSync, native=false, column=15, file=fs.js, function=Object.fs.readFileSync, line=284, method=fs.readFileSync, native=false, column=36, file=/usr/lib/node_modules/appium/android/adb.js, function=ADB.buildFastReset, line=131, method=buildFastReset, native=false, column=12, file=/usr/lib/node_modules/appium/android/adb.js, function=null, line=311, method=null, native=false, column=14, file=/usr/lib/node_modules/appium/android/adb.js, function=null, line=283, method=null, native=false, column=7, file=child_process.js, function=ChildProcess.exithandler, line=641, method=exithandler, native=false, column=17, file=events.js, function=ChildProcess.EventEmitter.emit, line=98, method=EventEmitter.emit, native=false, column=16, file=child_process.js, function=maybeClose, line=735, method=null, native=false, column=5, file=child_process.js, function=Process.ChildProcess._handle.onexit, line=802, method=ChildProcess._handle.onexit, native=false], stack=[Error: ENOENT, no such file or directory '/usr/lib/node_modules/appium/app/android/AndroidManifest.xml.src',     at Object.fs.openSync (fs.js:427:18),     at Object.fs.readFileSync (fs.js:284:15),     at ADB.buildFastReset (/usr/lib/node_modules/appium/android/adb.js:131:36),     at /usr/lib/node_modules/appium/android/adb.js:311:12,     at /usr/lib/node_modules/appium/android/adb.js:283:14,     at ChildProcess.exithandler (child_process.js:641:7),     at ChildProcess.EventEmitter.emit (events.js:98:17),     at maybeClose (child_process.js:735:16),     at Process.ChildProcess._handle.onexit (child_process.js:802:5)]

AND 在我执行 python 绑定脚本的终端上给出了以下结果。

Traceback (most recent call last):

  File "forth.py", line 12, in <module>
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 72, in __init__
    self.start_session(desired_capabilities, browser_profile)

  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 114, in start_session
    'desiredCapabilities': desired_capabilities,

  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 163, in execute
    response = self.command_executor.execute(driver_command, params)

  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/remote_connection.py", line 349, in execute
    return self._request(url, method=command_info[0], data=data)

  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/remote_connection.py", line 396, in _request
    response = opener.open(request)

  File "/usr/lib/python2.7/urllib2.py", line 400, in open
    response = self._open(req, data)

  File "/usr/lib/python2.7/urllib2.py", line 418, in _open
    '_open', req)

  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)

  File "/usr/lib/python2.7/urllib2.py", line 1207, in http_open
    return self.do_open(httplib.HTTPConnection, req)

  File "/usr/lib/python2.7/urllib2.py", line 1180, in do_open
    r = h.getresponse(buffering=True)

  File "/usr/lib/python2.7/httplib.py", line 1030, in getresponse
    response.begin()

  File "/usr/lib/python2.7/httplib.py", line 407, in begin
    version, status, reason = self._read_status()

  File "/usr/lib/python2.7/httplib.py", line 371, in _read_status
    raise BadStatusLine(line)

httplib.BadStatusLine: ''

我已使用自签名 apk 进行上述测试。

右键单击 Eclipse Android 项目 Android 工具 导出签名的应用程序包 彻底了解向导

我正在使用真实设备进行此测试。

谁能指出我在哪里/做错了什么?

【问题讨论】:

【参考方案1】:

appium &amp; 启动 appium 服务器。可以把它想象成相当于java -jar selenium.jar,它将启动 Selenium RC 服务器。

服务器启动后,您必须通过 python 绑定连接到它:

from selenium import webdriver

desired_caps = 
desired_caps['device'] = 'Android'
desired_caps['browserName'] = ''
desired_caps['version'] = '4.2'
desired_caps['app'] = '/path/to.your.apk'
desired_caps['app-package'] = 'com.example.android.package'
desired_caps['app-activity'] = 'YourActivity'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

连接后,您可以通过普通的 python webdriver 命令控制测试。

示例:https://github.com/appium/sample-code/tree/master/sample-code/examples/python

【讨论】:

感谢您的回复。我在尝试你的方法时又卡住了。我已根据您的回答编辑我的问题。请查看水平线后的新更新,并让我知道我在哪里/做错了什么。【参考方案2】:

从日志中,App not signed with debug cert. 您的 apk 未使用 ~/.android/debug.keystore 中的默认调试证书签名

【讨论】:

【参考方案3】:

像这样配置 SDK

 export ANDROID_HOME="$HOME/adt/sdk"

 export JAVA_HOME="/usr/bin/java"

 export PATH=$PATH:~/adt/sdk/tools

 export PATH=$PATH:~/adt/sdk/platform-tools

参考代码:

import os
from time import sleep
import unittest
from appium import webdriver

# Returns absolute path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p))
class SimpleAndroidTests(unittest.TestCase):
    def setUp(self):
        desired_caps = 
        #Specify platform below(Android, ios)
        desired_caps['platformName'] = 'Android'
        #Specify OS version(Settings->About phone -> android version)
        desired_caps['platformVersion'] = '4.4.4'
        #Obtain the Device name from Adb[For Android](Terminal Command: "adb devices")
        desired_caps['deviceName'] = 'TA93304QZD'
        #Specify the path to Application
        desired_caps['app'] = PATH('Media Drive-com.sandisk.scotti-55-v2.0.3.apk')
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    def tearDown(self):
        # end the session
        self.driver.quit()

    def test_images_copy(self):
        self.driver.implicitly_wait(5)

        for i in range(0,4):
                 self.driver.find_element_by_id("com.sandisk.scotti:id/txt_Next").click()
          self.driver.implicitly_wait(5)
           self.driver.find_element_by_id("com.sandisk.scotti:id/txt_Close").click()
        self.driver.implicitly_wait(5)
        self.driver.find_element_by_name("OK").click()
        self.driver.implicitly_wait(5)
        self.driver.find_element_by_id("com.sandisk.scotti:id/txt_Photo").click()
        self.driver.implicitly_wait(5)
           self.driver.find_element_by_id("com.sandisk.scotti:id/btn_Switch_Local").click()
        self.driver.implicitly_wait(5)
              self.driver.find_element_by_id("com.sandisk.scotti:id/txt_Name").click()
        self.driver.implicitly_wait(5)

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(SimpleAndroidTests)
    unittest.TextTestRunner(verbosity=2).run(suite)

【讨论】:

以上是关于如何在 Ubuntu 中使用 Appium 进行 Android 单元测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ubuntu for android 中设置 Appium

如何在 Python 中使用 appium 进行滚动

在Ubuntu Linux上安装Appium,用来构建自动化测试环境

如何将 Appium 与 C# 集成?

Ubuntu上的Appium桌面问题

Ubuntu14.04 install appium