Мне сложно понять, как правильно сделать пользовательский UIView доступным на iOS. В качестве примера можно привести пользовательский подкласс UIControl
, охватывающий подвиды UILabel
и UITextField
, который я хочу протестировать с помощью теста пользовательского интерфейса.
Просмотр иерархии:
→ UIControl
↪︎ UILabel
↪︎ UIView
Намеренное поведение:
1️⃣ Поведение по умолчанию
По умолчанию поведение не велико:
- Инспектор доступности проверяет два подпредставления как не связанные;
- Аудит инспектора доступности выдает предупреждение «область попадания слишком мала», так как он игнорирует целые
UIControl
, которые можно коснуться и уделит вниманиеUITextField
.
Но этот тестовый код работает нормально:
let emailField = app.textFields["Email"]
emailField.tap()
emailField.typeText("toto@tata.com")
2️⃣ Становится элементом доступности
Если UIControl
помечается как элемент доступности следующим образом,инспектор доступности покажет только 1 указатель для всего UIControl
, но тест пользовательского интерфейса завершится неудачей.
Вот код:
isAccessibilityElement = true
accessibilityLabel = innerLabel.text
accessibilityValue = innerTextField.text
accessibilityTraits = innerTextField.accessibilityTraits
И стек с ошибками теста, который, по-видимому,иметь элементное поддерево , ограниченное UIControl
(он же TextField
)
UI Test Activity:
Assertion Failure: SampleUITests.swift:21: Failed to synthesize event: Neither element nor any descendant has keyboard focus. Event dispatch snapshot: TextField, label: 'Email'
Element debug description:
Attributes: TextField, {{32.0, 229.0}, {350.0, 52.0}}, label: 'Email'
Element subtree:
→TextField, 0x600000925340, {{32.0, 229.0}, {350.0, 52.0}}, label: 'Email'
3️⃣ Упрощение информации о доступности
Вдохновлено Документация Apple покак упростить вашу информацию о доступности , я использовал следующий код:
var elements = [UIAccessibilityElement]()
let groupedElements = UIAccessibilityElement(accessibilityContainer: self)
groupedElements.accessibilityLabel = innerLabel.text
groupedElements.accessibilityTraits = innerTextField.accessibilityTraits
elements.append(groupedElements)
Что, похоже, ничего не делает: я вернулся к поведению по умолчанию.
Подводя итоги
Мне бы хотелось иметь структуру доступности из 2️⃣ и при этом иметь возможность выполнять тесты пользовательского интерфейса наиболее выразительным образом, то есть используя тот же код, что и 1️⃣, как я могу это сделать? Что я сделал не так в 3️⃣, что заставило его вести себя так же, как 1️⃣?
Правка
Как намекнул @Defragged, я попытался улучшитьСоответствие UIControl
UIResponder
, но это не очень помогло:
override var canBecomeFirstResponder: Bool {
return innerTextField.canBecomeFirstResponder
}
override func becomeFirstResponder() -> Bool {
return innerTextField.becomeFirstResponder()
}
override var isFirstResponder: Bool {
return innerTextField.isFirstResponder
}
Изучение журналов ошибок теста пользовательского интерфейса немного глубже, я прочитал это:
t = 9.65s Synthesize event
t = 9.68s Get number of matches for: Elements containing elements matching predicate 'hasKeyboardFocus == 1'
t = 9.72s Requesting snapshot of accessibility hierarchy for app with pid 24879
t = 9.74s Find: Descendants matching type TextField
t = 9.74s Find: Elements matching predicate '"Email" IN identifiers'
t = 9.74s Find: Elements containing elements matching predicate 'hasKeyboardFocus == 1'
Кажется, что XCUIElement
экземпляры имеют недокументированный атрибут hasKeyboardFocus
, который можно проверить с помощью отладчика, но я понятия не имею, как управлять ?♂️.