Appium pytest 测试用例执行时报'NoneType' object has no attribute 'to_capabilities'

strayeagle · 2024年03月24日 · 最后由 strayeagle 回复于 2024年03月24日 · 2920 次阅读

如下代码只是为了验证可行性。

环境:

root@Gavin:~# python3 -V
Python 3.11.6
root@Gavin:~# pip list |grep -i selenium
pytest-selenium              4.1.0
selenium                     4.18.1
root@Gavin:~# pip list |grep -i appium
Appium-Python-Client         4.0.0
pytest-appium                0.1
root@Gavin:~#

命令行启动的 appium server:

root@Gavin:~# appium server -ka 300 -a 127.0.0.1 -p 4723 --allow-cors --use-plugin relaxed-caps --use-drivers uiautomator2 --use-plugin execute-driver --log 4723.log
[Appium] Attempting to load plugin execute-driver...
[Appium] Requiring plugin at /root/.appium/node_modules/@appium/execute-driver-plugin/index.js
[Appium] ExecuteDriverPlugin has been successfully loaded in 0.063s
[Appium] Welcome to Appium v2.5.1
[Appium] Non-default server args:
[Appium] {
[Appium]   address: '127.0.0.1',
[Appium]   allowCors: true,
[Appium]   keepAliveTimeout: 300,
[Appium]   useDrivers: [
[Appium]     'uiautomator2'
[Appium]   ],
[Appium]   usePlugins: [
[Appium]     'execute-driver'
[Appium]   ]
[Appium] }
[Appium] The autodetected Appium home path: /root/.appium
[Appium] Attempting to load driver uiautomator2...
[Appium] Requiring driver at /root/.appium/node_modules/appium-uiautomator2-driver/build/index.js
[Appium] AndroidUiautomator2Driver has been successfully loaded in 0.951s
[Appium] You have enabled CORS requests from any host. Be careful not to visit sites which could maliciously try to start Appium sessions on your machine
[Appium] Appium REST http interface listener started on http://127.0.0.1:4723
[Appium] Available drivers:
[Appium]   - uiautomator2@3.0.4 (automationName 'UiAutomator2')
[Appium] Available plugins:
[Appium]   - relaxed-caps@1.0.6
[Appium]   - execute-driver@3.0.25 (ACTIVE)

variables 文件内容:

root@Gavin:~# cat /root/variables.json 
{
    "server": {
        "url": "http://127.0.0.1:4723"
    },
    "caps": {
        "platformName": "Android",
        "newCommonTimeout": 7200,
        "skipServerInstallation": true,
        "automationName": "UiAutomator2",
        "systemPort": 8200,
        "noReset": true,
        "fullReset": false,
        "deviceName": "62b6aca8",
        "platformVersion": "10",
        "appPackage": "com.xkw.client",
        "appActivity": "com.zxxk.page.main.LauncherActivity"
    }
}

测试用例内容:

root@Gavin:~# cat test_debug.py 
# -*- coding:UTF-8 -*-

import time
import pytest
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import AppiumOptions


# 定义一个fixture用于初始化和销毁WebDriver
@pytest.fixture
def driver(request):
    # 从pytest variables 插件中加载desired capabilities
    desired_caps = request.config.getoption('variables')
    server_url = desired_caps['server']['url']
    desired_caps = desired_caps['caps']

    # 初始化WebDriver
    appium_options = AppiumOptions()
    appium_options.load_capabilities(desired_caps)
    # driver = webdriver.Remote('http://localhost:4723/wd/hub', options=appium_options)
    driver = webdriver.Remote(server_url, options=appium_options)

    yield driver

    # 测试结束后关闭WebDriver会话
    driver.quit()


# 启动页同意
agree_btn = (AppiumBy.ID, "com.xkw.client:id/agree_yes")

# 登录页操作
mine_btn = (AppiumBy.ID, "com.xkw.client:id/mine_text")
login_btn = (AppiumBy.ID, "com.xkw.client:id/mine_username")
password_login_btn = (AppiumBy.ID, "com.xkw.client:id/login_mobile_use_password")
username_input = (AppiumBy.ID, "com.xkw.client:id/login_password_username")
password_input = (AppiumBy.ID, "com.xkw.client:id/login_password_password")
login_submit_btn = (AppiumBy.ID, "com.xkw.client:id/login_password_login")

discover_search_box = (AppiumBy.ID, "com.xkw.client:id/discover_search_box")

