I want to use UI testing for a game using SKSpriteKit
.
我想使用SKSpriteKit对游戏进行UI测试。
As my first tries did not work I wonder if it possible to use Xcode UI Testing with SpriteKit.
由于我的第一次尝试不起作用,我想知道是否可以使用SpriteKit进行Xcode UI测试。
3 个解决方案
#1
4
The main idea is to create the accessibility material for elements that you want to UI test. That's mean:
主要思想是为要进行UI测试的元素创建辅助功能材料。这意味着:
-
List all accessible elements contained in the scene
列出场景中包含的所有可访问元素
-
Configure settings for each of these elements, especially
frame
data.配置每个元素的设置,尤其是framedata。
Step by Step
This answer is for Swift 3 and is mainly based on Accessibility (Voice Over) with Sprite Kit
这个答案适用于Swift 3,主要基于Sprite Kit的辅助功能(Voice Over)
Let's say I want to make the SpriteKit button named tapMe
accessible.
假设我想让名为tapMe的SpriteKit按钮可访问。
List of accessible elements.
Add an array of UIAccessibilityElement
to the Scene.
将一个UIAccessibilityElement数组添加到Scene中。
var accessibleElements: [UIAccessibilityElement] = []
Scene's cycle life
I need to update two methods: didMove(to:)
and willMove(from:)
.
我需要更新两个方法:didMove(to :)和willMove(from :)。
override func didMove(to view: SKView) {
isAccessibilityElement = false
tapMe.isAccessibilityElement = true
}
As scene is the accessibility controller, documentation stated it must return False
to isAccessibilityElement
.
由于scene是辅助功能控制器,因此文档声明必须将False返回给isAccessibilityElement。
And:
override func willMove(from view: SKView) {
accessibleElements.removeAll()
}
Override UIAccessibilityContainer methods
3 methods are involved: accessibilityElementCount()
, accessibilityElement(at index:)
and index(ofAccessibilityElement
. Please allow me to introduce an initAccessibility()
method I'll describe later.
涉及3个方法:accessibilityElementCount(),accessibilityElement(在索引:)和索引(ofAccessibilityElement。请允许我介绍我稍后将描述的initAccessibility()方法。
override func accessibilityElementCount() -> Int {
initAccessibility()
return accessibleElements.count
}
override func accessibilityElement(at index: Int) -> Any? {
initAccessibility()
if (index < accessibleElements.count) {
return accessibleElements[index]
} else {
return nil
}
}
override func index(ofAccessibilityElement element: Any) -> Int {
initAccessibility()
return accessibleElements.index(of: element as! UIAccessibilityElement)!
}
Initialize accessibility for the Scene
func initAccessibility() {
if accessibleElements.count == 0 {
// 1.
let elementForTapMe = UIAccessibilityElement(accessibilityContainer: self.view!)
// 2.
var frameForTapMe = tapMe.frame
// From Scene to View
frameForTapMe.origin = (view?.convert(frameForTapMe.origin, from: self))!
// Don't forget origins are different for SpriteKit and UIKit:
// - SpriteKit is bottom/left
// - UIKit is top/left
// y
// ┌────┐ ▲
// │ │ │ x
// ◉────┘ └──▶
//
// x
// ◉────┐ ┌──▶
// │ │ │
// └────┘ y ▼
//
// Thus before the following conversion, origin value indicate the bottom/left edge of the frame.
// We then need to move it to top/left by retrieving the height of the frame.
//
frameForTapMe.origin.y = frameForTapMe.origin.y - frameForTapMe.size.height
// 3.
elementForTapMe.accessibilityLabel = "tap Me"
elementForTapMe.accessibilityFrame = frameForTapMe
elementForTapMe.accessibilityTraits = UIAccessibilityTraitButton
// 4.
accessibleElements.append(elementForTapMe)
}
}
- Create
UIAccessibilityElement
fortapMe
- Compute frame data on device's coordinates. Don't forget that
frame
's origin is the top/left corner for UIKit - Set data for
UIAccessibilityElement
- Add this
UIAccessibilityElement
to list of all accessible elements in scene.
为tapMe创建UIAccessibilityElement
计算设备坐标上的帧数据。不要忘记框架的原点是UIKit的左上角
设置UIAccessibilityElement的数据
将此UIAccessibilityElement添加到场景中所有可访问元素的列表中。
Now tapMe
is accessible from UI testing perspective.
现在可以从UI测试角度访问tapMe。
References
-
Session 406, UI Testing in Xcode, WWDC 2015
会议406,Xcode中的UI测试,WWDC 2015
-
eyes off eyes on — Voiceover accessibility in SpriteKit
睁大眼睛 - SpriteKit中的配音可访问性
-
How do I support VoiceOver in a SpriteKit game? | Apple Developer Forums
如何在SpriteKit游戏中支持VoiceOver? | Apple开发者论坛
-
swift - Accessibility (Voice Over) with Sprite Kit - Stack Overflow
swift - 使用Sprite Kit的辅助功能(Voice Over) - Stack Overflow
#2
3
According to Apple developer forum discussion, Integrate UITest with SpriteKit is not currently possible:
根据Apple开发人员论坛的讨论,目前无法使用SpriteKit集成UITest:
This is likely not currently possible, but it probably could be
这可能目前不可能,但可能是这样
Update 2017-02-19
According to comment by @ChrisLivdahl this may be achieved by using UIAccessibility — Session 406, UI Testing in Xcode, WWDC 2015.
根据@ChrisLivdahl的评论,这可以通过使用UIAccessibility - Session 406,Xcode中的UI测试,WWDC 2015来实现。
The idea is to make the element needed UI Testable.
想法是使元素需要UI Testable。
#3
1
I've implemented an example project based on your (@Domsware's) awesome answer, and I've confirmed this trick works well for both Xcode UI Testing Framework and KIF.
我已经基于您的(@ Domsware)非常棒的答案实现了一个示例项目,并且我已经确认这个技巧适用于Xcode UI Testing Framework和KIF。
Hope this example helps for anyone who is interested in this topic :)
希望这个例子对任何对这个主题感兴趣的人都有帮助:)
#1
4
The main idea is to create the accessibility material for elements that you want to UI test. That's mean:
主要思想是为要进行UI测试的元素创建辅助功能材料。这意味着:
-
List all accessible elements contained in the scene
列出场景中包含的所有可访问元素
-
Configure settings for each of these elements, especially
frame
data.配置每个元素的设置,尤其是framedata。
Step by Step
This answer is for Swift 3 and is mainly based on Accessibility (Voice Over) with Sprite Kit
这个答案适用于Swift 3,主要基于Sprite Kit的辅助功能(Voice Over)
Let's say I want to make the SpriteKit button named tapMe
accessible.
假设我想让名为tapMe的SpriteKit按钮可访问。
List of accessible elements.
Add an array of UIAccessibilityElement
to the Scene.
将一个UIAccessibilityElement数组添加到Scene中。
var accessibleElements: [UIAccessibilityElement] = []
Scene's cycle life
I need to update two methods: didMove(to:)
and willMove(from:)
.
我需要更新两个方法:didMove(to :)和willMove(from :)。
override func didMove(to view: SKView) {
isAccessibilityElement = false
tapMe.isAccessibilityElement = true
}
As scene is the accessibility controller, documentation stated it must return False
to isAccessibilityElement
.
由于scene是辅助功能控制器,因此文档声明必须将False返回给isAccessibilityElement。
And:
override func willMove(from view: SKView) {
accessibleElements.removeAll()
}
Override UIAccessibilityContainer methods
3 methods are involved: accessibilityElementCount()
, accessibilityElement(at index:)
and index(ofAccessibilityElement
. Please allow me to introduce an initAccessibility()
method I'll describe later.
涉及3个方法:accessibilityElementCount(),accessibilityElement(在索引:)和索引(ofAccessibilityElement。请允许我介绍我稍后将描述的initAccessibility()方法。
override func accessibilityElementCount() -> Int {
initAccessibility()
return accessibleElements.count
}
override func accessibilityElement(at index: Int) -> Any? {
initAccessibility()
if (index < accessibleElements.count) {
return accessibleElements[index]
} else {
return nil
}
}
override func index(ofAccessibilityElement element: Any) -> Int {
initAccessibility()
return accessibleElements.index(of: element as! UIAccessibilityElement)!
}
Initialize accessibility for the Scene
func initAccessibility() {
if accessibleElements.count == 0 {
// 1.
let elementForTapMe = UIAccessibilityElement(accessibilityContainer: self.view!)
// 2.
var frameForTapMe = tapMe.frame
// From Scene to View
frameForTapMe.origin = (view?.convert(frameForTapMe.origin, from: self))!
// Don't forget origins are different for SpriteKit and UIKit:
// - SpriteKit is bottom/left
// - UIKit is top/left
// y
// ┌────┐ ▲
// │ │ │ x
// ◉────┘ └──▶
//
// x
// ◉────┐ ┌──▶
// │ │ │
// └────┘ y ▼
//
// Thus before the following conversion, origin value indicate the bottom/left edge of the frame.
// We then need to move it to top/left by retrieving the height of the frame.
//
frameForTapMe.origin.y = frameForTapMe.origin.y - frameForTapMe.size.height
// 3.
elementForTapMe.accessibilityLabel = "tap Me"
elementForTapMe.accessibilityFrame = frameForTapMe
elementForTapMe.accessibilityTraits = UIAccessibilityTraitButton
// 4.
accessibleElements.append(elementForTapMe)
}
}
- Create
UIAccessibilityElement
fortapMe
- Compute frame data on device's coordinates. Don't forget that
frame
's origin is the top/left corner for UIKit - Set data for
UIAccessibilityElement
- Add this
UIAccessibilityElement
to list of all accessible elements in scene.
为tapMe创建UIAccessibilityElement
计算设备坐标上的帧数据。不要忘记框架的原点是UIKit的左上角
设置UIAccessibilityElement的数据
将此UIAccessibilityElement添加到场景中所有可访问元素的列表中。
Now tapMe
is accessible from UI testing perspective.
现在可以从UI测试角度访问tapMe。
References
-
Session 406, UI Testing in Xcode, WWDC 2015
会议406,Xcode中的UI测试,WWDC 2015
-
eyes off eyes on — Voiceover accessibility in SpriteKit
睁大眼睛 - SpriteKit中的配音可访问性
-
How do I support VoiceOver in a SpriteKit game? | Apple Developer Forums
如何在SpriteKit游戏中支持VoiceOver? | Apple开发者论坛
-
swift - Accessibility (Voice Over) with Sprite Kit - Stack Overflow
swift - 使用Sprite Kit的辅助功能(Voice Over) - Stack Overflow
#2
3
According to Apple developer forum discussion, Integrate UITest with SpriteKit is not currently possible:
根据Apple开发人员论坛的讨论,目前无法使用SpriteKit集成UITest:
This is likely not currently possible, but it probably could be
这可能目前不可能,但可能是这样
Update 2017-02-19
According to comment by @ChrisLivdahl this may be achieved by using UIAccessibility — Session 406, UI Testing in Xcode, WWDC 2015.
根据@ChrisLivdahl的评论,这可以通过使用UIAccessibility - Session 406,Xcode中的UI测试,WWDC 2015来实现。
The idea is to make the element needed UI Testable.
想法是使元素需要UI Testable。
#3
1
I've implemented an example project based on your (@Domsware's) awesome answer, and I've confirmed this trick works well for both Xcode UI Testing Framework and KIF.
我已经基于您的(@ Domsware)非常棒的答案实现了一个示例项目,并且我已经确认这个技巧适用于Xcode UI Testing Framework和KIF。
Hope this example helps for anyone who is interested in this topic :)
希望这个例子对任何对这个主题感兴趣的人都有帮助:)