开源测试工具 (已开源) 基于 XCTestWD,swiftmonkey 二次开发,实现无需插桩的 iOS monkey 自动化工具 fastmonkey

zhangzhao_lenovo · 发布于 2017年07月28日 · 最后由 Only7 回复于 2017年08月21日 · 2820 次阅读
本帖已被设为精华帖!

打造一款快速高效且高度可复用的ios自动化测试工具

优势

  1. 无需插桩!
  2. 高效率,每秒4-5个action!
  3. 轻量极简!

原理

先致敬两个开源工具;

  1. swiftmonkey
    https://github.com/zalando/SwiftMonkey
    因其直接使用了 苹果的私有api 如XCEventGenerator.tapAtTouchLocations 故执行速度极快。同时也用类似android monkey的事件生成机制,自身源源不断的产生如 tap,swipe,pinchIn等事件使其对被测app产生了极大的压力
    缺点:需要插桩

  2. XCTestWD
    https://github.com/macacajs/XCTestWD
    类似facebook wda的方式,在xcode中执行xcuitest时启动一个监听server,可通过外部发送命令来创建待测app对应session并启动app,同时也实现了dump tree 和依据xpath,id等来定位某个控件并操作这些控件

  3. Fastmonkey
    https://github.com/zhangzhao4444/Fastmonkey
    结合两者优点并改造两者,在XCTestWD基础上实现一个server路由,外部命令时可引导启动app 并执行monkey

app插桩增加小手的反馈,可以更直观的看到其点击效率! (可选,实际不插也可monkey)

测试时会保存截图,及appcrash log(此处植入广告!)


解决问题

1.monkey执行过程中跳出app,如何跳回继续跑monkey
增加一个定时执行的action,检测当前app,如果不是待测则重新launcher(其时更好的应该时reactive,但并没有找到类似api)