# 测试函数,使用driver fixture
def test_example(driver):
    # 同意并进入
    time.sleep(2)
    agree = driver.find_element(agree_btn)
    agree.click()

    time.sleep(3)
    mine = driver.find_element(mine_btn)
    mine.click()

    # # 测试可以在这里继续,比如验证登录是否成功
    # # ...

# 这里使用pytest命令执行定义的测试函数
if __name__ == "__main__":
    pytest.main()

用例执行报错:

root@Gavin:~# PYTHONPATH=. pytest --variables=/root/variables.json -s -v test_debug.py 
================================================================================================================== test session starts ==================================================================================================================
platform linux -- Python 3.11.6, pytest-8.0.2, pluggy-1.4.0 -- /usr/bin/python3
cachedir: .pytest_cache
Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type>
sensitiveurl: .*
metadata: {'Python': '3.11.6', 'Platform': 'Linux-6.5.0-26-generic-x86_64-with-glibc2.38', 'Packages': {'pytest': '8.0.2', 'pluggy': '1.4.0'}, 'Plugins': {'cov': '4.1.0', 'order': '1.2.0', 'random-order': '1.1.1', 'check': '2.2.2', 'instafail': '0.5.0', 'allure-pytest': '2.13.2', 'selenium': '4.1.0', 'xdist': '3.5.0', 'variables': '3.1.0', 'rerunfailures': '13.0', 'html': '4.1.1', 'progress': '1.2.5', 'metadata': '3.0.0', 'picked': '0.5.0', 'appium': '0.1', 'Faker': '24.0.0', 'repeat': '0.9.3', 'base-url': '2.1.0', 'dependency': '0.6.0', 'timeout': '2.2.0'}, 'JAVA_HOME': '/usr/lib/jdk1.8.0_171', 'Base URL': '', 'Driver': None, 'Capabilities': {}}
rootdir: /root
plugins: cov-4.1.0, order-1.2.0, random-order-1.1.1, check-2.2.2, instafail-0.5.0, allure-pytest-2.13.2, selenium-4.1.0, xdist-3.5.0, variables-3.1.0, rerunfailures-13.0, html-4.1.1, progress-1.2.5, metadata-3.0.0, picked-0.5.0, appium-0.1, Faker-24.0.0, repeat-0.9.3, base-url-2.1.0, dependency-0.6.0, timeout-2.2.0
collected 1 item                                                                                                                                                                                                                                        

test_debug.py::test_example SKIPPED ('NoneType' object has no attribute 'to_capabilities')

================================================================================================================== 1 skipped in 0.03s ===================================================================================================================
root@Gavin:~# 

额外补充说明:

  1. 有尝试过使用 pytest-appium-client 3.x 的版本,问题依旧
  2. 有尝试过删除掉 driver fixture,直接将 desired_caps 内容直接写入到此文件中,不使用 variables,但所有的报错信息都指向'NoneType' object has no attribute 'to_capabilities'
共收到 2 条回复 时间 点赞

独立出来执行这部分代码:

import time

from appium import webdriver
from appium.webdriver.webdriver import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy


appium_options = AppiumOptions()
desired_caps ={
    "platformName": "Android",
    "newCommonTimeout": 7200,
    "skipServerInstallation": True,
    "automationName": "UiAutomator2",
    "systemPort": 8200,
    # "noReset": True,
    # "fullReset": False,
    "deviceName": "62b6aca8",
    "platformVersion": "10",
    "appPackage": "com.xkw.client",
    "appActivity": "com.zxxk.page.main.LauncherActivity"
   }
appium_options.load_capabilities(desired_caps)

driver = webdriver.Remote('http://127.0.0.1:4723', options=appium_options)
print(f"Session ID: ({driver.session_id})")

time.sleep(6)
agree = driver.find_element(AppiumBy.ID, "com.xkw.client:id/agree_yes")
agree.click()

time.sleep(10)
mine = driver.find_element(AppiumBy.ID, "com.xkw.client:id/mine_text")
mine.click()

driver.quit()

运行结果如下:

C:\Python312\python.exe F:/workspace/MobileAppTestFramework/sample_test.py
Session ID: (8a9fc17d-b4da-467f-bff6-43516e0f13b8)

Process finished with exit code 0

APP GUI 页面点击 OK,说明 driver 初始化是 OK 的

Damn!After uninstall pytest-appium,everything works well。😂

strayeagle 关闭了讨论 03月25日 09:11
strayeagle 重新开启了讨论 03月25日 09:11
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册