UI 테스트 실패 - 요소 또는 하위 요소 모두 보안에 중점을 두지 않음텍스트 필드
제 경우는 이렇습니다.
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("wrong_password") //here is an error
UI 테스트 실패 - 요소 또는 하위 요소에 키보드 포커스가 없습니다.요소:
뭐가 문제야?이것은 정상적으로 작동합니다.textFields
하지만 문제는 오직 에만 발생합니다.secureTextFields
해결 방법은?
이 문제로 인해 저는 엄청난 고통을 겪었지만, 저는 적절한 해결책을 찾을 수 있었습니다.에서 Simulator(시뮬레이터)를 합니다.I/O -> Keyboard -> Connect hardware keyboard
꺼짐.
최근에 우리는 수락된 답변에서 해결책을 지속적으로 만드는 해킹을 발견했습니다.설정을 과 같이 하십시오.I/O -> Keyboard -> Connect hardware keyboard
명령행에서 다음과 같이 적어야 합니다.
defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0
실행 중인 시뮬레이터에는 영향을 주지 않습니다. 이 설정을 적용하려면 시뮬레이터를 다시 시작하거나 새 시뮬레이터를 시작해야 합니다.
저는 저에게 딱 맞는 작은 확장자(Swift)를 작성했습니다.코드는 다음과 같습니다.
extension XCTestCase {
func tapElementAndWaitForKeyboardToAppear(element: XCUIElement) {
let keyboard = XCUIApplication().keyboards.element
while (true) {
element.tap()
if keyboard.exists {
break;
}
NSRunLoop.currentRunLoop().runUntilDate(NSDate(timeIntervalSinceNow: 0.5))
}
}
}
주요 아이디어는 키보드가 표시되기 전에 요소(텍스트 필드)를 계속 누르는 것입니다.
스타니슬라프의 생각은 옳습니다.
팀 환경에서는 자동으로 작동하는 것이 필요합니다.제 블로그에서 해결책을 생각해 냈습니다.
기본적으로 붙여넣기만 하면 됩니다.
UIPasteboard.generalPasteboard().string = "Their password"
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.pressForDuration(1.1)
app.menuItems["Paste"].tap()
의 또 요소로 입니다.view.isAccessibilityElement = true
이 경우 XCTest는 하위 보기에서 텍스트를 입력하는 핸들을 가져올 수 없으며 오류를 반환합니다.
UI 테스트 실패 - 요소 또는 하위 요소에 키보드 포커스가 없습니다.
포커스가 있는 요소가 없는 것이 아니라(UITextField에서 키보드가 위에 있고 커서가 깜박이는 것을 자주 볼 수 있듯이) 도달할 수 있는 요소가 포커스가 없는 것입니다.UI 검색 표시줄에 텍스트를 입력할 때 이 문제가 발생했습니다.검색 줄 자체가 텍스트 필드가 아니므로 내게 필요한 옵션 요소로 설정할 때 기본 UIT 텍스트 필드에 대한 액세스가 차단되었습니다.이 문제를 해결하기 위해,searchBar.accessibilityIdentifier = "My Identifier"
에 설정되었습니다.UISearchBar
지그만, 하그.isAccessibilityElement
로 설정되지 않았습니다.true
후 다음과 같은의 테스트 합니다.
app.otherElements["My Identifier"].tap()
app.otherElements["My Identifier"].typeText("sample text")
작동하다
그것은 저와 함께 여러 번 일어났습니다.시뮬레이터에서 키보드 하드웨어 및 OSX와 동일한 레이아웃을 비활성화해야 합니다.
하드웨어/키보드(모두 사용 안 함)
그런 다음 키보드 소프트웨어가 해제되지 않고 테스트에서 텍스트를 입력할 수 있습니다.
나의 경우에는 이것.Hardware -> Keyboard -> Connect Hardware Keyboard
-> 비활성화는 저에게 효과가 없었습니다.
하지만 내가 따라갔을 때
1)Hardware -> Keyboard -> Connect Hardware Keyboard
-> 앱을 활성화하고 실행
2)Hardware -> Keyboard -> Connect Hardware Keyboard
-> 비활성화.
그것은 나에게 효과가 있었다.
func pasteTextFieldText(app:XCUIApplication, element:XCUIElement, value:String, clearText:Bool) {
// Get the password into the pasteboard buffer
UIPasteboard.generalPasteboard().string = value
// Bring up the popup menu on the password field
element.tap()
if clearText {
element.buttons["Clear text"].tap()
}
element.doubleTap()
// Tap the Paste button to input the password
app.menuItems["Paste"].tap()
}
앱을 시작하고 다음과 같은 텍스트 필드에 데이터를 입력하는 사이에 절전 모드를 사용합니다.
sleep(2)
저 같은 경우에는 매번 이 오류가 계속 발생했는데 이 해결책만 도움이 되었습니다.
이것은 도움이 될 수도 있습니다: 저는 오류 앞에 "탭" 동작을 추가합니다; 그게 전부입니다:)
[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];
키보드 또는 키보드가 연결되지 않은 상태에서 원하는 대로 케이스를 기록합니다.하지만 테스트를 하기 전에 다음을 수행합니다.
테스트를 실행하는 동안 이 옵션(하드웨어 키보드 연결)을 선택 취소해야 합니다.
내게 맞는 제품:
extension XCUIElement {
func typeTextAlt(_ text: String) {
// Solution for `Neither element nor any descendant has keyboard focus.`
if !(self.value(forKey: "hasKeyboardFocus") as? Bool ?? false) {
XCUIDevice.shared.press(XCUIDevice.Button.home)
XCUIApplication().activate()
}
self.typeText(text)
}
}
[Bartwomiej Semańczyk의 의견이 나를 위해 문제를 해결했기 때문에 답변으로 다시 게시]
저는 시뮬레이터 메뉴바에서 시뮬레이터 > 콘텐츠 및 설정 재설정을 수행하여 이 작업을 시작해야 했습니다.
@AlexDenisov가 게시한 솔루션을 실행 및 테스트를 위한 사전 조치에 추가하여 이 문제를 해결할 수 있었습니다.
위의 답변은 시뮬레이터 UI가 전경에 있는 동안 UI 테스트를 실행할 때 해결되었습니다(시뮬레이터 창에서 변경 사항을 볼 수 있을 때).그러나 백그라운드에서 실행할 때는 작동하지 않았습니다(예를 들어, 레인이 실행하는 속도).
나는 가야만 했습니다.Simulator > Device > Erase All Content and Settings...
확실히 하자면, 시뮬레이터 설정에서 하드웨어 키보드를 수동으로 비활성화-활성화-비활성화했습니다.defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0
내용 및 설정을 지웠습니다.
텍스트 필드가 텍스트 필드로 구현되지 않거나 다른 UI 요소로 감싸져 쉽게 액세스할 수 없는 경우가 있습니다.다음은 해결 방법입니다.
//XCUIApplication().scrollViews.otherElements.staticTexts["Email"] the locator for the element
RegistrationScreenStep1of2.emailTextField.tap()
let keys = app.keys
keys["p"].tap() //type the keys that you need
//If you stored your data somewhere and need to access that string //you can cats your string to an array and then pass the index //number to key[]
let newUserEmail = Array(newPatient.email())
let password = Array(newPatient.password)
//When you cast your string to an array the elements of the array //are Character so you would need to cast them into string otherwise //Xcode will compain.
let keys = app.keys
keys[String(newUserEmail[0])].tap()
keys[String(newUserEmail[1])].tap()
keys[String(newUserEmail[2])].tap()
keys[String(newUserEmail[3])].tap()
keys[String(newUserEmail[4])].tap()
keys[String(newUserEmail[5])].tap()
다음은 UI 테스트에 실패하는 Swift 5.4, Swift UI 앱 시나리오의 내용입니다.
app.cells.firstMatch.tap()
// transition from list view to detail view for item
app.textFields
.matching(identifier: "balance_textedit")
.element.tap()
app.textFields
.matching(identifier: "balance_textedit")
.element.typeText("7620") // :FAIL:
테스트: 이벤트를 합성하지 못했습니다.요소나 하위 요소 모두 키보드 포커스를 가지고 있지 않습니다.
솔루션:다시 누르기
번째 깐잠.tap()
통과한 것으로 밝혀졌습니다.
app.cells.firstMatch.tap()
// transition from list view to detail view for item
app.textFields
.matching(identifier: "balance_textedit")
.element.tap()
app.textFields
.matching(identifier: "balance_textedit")
.element.tap()
app.textFields
.matching(identifier: "balance_textedit")
.element.typeText("7620") // :PASS:
하만지,.doubleTap()
그리고.tap(withNumberOfTaps: 2, numberOfTouches: 1)
여전히 실패할 것입니다.
솔루션:텍스트 필드 도착을 기다린 다음 탭
때때로 보기 전환은 TextEdit 도착을 명시적으로 기다려야 합니다.아래의 접근 방식은 대상 텍스트 편집 필드의 도착을 기다립니다.
XCTestCase.swift 확장자:
extension XCTestCase {
func awaitArrival(element: XCUIElement, timeout: TimeInterval) {
let predicate = NSPredicate(format: "exists == 1")
expectation(for: predicate, evaluatedWith: element)
waitForExpectations(timeout: timeout)
}
func awaitDeparture(element: XCUIElement, timeout: TimeInterval) {
let predicate = NSPredicate(format: "exists == 0")
expectation(for: predicate, evaluatedWith: element)
waitForExpectations(timeout: timeout)
}
}
사용 예:
app.cells.firstMatch.tap()
// transition from list view to detail view for item
awaitArrival(
element: app.textFields.matching(identifier: "balance_textedit").element,
timeout: 5)
app.textFields
.matching(identifier: "balance_textedit")
.element.tap()
app.textFields
.matching(identifier: "balance_textedit")
.element.typeText("7620") // :PASS:
솔션:waitForExistence
그런 다음 탭
을 합니다.waitForExistence(timeout:)
에서 제공하는 XCUIElement
.
app.cells.firstMatch.tap()
// transition from list view to detail view for item
app.textFields.matching(identifier: "balance_textedit")
.element.waitForExistence(timeout: 5)
app.textFields
.matching(identifier: "balance_textedit")
.element.tap()
app.textFields
.matching(identifier: "balance_textedit")
.element.typeText("7620") // :PASS:
첫 번째 줄은 단지 쿼리 정의일 뿐이며, 이것은 그것을 의미하지 않습니다.passwordSecureTextField
실제로 존재할 것입니다.
두 번째 줄은 쿼리를 동적으로 실행하고 쿼리를 UI 요소에 바인딩(재)합니다.중단점을 지정하고 요소가 하나만 있는지 확인해야 합니다.또는 다음과 같은 주장을 사용합니다.
XCTAssertFalse(passwordSecureTextField.exists);
그렇지 않으면 괜찮아 보입니다.tap
를 강제로 에 표시해야 합니다.typeText
그냥 작동해야 합니다.오류 로그를 통해 더 많은 정보를 얻을 수 있습니다.
망치지 마십시오. 문제가 발생한 이유는 자동 테스트 시간 시뮬레이터는 소프트웨어 키보드만 사용하는 반면 앱이 하드웨어 키보드를 연결하는 테스트 시간을 기록하고 있기 때문입니다. 따라서 이 문제를 해결하는 방법입니다.녹화 시간에 소프트웨어 키보드를 사용하면 됩니다.당신은 마법을 볼 수 있습니다.
설정할 때 동일한 오류가 발생했습니다.accessibilityIdentifier
정의 보기 값( 정의 보기 값UIStackView
를 포함하는UIControl
부감 이 대한 수 .이 경우 XCTest는 하위 요소에 대한 키보드 포커스를 가져올 수 없습니다.
우리의 해결책은 간단히 제거하는 것이었습니다.accessibilityIdentifier
우리의 부모의 관점에서 그리고 설정.accessibilityIdentifier
전용 속성을 통해 하위 보기에 사용할 수 있습니다.
또 다른 대답이지만, 우리에게 문제는 그 뷰가 제스처 인식기가 그 위에 있는 다른 뷰에 너무 가깝다는 것이었습니다.아래의 경우 최소 20픽셀 이상 떨어져 있어야 합니다.말 그대로 15개는 효과가 없었고 20개 이상은 효과가 있었습니다.이것은 이상한 일이지만, 일부 UITextView는 작동하고 있었고 일부는 작동하지 않았으며 모두 동일한 상위 및 동일한 다른 포지셔닝(및 변수 이름) 아래에 있었습니다.키보드를 켜거나 끄거나 무엇이든 아무런 차이가 없었습니다.내게 필요한 옵션에 필드가 표시되었습니다.우리는 컴퓨터를 다시 시작했습니다.클린 빌드를 했습니다.새로운 소스 체크아웃.
I/O에서 키보드를 켜거나 끌 필요가 없습니다.보안을 위해 .typeText를 사용하지 않음텍스트 필드, 그냥 사용
app.keys["p"].tap()
app.keys["a"].tap()
app.keys["s"].tap()
app.keys["s"].tap()
보너스 : 키보드 소리 클릭 :)
의 .파일을 하고 .plist 파일을 했습니다.ConnectHardwareKeyboard
선택한 시뮬레이터에 대해 속성이 false가 됩니다.제대로 들으신 대로, 전역 속성을 편집하는 대신 "장치 기본 설정" 사전에서 특별히 선택한 시뮬레이터의 속성을 변경합니다.
먼저 disable-hardware-keyboard라는 이름의 셸 스크립트를 만듭니다.다음과 같은 내용으로 sh."당신의 프로젝트/xyz" 내에 배치할 수 있습니다.UI 테스트/스크립트/":
echo "Script: Set ConnectHardwareKeyboard to false for given Simulator UDID"
if [[ $1 != *-*-*-*-* ]]; then
echo "Pass device udid as first argument."
exit 1
else
DEVICE_ID=$1
fi
DEVICE_PREFERENCES_VALUE='<dict><key>ConnectHardwareKeyboard</key><false/></dict>'
killall Simulator # kill restart the simulator to make the plist changes picked up
defaults write com.apple.iphonesimulator DevicePreferences -dict-add $DEVICE_ID $DEVICE_PREFERENCES_VALUE
open -a Simulator # IMPORTANT
이제 다음 단계에 따라 선택한 시뮬레이터의 udid를 인수로 전달하여 호출합니다.
- Xcode 체계 편집(또는 특정 체계가 있는 경우 UI 테스트)
- 이동: 테스트 > 사전 조치
- "+" 기호 > "새 스크립트 실행 작업"을 눌러 새 스크립트를 추가합니다.
- 중요:빌드 설정 제공 위치 드롭다운에서 UI 테스트 대상이 아닌 기본 앱 대상을 선택합니다.
- 이제 아래 텍스트 영역에 다음 스크립트를 추가합니다.
테스트 > 사전 조치 내 스크립트:
#!/bin/sh
# $PROJECT_DIR is path to your source project. This is provided when we select "Provide build settings from" to "AppTarget"
# $TARGET_DEVICE_IDENTIFIER is the UDID of the selected simulator
sh $PROJECT_DIR/xyzUITests/Scripts/disable-hardware-keyboard.sh $TARGET_DEVICE_IDENTIFIER
# In order to see output of above script, append following with it:
# | tee ~/Desktop/ui-test-scheme-prescript.txt
테스트 시간:
- 시뮬레이터 발사
- 하드웨어 키보드 활성화
- 키보드 상호 작용으로 UI 테스트를 실행합니다.시뮬레이터가 다시 시작되고 하드웨어 키보드가 비활성화됩니다.그리고 테스트의 키보드 상호작용은 잘 작동합니다.:)
긴 이야기: iOS 시뮬레이터의 하드웨어 키보드 입력이 오랫동안 고장난 것 같습니다.
중요한 것은-[UIApplicationSupport _accessibilityHardwareKeyboardActive]
방법적의 방법.com.apple.UIKit.axbundle
때때로 되돌아옴NO
비록 그것이 돌아올지라도.YES
(텍스트 입력 보기가 다음과 같은 경우)firstResponder
커서가 깜박거립니다. 이는 문자 그대로 하드웨어 키보드가 활성 상태임을 의미합니다.
이 코드를 앱의 아무 곳에나 넣어 iOS 시뮬레이터가 소프트웨어 키보드가 비활성화되면 하드웨어 키보드가 활성화된 것으로 믿게 합니다.
#if TARGET_OS_SIMULATOR
__attribute__((constructor))
static void Fix_UIApplicationAccessibility__accessibilityHardwareKeyboardActive(void) {
{
static id observer = nil;
observer = [[NSNotificationCenter defaultCenter] addObserverForName:NSBundleDidLoadNotification
object:nil
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
NSBundle *bundle = note.object;
if ([bundle.bundleIdentifier isEqualToString:@"com.apple.UIKit.axbundle"]) {
Class cls = objc_lookUpClass("UIApplicationAccessibility");
SEL sel = sel_getUid("_accessibilityHardwareKeyboardActive");
Method m = class_getInstanceMethod(cls, sel);
method_setImplementation(m, imp_implementationWithBlock(^BOOL(UIApplication *app) {
return ![[app valueForKey:@"_accessibilitySoftwareKeyboardActive"] boolValue];
}));
}
}];
}
}
#endif
emailTextField.tap() // add this line before typeText
emailTextField.typeText("your text")
저의 문제는 테드의 문제와 같았습니다.실제로 로그인 필드 후에 암호 필드가 탭되고 하드웨어 KB가 켜지면 소프트웨어 키보드는 두 번째 필드 탭에서 자동으로 해제되며 UI 테스트에만 국한되지 않습니다.
AppleScript를 잠시 만지작거리다가 다음과 같이 생각해냈습니다(개선은 환영합니다).
tell application "Simulator"
activate
tell application "System Events"
try
tell process "Simulator"
tell menu bar 1
tell menu bar item "Hardware"
tell menu "Hardware"
tell menu item "Keyboard"
tell menu "Keyboard"
set menuItem to menu item "Connect Hardware Keyboard"
tell menu item "Connect Hardware Keyboard"
set checkboxStatus to value of attribute "AXMenuItemMarkChar" of menuItem
if checkboxStatus is equal to "✓" then
click
end if
end tell
end tell
end tell
end tell
end tell
end tell
end tell
on error
tell application "System Preferences"
activate
set securityPane to pane id "com.apple.preference.security"
tell securityPane to reveal anchor "Privacy_Accessibility"
display dialog "Xcode needs Universal access to disable hardware keyboard during tests(otherwise tests may fail because of focus issues)"
end tell
end try
end tell
end tell
위의 코드로 스크립트 파일을 만들어 필요한 대상에 추가합니다(아마 UI 테스트 대상만 해당). 개발 중에 HW 키보드를 다시 활성화하기 위해 개발 대상에 유사한 스크립트를 추가할 수 있습니다.당신은 야합해다를 .Run Script
합니다.osascript Path/To/Script/script_name.applescript
보안 텍스트 필드에 동일한 문제가 있습니다.내 시뮬레이터의 하드웨어 연결 옵션은 에 있었지만 여전히 문제가 발생했습니다.마지막으로, 이것은 저에게 효과가 있었습니다(Swift 3).
let enterPasswordSecureTextField = app.secureTextFields["Enter Password"]
enterPasswordSecureTextField.tap()
enterPasswordSecureTextField.typeText("12345678")
이 문제를 해결한 것은 1초 수면을 추가한 것입니다.
let textField = app.textFields["identifier"]
textField.tap()
sleep(1)
textField.typeText(text)
언급URL : https://stackoverflow.com/questions/32184837/ui-testing-failure-neither-element-nor-any-descendant-has-keyboard-focus-on-se
'programing' 카테고리의 다른 글
NodeJS에는 글로벌 모듈/패키지가 필요합니다. (0) | 2023.05.24 |
---|---|
Postgre에서 중복 레코드를 찾는 방법SQL (0) | 2023.05.24 |
Project-Swift.h를 Object-C 클래스로 가져오는 중...파일을 찾을 수 없음 (0) | 2023.05.24 |
Git에서 HEAD^와 HEAD~의 차이점은 무엇입니까? (0) | 2023.05.24 |
스토리보드에서 간단한 둥근 단추를 만드는 방법은 무엇입니까? (0) | 2023.05.24 |