xcode XCTest Swift - 如何更快或更精确地滑动?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39280821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 09:11:54  来源:igfitidea点击:

XCTest Swift - How do I swipe faster or more precisely?

iosswiftxcodexctest

提问by Laser Hawk

I have tests in XCTest using Swift and I am trying to swipe through a feed until a condition is met. I am using the swipeUp(), but the problem with this is it acts like a human swipe and has this painful animation of slowing down when it lets go. It doesn't try the swipe again until the slowing-down-animation is complete. Additionally, that method takes no arguments. I would like to see if there is something like Calabash or shoot even Androids Espresso where there are properties to a swipe method like swipeUp(fast)or swipeUp(medium)or even swipeUp(x0,y200).

我在 XCTest 中使用 Swift 进行了测试,我正在尝试浏览提要,直到满足条件。我正在使用swipeUp(),但问题在于它就像人类滑动一样,并且在放手时会出现减速的痛苦动画。在减速动画完成之前,它不会再次尝试滑动。此外,该方法不接受任何参数。我想看看是否有像 Calabash 这样的东西,或者甚至可以拍摄 Androids Espresso,其中有像swipeUp(fast)orswipeUp(medium)或 even 之类的滑动方法的属性swipeUp(x0,y200)

Here is what I am trying to do in code:

这是我在代码中尝试执行的操作:

    func scrollDownUntilYouFindSomething() {
    while !findingSomehting.exists {
        app.swipeUp()
    }
}

Simple enough, but the swipeUp() in XCUIApplication is painfully slow. I want to be able to swipe with precision and even by coordinate. I tried to use the coordinate approach taken from Replicate pull to refresh in XCTest UI testing

很简单,但是 XCUIApplication 中的 swipeUp() 非常缓慢。我希望能够精确滑动,甚至通过坐标滑动。我尝试在 XCTest UI 测试中使用从复制拉取刷新的坐标方法

but its equally as slow when put into a loop.

但放入循环时同样慢。

回答by UglyBlueCat

I wrote an extension based on the excellent answer given by Bharathram C.

我根据 Bharathram C 给出的优秀答案写了一个扩展。

I find it to be a much gentler swipe than XCUIElement.swipeUp()

我发现它比 XCUIElement.swipeUp() 轻得多

//  XCUIElement+GentleSwipe.swift

import Foundation
import XCTest

extension XCUIElement
{
    enum direction : Int {
        case Up, Down, Left, Right
    }

    func gentleSwipe(_ direction : direction) {
        let half : CGFloat = 0.5
        let adjustment : CGFloat = 0.25
        let pressDuration : TimeInterval = 0.05

        let lessThanHalf = half - adjustment
        let moreThanHalf = half + adjustment

        let centre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: half))
        let aboveCentre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: lessThanHalf))
        let belowCentre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: moreThanHalf))
        let leftOfCentre = self.coordinate(withNormalizedOffset: CGVector(dx: lessThanHalf, dy: half))
        let rightOfCentre = self.coordinate(withNormalizedOffset: CGVector(dx: moreThanHalf, dy: half))

        switch direction {
        case .Up:
            centre.press(forDuration: pressDuration, thenDragTo: aboveCentre)
            break
        case .Down:
            centre.press(forDuration: pressDuration, thenDragTo: belowCentre)
            break
        case .Left:
            centre.press(forDuration: pressDuration, thenDragTo: leftOfCentre)
            break
        case .Right:
            centre.press(forDuration: pressDuration, thenDragTo: rightOfCentre)
            break
        }
    }
}

回答by Bharathram C

Yes, we can have a co-ordinate based swipe in Swift. We can create our own swipe action by using the pressForDuration(duration, thenDragToElement: XCElement). Please see an example below.

是的,我们可以在 Swift 中进行基于坐标的滑动。我们可以通过使用 pressForDuration(duration, thenDragToElement: XCElement) 创建我们自己的滑动动作。请看下面的例子。

For this we will need

为此,我们将需要

  1. Reference Element in the view.(Pick one in the section where the swiping action has to be performed, and it should not be a draggable element).
  2. A beginning co-ordinate with respect to the reference element.
  3. An end co-ordinate/XCUIElement with respect to the reference element.
  1. 视图中的参考元素。(在必须执行滑动操作的部分中选择一个,它不应是可拖动的元素)。
  2. 相对于参考元素的开始坐标。
  3. 相对于参考元素的结束坐标/XCUIElement。

Then we can have a function similar to below (in Swift 3)

然后我们可以有一个类似于下面的函数(在 Swift 3 中)

func customSwipe(refElement:XCUIElement,startdelxy:CGVector,enddeltaxy: CGVector){
      let swipeStartPoint = refElement.coordinate(withNormalizedOffset: startdelxy)
      let swipeEndPoint = refElement.coordinate(withNormalizedOffset: enddeltaxy)
      swipeStartPoint.press(forDuration: 0.1, thenDragTo: swipeEndPoint)

}