public func addXCTestCheckCurrentApp(interval:Int, appname:String, application:XCUIApplication)  {
        addAction(interval:interval){ [weak self] in

            let current = XCTestWDFindElementUtils.getAppName(underElement: root!)
            let isRunning = application.running
            if current == appname && isRunning {
                for i in 0 ..< application.alerts.count {
                    let alert = application.alerts.element(boundBy: i)
                    ...
                }
            }else{
                application.launch()
                self!.sleep(5)

2.登陆等业务流程如何解决
同样增加一个定时的action,检测当某个关键点出现时,往事件队列中插入一个业务事件

public func addXCTestAppLogin(interval:Int, application:XCUIApplication) {
        addAction(interval:interval){ [weak self] in
           if root != nil{
                let usage = "xpath"
                let tag = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeTextField"
                let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!)
                ...
                    if element != nil {
                        self?.addXCTestLoginAction(application: application)
                    }

public func addXCTestLoginAction(application:XCUIApplication) {
        addAction(){ [weak self] in
            if root == nil{
                return
            }
            let usage = "xpath"
            let username = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeTextField"
            let passwd = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeSecureTextField"
            let button = "//XCUIElementTypeOther[@name='登录']//XCUIElementTypeStaticText[@name='登录']"

            var element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: username, underElement: root!)
            if let element = element {
                    let value = "abc"
                    ...
                    let semaphore = DispatchSemaphore(value: 0)
                    let numberOfTaps = 1
                    self!.sharedXCEventGenerator.tapAtTouchLocations(locations, numberOfTaps: UInt(numberOfTaps), orientation: orientationValue) {
                        semaphore.signal()
                    }
                    semaphore.wait()

未来

  1. 实现基于控件的monkey
  2. crash收集上报
  3. 性能数据
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 110 条回复
13930

期待开源....

306

这个图片分类有点牛批

15929

工具巨叼

2457

好工具,期待开放

1203

厉害了

110

请问能加入业务流程脚本嘛?

3170
110Lihuazhang 回复

业务流程脚本? 比如登陆吗? 如果是跑monkey过程中插入一些特定业务逻辑是可以的。 业务逻辑实际就是原子性的一系列点击输入。 如果是按case跑目前还不支持 改造会比较大 但理论上也是可以的

110

是这样子,就是比如有业务链路:

a->b->d->c->a

随机可能做不到。那如果我用脚本把这些链路都写成一个个业务脚本,可以当做插件插到框架中去,随机执行的话,就会更加有效果。

3170
110Lihuazhang 回复

可以的。这个链路执行的时候 ,随机会暂停。执行完随机再继续。只要设置好各个链路的触发点即可。相对于单个链路中的行为不随机,而不同链路之间也是随机的

209
110Lihuazhang 回复

好想法!

104 seveniruby 将本帖设为了精华贴 07月31日 02:25
3170
110Lihuazhang 回复

补充一个业务流程

7556

期待源码

7313

好工具 坐等开源

11419

能并发吗?

8139

其实现在的核心应该还是数据监控和数据分析,执行的话相对还比较好实现一些,期待楼主把未来那块补全,加油

3170
11419sixleaves 回复

稍微改造下可以的。

11783

膜拜大神,期待开源,牛的一批

5411

高效率,每秒4-5个action!
这块是带截图吗?
idevicescreenshot?

3170
5411junewang 回复

截图没有细研究,目前调试看截图是异步的,跟不上action的速度

5411

那会不会出现,截图看到的,和真实的不是一个地方的现象?

5411

另外想咨询一下:
关于检测是否在指定APP,调用的这个方法,是封装的吗? 具体是会调用哪个API? 或者内部的实现机制是?
let current = XCTestWDFindElementUtils.getAppName(underElement: root!)

目前感觉检测是否指定APP,还挺难实现的。 我看你这个方法,挺好。

3170
5411junewang 回复

打个比方,会出现点击了20次 可能才截出6,7张图。 截图比较鸡肋,实际效果不如录像或者log

3170
5411junewang 回复

自己加了个接口。

这个取得是 xml里 节点属性name

5411

这个func大致实现原理是?

log的话,是采用idevicesyslog来收集还是?
录屏是用什么方案😀

5411

重新launcher。
这块是用的什么方法?

我之前有使用过:idevicedebug 方法

3170
5411junewang 回复

重新launcher 就调的 XCUIApplication.launch()
但这样会重启app,我希望能后台切回前台是最好的。
见 官方api
https://developer.apple.com/documentation/xctest/xcuiapplication

感觉应该用 activate() 但目前只是beta的

3170
5411junewang 回复

log的 就记录每个action后 点击什么页面什么位置。

3170

已完成 基于控件的点击,解析出所有控件,随机某个控件点其中心点 。每秒大概3-4个action

15498

大赞

5411

log的 就记录每个action后 点击什么页面什么位置。

点击什么页面,这个是如何定义页面这个概念的? iOS端毕竟没有Android端activity

3170
5411junewang 回复

取title辅助定位就行。appname会引起个问题,那个函数要重写了

5411

取title辅助定位,是指类似dump出xml后,然后取里面的title?
这里面有没有什么规则? 如取几个,或者去布局的几个等?

有没有验证过,定义window后的准确率有多高? 即,进入相似页面,或者滑动后,是否认为是同一个页面。

5411

了解了,多谢。

3170
5411junewang 回复

xctestwd里已有api取title

37楼 已删除
25f875

请问XCEventGenerator这个API怎么获得啊~~~我在iOS-Runtime-Headers里面没找到,求大神分享一下

25f875

Thanks!
楼主太棒啦

但是第二个地址报404不知道是怎么回事~~~

虽然做伸手党有点可耻,但是我还是想问楼主这么强大的工具什么时候开源给大家用啊~~~~~

41楼 已删除
3170
25f875yxys01 回复

404 那个发帖时链接多了个( ,不明所以。。
这个仅仅是api简易说明。google搜搜就有了

11783

application.running , XCUIApplication 好像没有这个吧...

3170

注! 熊猫直播测试组 出品; 玩游戏关注熊猫直播

已开源了1.0.0.1002。 尚有瑕疵,望见谅。

运行说明:

  1. build 配置 类似wda
  2. 启动server前 执行 iproxy 8001 8001 做手机与mac的端口映射
  3. 在xcode中的XCTestWDUITests target 里执行 run the test case 启动server,开始监听8001端口
  4. 执行 ‘curl -X POST -H "xx" -d "xx" http ://127.0.0.1:8001/wd/hub/monkey’ ,开始执行monkey

配置:

XCTestWDMonkeyController.swift 
        let monkey = Monkey(frame: app.frame)
        monkey.addDefaultXCTestPrivateActions()
        monkey.addXCTestTapAlertAction(interval: 100, application: app)
        monkey.addXCTestCheckCurrentApp(interval: 10, application: app)     # app后台或退出检测
        //monkey.addXCTestAppLogin(interval: 50, application: app)          # 登陆业务逻辑   50次事件加入1次业务关键点检查,无登陆逻辑可注释
        monkey.monkeyAround()
MonkeyXCTestPrivate.swift 
public func addDefaultXCTestPrivateActions() {
        addXCTestTapAction(weight: 35)              #随机点击事件  100-200ms/action
        //addXCTestElementTapAction(weight: 10)     #基于控件的点击事件   执行概率: 10/(35+10+5)   300-400ms/action
        addXCTestLongPressAction(weight: 1)
        addXCTestDragAction(weight: 1)
        addXCTestPinchCloseAction(weight: 1)
        addXCTestPinchOpenAction(weight: 1)
        addXCTestRotateAction(weight: 1)
    }

注!事件序列如何实现:
通过设置一个关键点 引入一个事件序列,当检测到出现关键点时插入自定义事件序列,并立即执行; 可按此原理实现自己的事件序列

public func addXCTestAppLogin(interval:Int, application:XCUIApplication) {
        addAction(interval:interval){ [weak self] in
            do{
                let session = try XCTestWDSessionManager.singleton.checkDefaultSessionthrow()     #检测到出现'登录'关键点时 插入
                let root = session.application
                if root != nil{
                    let usage = "xpath"
                    let tag = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeTextField"
                    let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!)
                    if let element = element {
                        if element != nil {
                            self?.addXCTestLoginAction(application: application)   #插入一个特殊事件序列
                        }
                        else{
                            return
                        }
                    }
                }
            }catch{
                return
            }
        }
    }
public func addXCTestLoginAction(application:XCUIApplication) {     #该事件为一个原子事件序列,保证事件中不会插入其他事件
        addAction(){ [weak self] in
            do{
                let session = try XCTestWDSessionManager.singleton.checkDefaultSessionthrow()
                let root = session.application
                if root == nil{
                    return
                }
                let usage = "xpath"
                let username = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeTextField"
                let passwd = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeSecureTextField"
                let button = "//XCUIElementTypeOther[@name='登录']//XCUIElementTypeStaticText[@name='登录']"
                var element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: username, underElement: root!)
                if let element = element {
                    if let element = element {
                        NSLog("XCTestWDSetup->loginuser find?\(String(describing: element))<-XCTestWDSetup")
                        let value = "1111111111"
                        let rect = element.wdRect()
                        let point = CGPoint(x:rect["x"]!,y:rect["y"]!)
                        let locations = [point]
                        let semaphore = DispatchSemaphore(value: 0)
                        let numberOfTaps = 1
                        self!.sharedXCEventGenerator.tapAtTouchLocations(locations, numberOfTaps: UInt(numberOfTaps), orientation: orientationValue) {      #点击使用坐标,调用xctest私有api
                            semaphore.signal()
                        }
                        semaphore.wait()

注! 屏幕中控件获取如何加快速度
如果使用 app.descendants(matching: .xxx) 可以获取某种类型的控件集,但获取其中某个控件坐标时,xctest内部会再次执行一次当前界面查找确保控件仍存在,该过程测试时间过长,超过500ms甚至1s更多。故此处进行了优化,缩短了时间 ;最终点击某个控件控制在300-400ms

static func xpathToList(_ root:XCElementSnapshot, _ xpathQuery:String) -> [CGPoint]? {

        var mapping = [String:XCElementSnapshot]()
        let xml = generateXMLPresentation(root,nil,nil,defaultTopDir,&mapping)?.xml
        if xml == nil
        {return nil}

        let tree = try? XMLDocument(string: xml!, encoding:String.Encoding.utf8)    #xml tree
        let nodes = tree?.xpath(xpathQuery)   #筛选生成对应节点
        var list = [CGPoint]()
        for node in nodes! {
            if mapping[node.attr("private_indexPath")!] != nil{
                let x = (node.attr("x")! as NSString).floatValue
                let y = (node.attr("y")! as NSString).floatValue
                if (x <= 0) && (y <= 0)
                {continue}

                let snapshot = mapping[node.attr("private_indexPath")!]
                let isvisible = try? snapshot?.isWDVisible()    #仅isvisible的才视为当前可见,加入到point队列
                if isvisible == nil || isvisible! == false
                {continue}

                let w = (node.attr("width")! as NSString).floatValue
                let h = (node.attr("height")! as NSString).floatValue
                let cX = Int(x + w/2)
                let cY = Int(y + h/2)
                let point = CGPoint(x:cX,y:cY)
                if list.contains(point) == false {
                    list.append(point)
                }
            }
        }
        return list    #最终返回所选控件对应的坐标队列集
    }

注! app退出如何检测
(坑点!!! app切换或者闪退自身也需要时间,可能获取当前pid时app还未完成退出或切换操作)
app退出通过三种方式检测
1) app退出检测线程 每500ms执行一次, 检测耗时50ms

public func addXCTestCheckCurrentApp(interval:Int, application:XCUIApplication) {
        addCheck(interval:interval){ [weak self] in
            let work = DispatchWorkItem(qos:.userInteractive){
                let isRunning = application.running   #获取当前是否在运行中
                let current = Int(XCTestWDFindElementUtils.getAppPid())   #获取当前前台pid
                if current != self?.pid || !isRunning{   #当切换到后台或已退出时,执行launch
                    application.launch() 
                    self?.sleep(5)
                    self?.pid = Int(XCTestWDFindElementUtils.getAppPid())
                }
            }
            DispatchQueue.main.async(execute:work)  
        }
    }
static func getAppPid() -> Int32{
        var activeApplicationElement:XCAccessibilityElement?
        activeApplicationElement = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).activeApplications().first
        if activeApplicationElement == nil {
            activeApplicationElement = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).systemApplication() as? XCAccessibilityElement
        }
        let pid = activeApplicationElement?.processIdentifier    #通过私有api 获取当前前台pid 
        if pid == nil{
            return 0
        }
        return pid!
    }

上述检测方式 因为使用xcaxclient私有api和launch 只能在主线程中执行,故只能通过定时方式检测并插入高优先级队列执行。而且要尽量缩短其耗时从而不会影响其他各点击事件的执行频率

2) 低概率检测事件,获取pid前增加延迟

public func addXCTestTapAlertAction(interval: Int, application: XCUIApplication) {
        addAction(interval: interval) { [weak self] in
            usleep(2000000)   #sleep 2s
            let isRunning = application.running
            let current = Int(XCTestWDFindElementUtils.getAppPid())

3) 最后一关把控,当resovle前再检测一次

func resolve() throws {
        self._application.query()
        let pid = self._application.processID
        let activeApplicationElement = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).activeApplications().first
        let currentprocessID = activeApplicationElement?.processIdentifier     #@A@
        if pid != currentprocessID{    #最后把关 pid不同 则抛出异常
            throw OperationError.Error
        }
        #@B@
        self._application?.resolve()  

    }

此处实现目前仍存在瑕疵,如果app在上述@A处仍在前台,@B处却切到后台,monkey可能crash,原因是此时application已不在 _application.resolve崩溃。但当xcode9发布时应该就不存在问题了,新api 提供了state,可以线程检测当前状态
(此崩溃仅会出现在 开启基于的控件点击)

未来后续;
1) 瑕疵修正
2) 性能监控
3) 崩溃分析
4) 控件选择子 算法

3170
11783Tonyzhangcanon 回复

我测试这个是可以用,可能没公开。我当时搜google 好像在某个stackoverflow里看到的。

69ae3c

@zhangzhao_lenovo 楼主强大 问个问题 就是这个录屏是怎么实现的?是通过screenshort()这个返回的截图合成的视频么
还有一个疑问就是getPageSource()这个拿页面的xml结构的api好慢呀 有没有什么好的办法

3170
69ae3cpliue 回复

录屏我也还没有实现,仅仅是个想法。
你说的getpagesource 是哪个框架的api? 在44楼发了个优化的方案,牺牲一些准确度来提升获取速度。

69ae3c

@感谢楼主回复 getpagesource这个是appium的实际上就是调用的wda的source 取页面的xml结构 因为我现在做了一个事实操控ios的平台 其他部分已经优化了但就是唯独获取页面xml这块 复杂的页面居然要10s 不好意思 还有一个问题 就是XCTestWD貌似要安装两个app 表示没有开发者账号很蛋疼 你这个要安装多少个app呀 在手机上 谢谢

69ae3c

还有一个就是我发现wda的查找控件我一般是根据id 需要1s多 然后点击啥的也要1s多

3170
69ae3cpliue 回复

是的,需要占两个bundle id

69ae3c

我在想一个问题 是不是swift比object-c的效率要高点 我发现相同的操作 wda的运行速度要低于XCTestWD

69ae3c

@zhangzhao_lenovo 我一开始就选的wda 所以我现在执行一个action 基本上都要2-3s
真想换成XCTestWD

3170
69ae3cpliue 回复

没有 我看wda,xctestwd代码大致类似。 理论上oc的应该更快些,你那里速度慢 根本原因是用的appium,中间经过了太多过程,比如网络请求

13851

Hi 楼主 iOS初级用户请教,我在打开XCTestWD.xcodeproj 文件时,提示我下图错误(我的是xcode9 beta5)说是缺少文件,请教如何解决,谢谢~

55楼 已删除
69ae3c

@zhangzhao_lenovo 我在取xml的时候 是直接通过调用的wda没有经过appium还是差不多慢一点 而且这又有个新的问题 当我用iproxy得时候 映射到本地mac的ip地址是127.0.0.1也就是说 我通本机的ip地址是无法访问的 这个有木有比较好的解决办法呀 对了性能数据的获取我已经做好了 需要的话 可以找我拿

25f875
69ae3cpliue 回复

大佬你怎么做的性能数据的获取啊?注入式还是?

69ae3c

@yxys01 是的 直接把代码注入到wda中然后以rest服务的形式发布出来

13851

谢谢楼主回复,我打开后里面还是没找到,我是刚从你的git上clone 下来的,里面没这个文件,能发一个给我吗或者楼主重新传一个到git上,谢谢~

25f875
69ae3cpliue 回复

我今天WDA不知道怎么回事报错:
2017-08-15 15:23:50.445222+0800 XCTRunner[3977:2074841] Running tests...
2017-08-15 15:23:50.874611+0800 XCTRunner[3977:2074893] Connection peer refused channel request for "dtxproxy:XCTestDriverInterface:XCTestManager_IDEInterface"; channel canceled
Failed to run tests: The operation couldn’t be completed. (DTXProxyChannel error 1.)
大佬知道这个该怎么解决吗?

69ae3c

1.断掉use线 然后重启wda
2.重启手机 重启wda
能解决95%的wda问题
@yxys01

69ae3c

@zhangzhao_lenovo 楼主 你的xml是通过sctestwd取得么 怎么取得呀

13851

刚从楼主的git上clone的zip包,报错缺少project.pbxproj 文件,各位大神们,谁有这个文件发一个呗,万分谢谢~邮箱:zhulixin@live.com

3170
13851slideplustest 回复

所有文件又重新提交了。你再clone试试,应该是环境问题

3170
69ae3cpliue 回复

44楼的 xpathToList 我取的point集合

3170
69ae3cpliue 回复

25楼那个 func 效率低 重写了

69ae3c

@zhangzhao_lenovo 我已找到了
XCTestWDXPath 这个类中就有 生成xml的方法 哈哈 好开心

13851

谢谢楼主,还是不行,不知道是不是我的环境问题(我xcode版本Xcode 9 beta 5),还是同样的错误,提示我缺少那个文件,楼主直接发我一个这个文件,我拷贝过来可以用吗?如果可以的话,楼主可以邮件发我下吗?谢谢~麻烦了~ 我邮箱 zhulixin@live.com

D754b7

楼主,我这边遇到了同样的问题,提示
“....Fastmonkey/XCTestWD-master/XCTestWD/XCTestWD.xcodeproj cannot be opened because it is missing its project.pbxproj file.”
刚重新下载,还是不行,在线等~

2506

Xcode 8.3.2 打开同样问题
XCTestWD-master/XCTestWD/XCTestWD.xcodeproj cannot be opened because it is missing its project.pbxproj file.

3170
13851slideplustest 回复

可能我少传了.. 马上看下

13851

hi 楼主 git用户@magaofei 发现那个缺失的文件是写到了 .gitignore 文件里,他已经给复制出来了,其他朋友如果遇到这个问题,可以.gitignore 里找,或者直接clone https://github.com/magaofei/Fastmonkey.git,谢谢楼主的积极回复,万分感谢~

3170
13851slideplustest 回复

@magaofei 感谢 ,已修正了问题。

75楼 已删除
3170

赞一下 👍 我还在晕头中,你已经改好了。

D754b7

感谢各位大神们,可以打开了!!激动中~

15498

我把项目克隆下来, 发现打不开, 把错误Google了一下, 从原版XCTestWD当中xcodeproj文件的包内容, 复制了一个文件过去, 再重新拉项目文件, 又提示缺东西, 我看又有新的更新, 我pull了就好了, 其他人还说有问题, 然后我发现我修改了xcodeproj文件后git没有提示任何变动, 想了一会才发现是 .gitignore 文件的问题

1db7ea



请问楼主这怎添加

3170
1db7eaAlanFightting 回复

第三方库都用cartfile安装

81楼 已删除
11783

application.running 没公开的话,是如何能使用的呢? 你用的是Xcode9?

3170
11783Tonyzhangcanon 回复

我的是8.3.3 ,这个试试便知了

1db7ea

谢谢回复,安装好了,再问一下可否做到多台设备一起测试

3170
1db7eaAlanFightting 回复

可以的。但需要代码修改下。 1启动server监听的端口 2iproxy端口 3curl命令请求的端口
有空我再改下,xcodebuild 直接完成 1,2,3 ,这样可以简单对接到jenkins支持多机了

69ae3c

楼主 swift 里面怎么取一个map的value值么@zhangzhao_lenovo 这个语言真的是坑呀

3170
69ae3cpliue 回复

有那么点像python。但!,?,_ 这些并不友好。而且异常捕获也很坑

// 查询字典
dict["name"]

// 遍历字典中所有的值
for value in dict.values {
    print(value)
}
if mapping[node.attr("private_indexPath")!] != nil{

               let snapshot = mapping[node.attr("private_indexPath")!]
1db7ea

参照swiftMonkey的似乎没有限制时长的,我在原地方看到有个扩展方法设置跑的时间
https://www.ctolib.com/article/comments/23532

extension Monkey {
func startTesting(forDuration duration: TimeInterval) {
let start = CFAbsoluteTimeGetCurrent() // start time

repeat {
actRandomly()
actRegularly()
} while ((CFAbsoluteTimeGetCurrent() - start) < duration)
}
}

3170
1db7eaAlanFightting 回复

ok这个时长已计划

69ae3c

@zhangzhao_lenovo 突然发现xctestwd 不支持utf-8的中文 怎么搞呀

3170
69ae3cpliue 回复

输入中文字符 ?

69ae3c

@zhangzhao_lenovo 查询控件的时候 控件的id为中文
let value = request.jsonBody["value"].string 这里取出来的就是???????

69ae3c

@zhangzhao_lenovo request这个里面就已经解析成?了 转码也转不鸟了 我看了下源码 是把所有的存成了Uint8
不知道作者怎么想的

3170
69ae3cpliue 回复

调式下看看 是从哪里开始存成??了。感觉上层macaca也会有获取中文的需求,不应该啊

69ae3c

@zhangzhao_lenovo 解析请求的时候 存成了Uint8 这玩意 这玩意存不鸟中文

3170
69ae3cpliue 回复

哦 我明白了。你是说,发给 xctestwd的请求 如 控件的id是个中文。 xctestwd接收到就解析成 uint8了。。 @xdf 达峰帮看看?

69ae3c

@zhangzhao_lenovo @xdf 对的 对的 而且能不能把两个应用合成一个呀 没有开发者账号 要是再加一个应用就不行了
谢谢

69ae3c

@zhangzhao_lenovo @xdf clear 清除文本这个方法写的也有问题

3170
69ae3cpliue 回复

哪个clear清除? 你发的请求是什么?

2457

@zhangzhao_lenovo @pliue 确认的问题请提issue

69ae3c

@xdf 已在github上提了

69ae3c

@zhangzhao_lenovo @xdf (RequestRoute("/wd/hub/session/:sessionId/element/:elementId/clear", "post"), clearText),
这个方法 element?.typeText(“”) 这样是不会清除文本的 我改了下:
let text:String = firstNonEmptyValue(element?.wdValue() as? String, element?.wdLabel()) ?? ""
let l = text.characters.count
var bb = "\u{8}"
var typeString = ""
for _ in 1...l {
typeString=typeString + bb
}
element?.typeText(typeString)
这样就可以清除了 谢谢

2457

@pliue clear的方法麻烦给xctestwd提个merge request

105楼 已删除
69ae3c

@xdf 刚才试了下 最新版的 只test xctestwduitests 只会安装一个应用了

3170
69ae3cpliue 回复

👍 我也同步下

69ae3c

@zhangzhao_lenovo 中文的还没回复 清除的 看下103楼 目前还发现xpath定位不是很准确

D754b7

@zhangzhao_lenovo 用真机跑可以得到截图和crash日志吗

3170
D754b7Only7 回复

可以的 xcode里点结束时有个日志路径 xxxxx/test/attachments/ 包含截图和crash

69ae3c

github上XCTestWD的管理员SamuelZhaoY 这哥们大家遇到么 有点无语呀

F8621b
69ae3cpliue 回复

你好,我是XCTestWD 的作,对于你提出的部分问题, 因为考虑到实际价值,所以做了bypaas.

69ae3c

@Samuel.ZhaoY 只是觉得 应该充分的沟通 这个github 评论模式不太习惯

F8621b
69ae3cpliue 回复

欢迎钉钉留言 Samuel.蕉庵 +65-97788734, 提交issue 建议提供多的信息, 关于一些想法可以给一些完整的建议,而不是只言片语. 对issue 处理及时,其实在作者的角度已经是对答问者最大的负责. 特别是同时提出4 - 5 个issue 的时候, 不妨先整理一下思绪😀

115楼 已删除
D754b7

@zhangzhao_lenovo

您好 我这边成功用carthage安装了swiftJSON.framework,但是swifter.framework却失败,查看发现git地址已经404了,不知道是该如何解决呢?

3170
D754b7Only7 回复

github "glock45/swifter" == 1.3.3 试试这个。

D754b7

成功了!感谢回复😍

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册