I want to use UI testing for a game using SKSpriteKit
.
As my first tries did not work I wonder if it possible to use Xcode UI Testing with SpriteKit.
Even though the default Game Xcode Template creates the project based on a UIKit application, you can create a SwiftUI app and put your SpriteKit game inside it without any hustle thanks to the SpriteView view!
If you are making a new app, make sure you select the “Use UI Tests” checkbox when creating a new Xcode project. To add it in an existing project go to the build folder and on the bottom left you will see the plus button. Selecting that will give you a dropdown menu, where you can then select “UI Testing Bundle”.
Recording a UI TestFrom the debug bar, click the Record UI Test button. Xcode will launch the app and run it. You can interact with the element on-screen and perform a sequence of interactions for any UI test. Whenever you interact with an element, Xcode writes the corresponding code for it into your method.
SpriteKit is definitely not dead and still supported by Apple. However it has been overshadowed by other technologies from Apple such as AR, Metal, etc. Additionally, it's not portable to other platforms (unlike Unity).
The main idea is to create the accessibility material for elements that you want to UI test. That's mean:
List all accessible elements contained in the scene
Configure settings for each of these elements, especially frame
data.
This answer is for Swift 3 and is mainly based on Accessibility (Voice Over) with Sprite Kit
Let's say I want to make the SpriteKit button named tapMe
accessible.
Add an array of UIAccessibilityElement
to the Scene.
var accessibleElements: [UIAccessibilityElement] = []
I need to update two methods: didMove(to:)
and 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
.
And:
override func willMove(from view: SKView) {
accessibleElements.removeAll()
}
3 methods are involved: accessibilityElementCount()
, accessibilityElement(at index:)
and index(ofAccessibilityElement
. Please allow me to introduce an initAccessibility()
method I'll describe later.
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)!
}
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)
}
}
UIAccessibilityElement
for tapMe
frame
's origin is the top/left corner for UIKitUIAccessibilityElement
UIAccessibilityElement
to list of all accessible elements in scene.Now tapMe
is accessible from UI testing perspective.
Session 406, UI Testing in Xcode, WWDC 2015
eyes off eyes on — Voiceover accessibility in SpriteKit
How do I support VoiceOver in a SpriteKit game? | Apple Developer Forums
swift - Accessibility (Voice Over) with Sprite Kit - Stack Overflow
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With