Here if startdelxyis (0.0,0.0) and enddeltaxyis (0.0,-ve), swipe will go upward from the refElement. If enddeltaxyis (0.0,+ve) swipe will go down.This is because our reference element will be the origin, X is +ve going right and Y is +ve going below our reference element. Start with smaller values of Y (say -0.75) and change as necessary. More the Difference, Longer the Swipe.

这里如果startdelxy是 (0.0,0.0) 并且enddeltaxy是 (0.0,-ve),滑动将从refElement向上。如果enddeltaxy是 (0.0,+ve) 滑动将向下。这是因为我们的参考元素将是原点,X 是 +ve 向右,Y 是 +ve 低于我们的参考元素。从较小的 Y 值(例如 -0.75)开始,并根据需要进行更改。差异越大,滑动时间越长。

The swipeStartPointand swipeEndPointcan be replaced with an element (if such exists in the view). Usually, for swipeEndPointwe can go for an element in the Nav Bar for a swipeUp action. Also, Changing the X can give us customSwipes in the left and right directions.

swipeStartPointswipeEndPoint可以用元件更换(如果这样的存在于图)。通常,对于swipeEndPoint,我们可以在导航栏中寻找一个元素来执行 swipeUp 操作。此外,更改 X 可以为我们提供左右方向的自定义滑动。

As for the Speed of swiping, I'm not aware of any API that can swipe faster/slower than the default rate.

至于滑动速度,我不知道有任何 API 可以比默认速率更快/更慢地滑动。

回答by Benzy

Updated the first answerfor Swift 4.

更新Swift 4的第一个答案

extension XCUIElement {
    enum Direction: Int {
        case up, down, left, right
    }

    func gentleSwipe(_ direction: Direction) {
        let half: CGFloat = 0.5
        let adjustment: CGFloat = 0.25
        let pressDuration: TimeInterval = 0.05

        let lessThanHalf = half - adjustment
        let moreThanHalf = half + adjustment

        let centre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: half))
        let aboveCentre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: lessThanHalf))
        let belowCentre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: moreThanHalf))
        let leftOfCentre = self.coordinate(withNormalizedOffset: CGVector(dx: lessThanHalf, dy: half))
        let rightOfCentre = self.coordinate(withNormalizedOffset: CGVector(dx: moreThanHalf, dy: half))

        switch direction {
        case .up:
            centre.press(forDuration: pressDuration, thenDragTo: aboveCentre)
        case .down:
            centre.press(forDuration: pressDuration, thenDragTo: belowCentre)
        case .left:
            centre.press(forDuration: pressDuration, thenDragTo: leftOfCentre)
        case .right:
            centre.press(forDuration: pressDuration, thenDragTo: rightOfCentre)
        }
    }
}

回答by N..

I tried to refactor gentleSwipe function to target element. Following refactor focus to reach targeted element. We can pass element in swipeUp function and it will call gentleSwipe that's will help us to reach targeted element. I hope it will help others as well.

我尝试将 GentleSwipe 函数重构为目标元素。遵循重构焦点以达到目标元素。我们可以在 swipeUp 函数中传递元素,它会调用 GentleSwipe 这将帮助我们到达目标元素。我希望它也能帮助其他人。

Here is code :

这是代码:

public func swipeUp(to element: XCUIElement) {
    while !(elementIsWithinWindow(element: element)) {
           XCUIApplication().gentleSwipe(.up)
    }
}

private func elementIsWithinWindow(element: XCUIElement) -> Bool{
    guard element.exists && element.isHittable else {return false}
    return true
}

enum direction : Int {
    case up, down, left, right
}

func gentleSwipe(_ direction : direction) {
    let half : CGFloat = 0.5
    let adjustment : CGFloat = 0.25
    let pressDuration : TimeInterval = 0.05

    let lessThanHalf = half - adjustment
    let moreThanHalf = half + adjustment

    let centre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: half))
    let aboveCentre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: lessThanHalf))
    let belowCentre = self.coordinate(withNormalizedOffset: CGVector(dx: half, dy: moreThanHalf))
    let leftOfCentre = self.coordinate(withNormalizedOffset: CGVector(dx: lessThanHalf, dy: half))
    let rightOfCentre = self.coordinate(withNormalizedOffset: CGVector(dx: moreThanHalf, dy: half))

    switch direction {
    case .up:
        centre.press(forDuration: pressDuration, thenDragTo: aboveCentre)
        break
    case .down:
        centre.press(forDuration: pressDuration, thenDragTo: belowCentre)
        break
    case .left:
        centre.press(forDuration: pressDuration, thenDragTo: leftOfCentre)
        break
    case .right:
        centre.press(forDuration: pressDuration, thenDragTo: rightOfCentre)
        break
    }
}

Call Tips

通话提示

app.swipeUp(to: "element")

app.swipeUp(到:“元素”)