51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1361|回复: 1
打印 上一主题 下一主题

[Appium] 一个新版本引发一个问题之Appium

[复制链接]
  • TA的每日心情
    无聊
    2024-7-29 11:15
  • 签到天数: 32 天

    连续签到: 1 天

    [LV.5]测试团长

    跳转到指定楼层
    1#
    发表于 2023-7-21 10:13:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 韶光暗淡 于 2023-7-21 10:19 编辑

    准备工作
    1、测试代码
    1. <font size="3">from appium import webdriver
    2. des_cap = {'platformName': 'android'}
    3. driver = webdriver.Remote(command_executor='http://127.0.0.1:4723/wd/hub',
    4.                           desired_capabilities=des_cap)</font>
    复制代码
    2、测试环境
    • python 3.10,虚拟环境
    • pycharm 2018 community
    • 测试时间 2023-7-20

    3、场景一:默认安装PASS
    • 在pycharm中安装appium-python-client,版本不指定,此时是2.11.1
    • 对应依赖selenium4.10.0
    • 执行示例代码
    • 测试通过
    • ??? 所以博主你要表达啥
    • 继续看下去


    4 场景二:appium-python-client2.6.0+selenium4.10 FAlL
    • 你根据指定版本安装appium-python-client为2.6,自动安装selenium4.10
    • 执行示例代码
    • 测试失败
    • 提示如下


    1. <font size="3">D:\Appium01\venv\Scripts\python.exe D:/Appium01/demo1.py
    2. Traceback (most recent call last):
    3.   File "D:\Appium01\demo1.py", line 9, in <module>
    4.     driver = webdriver.Remote(command_executor='http://127.0.0.1:4723/wd/hub',
    5.   File "D:\Appium01\venv\lib\site-packages\appium\webdriver\webdriver.py", line 230, in __init__
    6.     super().__init__(
    7. TypeError: WebDriver.__init__() got an unexpected keyword argument 'desired_capabilities'</font>
    复制代码

    五 场景3:appium-python-client2.6.0+selenium4.3.0 PASS
    • 你应该是先安装selenium4.3.0
    • 然后再安装appium-python-client2.6.0
    • 都是指定版本安装

      • 有同学会说,谁会这样安装呢
      • 会的,因为你可能是先学selenium(我课程要求是4.3,最新的版本4.10的改进对我们没有太大意义,但底层确实改变了很多)

    • 测试通过


    6、问题说明TypeError 分析
    先看报错
    1. <font size="3">TypeError: WebDriver.__init__() got an unexpected keyword argument 'desired_capabilities'</font>
    复制代码
    • 主要版本信息:


      • appium-python-client2.6.0
      • selenium4.10

    • 报错行


    1. <font size="3">driver = webdriver.Remote</font>
    复制代码
    Remote是个别名
    1. <font size="3"> from .webdriver import WebDriver as Remote</font>
    复制代码

    看WebDriver源码
    1. <font size="3">class WebDriver(
    2.     webdriver.Remote,
    3.     ActionHelpers,
    4.     Activities,
    5.     Applications,
    6.     Clipboard,
    7.     Context,
    8.     Common,
    9.     DeviceTime,
    10.     Display,
    11.     ExecuteDriver,
    12.     ExecuteMobileCommand,
    13.     Gsm,
    14.     HardwareActions,
    15.     ImagesComparison,
    16.     IME,
    17.     Keyboard,
    18.     Location,
    19.     LogEvent,
    20.     Network,
    21.     Performance,
    22.     Power,
    23.     RemoteFS,
    24.     ScreenRecord,
    25.     Session,
    26.     Settings,
    27.     Sms,
    28.     SystemBars,
    29. ):
    30.     def __init__(
    31.         self,
    32.         command_executor: str = 'http://127.0.0.1:4444/wd/hub',
    33.         desired_capabilities: Optional[Dict] = None,
    34.         browser_profile: str = None,
    35.         proxy: str = None,
    36.         keep_alive: bool = True,
    37.         direct_connection: bool = True,
    38.         extensions: Optional[List['WebDriver']] = None,
    39.         strict_ssl: bool = True,
    40.         options: Union[AppiumOptions, List[AppiumOptions]] = None,
    41.     ):</font>
    复制代码
    • __init__中传递了desired_capabilities没有问题
    • 继续分析堆栈


    1. <font size="3">File "D:\Appium01\venv\lib\site-packages\appium\webdriver\webdriver.py", line 230, in __init__
    2.     super().__init__(</font>
    复制代码

    继续看WebDriver此处源码
    1. <font size="3">File "D:\Appium01\venv\lib\site-packages\appium\webdriver\webdriver.py", line 230, in __init__
    2.     super().__init__(</font>
    复制代码
    继续看WebDriver此处源码
    1. <font size="3">        super().__init__(
    2.             command_executor=AppiumConnection(command_executor, keep_alive=keep_alive),
    3.             desired_capabilities=desired_capabilities,
    4.             browser_profile=browser_profile,
    5.             proxy=proxy,
    6.             options=options,
    7.         )</font>
    复制代码
    • 这里也有desired_capabilities,为何报错了呢
    • 请看WebDriver的继承webdriver.Remote


    1. <font size="3">class WebDriver(BaseWebDriver):
    2.     _web_element_cls = WebElement
    3.     _shadowroot_cls = ShadowRoot

    4.     def __init__(
    5.         self,
    6.         command_executor="http://127.0.0.1:4444",
    7.         keep_alive=True,
    8.         file_detector=None,
    9.         options: Union[BaseOptions, List[BaseOptions]] = None,
    10.     ) -> None:</font>
    复制代码

    • 到这里你发现了,这个__init__里面没有desired_capabilities
    • 注意webdriver.Remote是隶属于selenium的,你此时的selenium是4.10,升级了,可能导致它remove了一些参数

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2024-7-29 11:15
  • 签到天数: 32 天

    连续签到: 1 天

    [LV.5]测试团长

    2#
     楼主| 发表于 2023-7-21 10:17:48 | 只看该作者
    6.2appium-python-client2.11.1+selenium4.10
    • 这是默认组合,要知道selenium也是4.10了,为何没有报错呢?
    • 其调用关系简单分析下
    • 在Remote的__init__中,也支持desired_capabilities,但有如下信息


    1. <font size="3">        # TODO: Remove the deprecated arg
    2.         desired_capabilities: Optional[Dict] = None,
    3.         
    4.         if desired_capabilities is not None:
    5.             warnings.warn(
    6.                 'desired_capabilities argument is deprecated and will be removed in future versions. '
    7.                 'Use options instead.',
    8.                 DeprecationWarning,
    9.             )</font>
    复制代码



      • 后续要移除desired_capabilities
      • 用options替代(模仿selenium)

    • 关键的问题是在于,appium-python-client2.11.1中对父类__init__的调用是不携带desired_capabilities的


    1. <font size="3">        super().__init__(
    2.             command_executor=command_executor,
    3.             options=dst_options,
    4.         )</font>
    复制代码

    [backcolor=rgba(255, 255, 255, 0.9)]完整代码片段如下
    1. <font size="3">class WebDriver(
    2.     webdriver.Remote,
    3.     ActionHelpers,
    4.     Activities,
    5.     Applications,
    6.     Clipboard,
    7.     Context,
    8.     Common,
    9.     DeviceTime,
    10.     Display,
    11.     ExecuteDriver,
    12.     ExecuteMobileCommand,
    13.     Gsm,
    14.     HardwareActions,
    15.     ImagesComparison,
    16.     IME,
    17.     Keyboard,
    18.     Location,
    19.     LogEvent,
    20.     Network,
    21.     Performance,
    22.     Power,
    23.     RemoteFS,
    24.     ScreenRecord,
    25.     Session,
    26.     Settings,
    27.     Sms,
    28.     SystemBars,
    29. ):
    30.     def __init__(
    31.         self,
    32.         command_executor: Union[str, AppiumConnection] = 'http://127.0.0.1:4444/wd/hub',
    33.         # TODO: Remove the deprecated arg
    34.         desired_capabilities: Optional[Dict] = None,
    35.         # TODO: Remove the deprecated arg
    36.         browser_profile: Union[str, None] = None,
    37.         # TODO: Remove the deprecated arg
    38.         proxy: Union[str, None] = None,
    39.         keep_alive: bool = True,
    40.         direct_connection: bool = True,
    41.         extensions: Optional[List['WebDriver']] = None,
    42.         strict_ssl: bool = True,
    43.         options: Union[AppiumOptions, List[AppiumOptions], None] = None,
    44.     ):
    45.         if strict_ssl is False:
    46.             # pylint: disable=E1101
    47.             # noinspection PyPackageRequirements
    48.             import urllib3

    49.             # pylint: disable=E1101
    50.             # noinspection PyPackageRequirements
    51.             import urllib3.exceptions

    52.             # noinspection PyUnresolvedReferences
    53.             AppiumConnection.set_certificate_bundle_path(None)
    54.             urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

    55.         if isinstance(command_executor, str):
    56.             command_executor = AppiumConnection(command_executor, keep_alive=keep_alive)

    57.         if browser_profile is not None:
    58.             warnings.warn('browser_profile argument is deprecated and has no effect', DeprecationWarning)

    59.         if proxy is not None:
    60.             warnings.warn('proxy argument is deprecated and has no effect', DeprecationWarning)

    61.         if desired_capabilities is not None:
    62.             warnings.warn(
    63.                 'desired_capabilities argument is deprecated and will be removed in future versions. '
    64.                 'Use options instead.',
    65.                 DeprecationWarning,
    66.             )
    67.         # TODO: Remove the fallback after desired_capabilities removal
    68.         dst_options = (
    69.             AppiumOptions().load_capabilities(desired_capabilities)
    70.             if desired_capabilities is not None and options is None
    71.             else options
    72.         )

    73.         super().__init__(
    74.             command_executor=command_executor,
    75.             options=dst_options,
    76.         )</font>
    复制代码
    6.3appium-python-client2.6.0+selenium4.3.0
    • 想必分析到此处,你应该盲猜能知道为何这个也PASS了
    • 是因为selenium的版本中webdriver.Remote中是有desired_capabilities的




    1. <font size="3">class WebDriver(BaseWebDriver):
    2.     _web_element_cls = WebElement
    3.     _shadowroot_cls = ShadowRoot

    4.     def __init__(self, command_executor='http://127.0.0.1:4444',
    5.                  desired_capabilities=None, browser_profile=None, proxy=None,
    6.                  keep_alive=True, file_detector=None, options: Union[BaseOptions, List[BaseOptions]] = None):</font>
    复制代码
    7.0总结:
    • 最新版本appium-python-client即将不提供desired_capabilities的传参,但目前能用
    • 在selenium4.10中已经不支持desired_capabilities参数
    • 错误的搭配可能会引发上述问题,要么用最新的版本(默认安装),要么2个都用较低的版本
    • 留在最后的问题,那么在appium最新版中应该如何传递能力值呢?

    1. <font size="3">from appium import webdriver
    2. from appium.options.common import AppiumOptions

    3. option = AppiumOptions()
    4. option.set_capability('platformName','android')
    5. driver = webdriver.Remote(command_executor='http://127.0.0.1:4723/wd/hub',
    6.                           options=option)</font>
    复制代码

    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-22 16:36 , Processed in 0.067116 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表