Appium-Desktop测试flutter应用

软件测试 专栏收录该内容
1 篇文章 0 订阅

本博客主要讲解怎么用appium-desktop测试纯flutter应用

Android端

准备

  1. 一台window电脑
  2. 安装最新appium-desktop(https://github.com/appium/appium-desktop/releases,我是1.18.3,因为appium只有在高版本才能测试flutter)

步骤

  1. 给要测试的flutter应用添加依赖
    dev_dependencies:
      test: any
      flutter_test:
        sdk: flutter
      flutter_driver:
        sdk: flutter

     

  2. 给main方法添加代码

    void main() {
      enableFlutterDriverExtension();
      runApp(MyApp());
    }

      这里给出main.dart的代码

    import 'package:flutter/material.dart';
    import 'package:flutter_driver/driver_extension.dart';
    
    void main() {
      enableFlutterDriverExtension();
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Counter App',
          home: MyHomePage(title: 'Counter App Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: ListView.builder(
            itemExtent: 80,
            itemCount: 10000,
            itemBuilder: (context,index){
              return Container(
                alignment: AlignmentDirectional.center,
                child: Text(index.toString()),
              );
           }),
          )
        );
      }
    }
    

     

  3.  将flutter 应用打包成debug版或者profile版apk

    flutter build apk --debug

     

  4.  编写测试脚本,脚本中要用到一个第三方包(https://github.com/truongsinh/appium-flutter-driver),我是用python写的脚本,所以直接用即可安装

    pip install Appium-Flutter-Finder

    然后代码里导包

    import os
    
    from appium.webdriver import Remote
    from appium_flutter_finder import FlutterElement, FlutterFinder

     如果FlutterElement, FlutterFinder编辑器一直显示导不进来,你可以去pip下载的文件夹那里(一般是在python\Lib\site-packages\appium_flutter_finder)下的_init_.py,添加代码即可

    from .flutter_finder import *

    测试代码方面不同的主要是获取元素的api和对元素操作的api不同,这里以一个不断滑动listview的脚本作为示例,模板代码如下

    import os
    
    from appium.webdriver import Remote
    from appium_flutter_finder import FlutterElement, FlutterFinder
    
    import time
    
    
    driver = Remote('http://localhost:4723/wd/hub', dict(
        platformName='Android',
        automationName='Flutter',#自动化引擎要选Flutter
        platformVersion='10',
        deviceName='PQY5T20B11029932',
        appPackage="com.example.first_flutter",
        app="D:/appium_code/apk/demo-debug.apk", #填写你刚刚打包好的apk
        appActivity="com.example.first_flutter.MainActivity",
        noReset="True",
        retryBackoffTime=500
    ))
    
    finder = FlutterFinder()#用于搜索元素
    four=FlutterElement(driver, finder.by_text("4"))#通过文本“4”来搜索元素
    six=FlutterElement(driver, finder.by_text("6"))#通过文本“6”来搜索元素
    four_get_center_params={
        "script":"flutter:getCenter", #这里设置要发给设备应用的命令
        "args":[four._id] #命令的参数
    }
    six_get_center_params={
        "script":"flutter:getCenter",#这里设置要发给设备应用的命令
        "args":[six._id] #命令的参数
    }
    four_center=driver.execute('executeScript',four_get_center_params)#获取元素的中心坐标
    six_center=driver.execute('executeScript',six_get_center_params)#获取元素的中心坐标
    d_value=six_center["value"]["dy"]-four_center["value"]["dy"]#计算两个元素的坐标高度差值
    up_scroll_params={
        "script":"flutter:scroll",#这里设置要发给设备应用的命令
        "args":[six._id,{"dx":0.01,"dy":-(d_value),"durationMilliseconds":20}]#命令的参数
    }
    down_scroll_params={
        "script":"flutter:scroll",#这里设置要发给设备应用的命令
        "args":[six._id,{"dx":0.01,"dy":d_value,"durationMilliseconds":20}]#命令的参数
    }
    time_start=time.time()
    for i in range(1,20):
        driver.execute('executeScript',up_scroll_params)#将元素“6”上划到元素“4”的位置
        driver.execute('executeScript',down_scroll_params)#将元素“6”下划到原来的位置
    time_end=time.time()
    print('totally cost',time_end-time_start," sceonds")
    driver.quit() #退出应用

     其中获取元素的方法以及参数script的命令主要要看着https://github.com/truongsinh/appium-flutter-driver的说明来设置,相信各位照着这个代码依葫芦画瓢应该就能写出和其他的测试代码了,当然这个第三方插件也支持使用java、node‘、ruby来写测试脚本,具体可以去仓库的example目录下查看

  5. 然后启动appium的服务器并运行脚本就可以自动化测试了

 

IOS端

ios端相对android来说就比较复杂,但是大体思路是一样的

准备

  1. 一台mac电脑
  2. 一台ios手机(版本最好不要太高,ios14以下就差不多了)
  3. 安装最新appium-desktop(https://github.com/appium/appium-desktop/releases,我是1.18.3,因为appium只有在高版本才能测试flutter)

步骤

在被测应用方面的代码与android端的一样

  1. 编译代码打包成debug版app
    flutter build ios --debug

    编译打包之后就可以在目标项目里的Products文件夹看到打包好的app

  2. 编写测试脚本,代码与安卓端的一致,只是配置参数要改

    
    Appium-Desktop测试flutter应用
    25/100
    weixin_41641941
    
    
    Python
    import os
    
    from appium.webdriver import Remote
    from appium_flutter_finder import FlutterElement, FlutterFinder
    
    import time
    
    
    driver = Remote('http://localhost:4723/wd/hub', dict(
        platformName='ios', #app平台
        automationName='flutter', #测试引擎要选flutter
        platformVersion="13.4.1", #ios版本
        deviceName='iPhone',
        bundleId="com.example.firstFlutter", #应用包名
        udid="b9c49f2e4484b89c655b091340db65fd0a6cb781", #测试手机的udid,获取方法可自行百度
        noReset="True",
        retryBackoffTime=500,
        app="/Users/willyliu/Documents/appium_code/ipa/Runner.app", #刚刚打包的app路径
    ))
    
    finder = FlutterFinder()#用于搜索元素
    four=FlutterElement(driver, finder.by_text("4"))#通过文本“4”来搜索元素
    six=FlutterElement(driver, finder.by_text("6"))#通过文本“6”来搜索元素
    four_get_center_params={
        "script":"flutter:getCenter", #这里设置要发给设备应用的命令
        "args":[four._id] #命令的参数
    }
    six_get_center_params={
        "script":"flutter:getCenter",#这里设置要发给设备应用的命令
        "args":[six._id] #命令的参数
    }
    four_center=driver.execute('executeScript',four_get_center_params)#获取元素的中心坐标
    six_center=driver.execute('executeScript',six_get_center_params)#获取元素的中心坐标
    d_value=six_center["value"]["dy"]-four_center["value"]["dy"]#计算两个元素的坐标高度差值
    up_scroll_params={
        "script":"flutter:scroll",#这里设置要发给设备应用的命令
        "args":[six._id,{"dx":0.01,"dy":-(d_value),"durationMilliseconds":20}]#命令的参数
    }
    down_scroll_params={
        "script":"flutter:scroll",#这里设置要发给设备应用的命令
        "args":[six._id,{"dx":0.01,"dy":d_value,"durationMilliseconds":20}]#命令的参数
    }
    time_start=time.time()
    for i in range(1,20):
        driver.execute('executeScript',up_scroll_params)#将元素“6”上划到元素“4”的位置
        driver.execute('executeScript',down_scroll_params)#将元素“6”下划到原来的位置
    time_end=time.time()
    print('totally cost',time_end-time_start," sceonds")
    driver.quit() #退出应用
     

     

  3. 然后当你自信地启动appium服务器并且运行脚本之后,你会发现脚本一直没有运行,但是也不报错,这时你看一下appium服务器的日志就会发现下面这个异常,这个异常的原因是appium要用到http和websocket两种协议来与手机进行通信,其中http已经通过端口(8100)转发到手机上了,但是websocket他就没有自动设置转发,原因暂时还不知道,可能要看一下 源码

  4. 手动设置ip转发,这个相当于每次你启动脚本的时候都要去日志看一下要转发的端口号是多少,然后再手动设置转发,之后等待一段时间就ok了,然后脚本就正常运行
    brew install libimobiledevice //安装iproxy软件
    iproxy 57771 57771 //将电脑57771端口的请求转发到手机57771端口上

     

     

     

     


     -----------------------------------------------------------------------------------------------分割线-----2020年12月1号--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

通过查看appium-desktop的源码,因为只有在automationName="Flutter"时才会出现上述的异常,所以我查看的是有关appium-flutter-driver的源码,具体路径是/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-flutter-driver/build/driver/lib/sessions/observatory.js,在这个文件里可以看到以下代码

可以看的出来,日志的报错就是在这里输出的,调用的话则是在相同文件夹下的ios.js文件里,

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-ignore
const appium_xcuitest_driver_1 = __importDefault(require("appium-xcuitest-driver"));
const logger_1 = require("../logger");
const observatory_1 = require("./observatory");
const setupNewIOSDriver = async (caps) => {
    const iosArgs = {
        javascriptEnabled: true,
    };
    const iosdriver = new appium_xcuitest_driver_1.default(iosArgs);
    const capsCopy = Object.assign({}, caps, { newCommandTimeout: 0 });
    await iosdriver.createSession(capsCopy);
    return iosdriver;
};
exports.startIOSSession = async (caps) => {
    logger_1.log.info(`Starting an IOS proxy session`);
    const iosdriver = await setupNewIOSDriver(caps);
    const observatoryWsUri = exports.getObservatoryWsUri(iosdriver);#构造websock的url
    return Promise.all([
        iosdriver,
        observatory_1.connectSocket(observatoryWsUri),#建立websocke的连接
    ]);
};
exports.getObservatoryWsUri = (proxydriver) => {
    const urlObject = observatory_1.processLogToGetobservatory(proxydriver.logs.syslog.logs);#通过对手机的log信息进行字符串匹配“Observatory listening on”来知道手机的websocket监听端口是哪个
    return urlObject.toJSON();
};
//# sourceMappingURL=ios.js.map

可以看出来,代码里的确进行了与手机设备进行websocke的连接,准确的来说应该是想与手机上的WebDriverAgent App进行连接,但是由于mac的缘故不能直接进行连接,只能将电脑端口映射到手机上的端口,可惜代码里没有这一步的操作,但奇怪的是http协议的8100端口却自动进行了转发,日志里可以看到

所以说,如果能找到appium设置自动转发http 8100端口的代码 ,然后负责到appium-flutter-driver这里,那就能自动转发websocket的端口了,可惜没找到hhhhh

  • 2
    点赞
  • 5
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值