Teste de IU do Xcode - Falha no teste de IU - Falha ao rolar para visível (por ação AX) ao tocar no campo Pesquisar botão "Cancelar"

85

Estou tentando descartar o campo de pesquisa tocando no botão 'Cancelar' na barra de pesquisa.

O caso de teste está falhando em encontrar o botão Cancelar. Estava funcionando bem no Xcode 7.0.1

Eu adicionei predicado para aguardar o botão aparecer. O caso de teste está falhando quando tocamos no botão "cancelar"

let button = app.buttons[“Cancel”]
let existsPredicate = NSPredicate(format: "exists == 1")

expectationForPredicate(existsPredicate, evaluatedWithObject: button, handler: nil)
waitForExpectationsWithTimeout(5, handler: nil)

button.tap() // Failing here

logs :

    t =     7.21s     Tap SearchField
t =     7.21s         Wait for app to idle
t =     7.29s         Find the SearchField
t =     7.29s             Snapshot accessibility hierarchy for com.test.mail
t =     7.49s             Find: Descendants matching type SearchField
t =     7.49s             Find: Element at index 0
t =     7.49s             Wait for app to idle
t =     7.55s         Synthesize event
t =     7.84s         Wait for app to idle
t =     8.97s     Type '[email protected]' into
t =     8.97s         Wait for app to idle
t =     9.03s         Find the "Search" SearchField
t =     9.03s             Snapshot accessibility hierarchy for com.test.mail
t =     9.35s             Find: Descendants matching type SearchField
t =     9.35s             Find: Element at index 0
t =     9.36s             Wait for app to idle
t =     9.42s         Synthesize event
t =    10.37s         Wait for app to idle
t =    10.44s     Check predicate `exists == 1` against object `"Cancel" Button`
t =    10.44s         Snapshot accessibility hierarchy for com.test.mail
t =    10.58s         Find: Descendants matching type Button
t =    10.58s         Find: Elements matching predicate '"Cancel" IN identifiers'
t =    10.58s     Tap "Cancel" Button
t =    10.58s         Wait for app to idle
t =    10.64s         Find the "Cancel" Button
t =    10.64s             Snapshot accessibility hierarchy for com.test.mail
t =    10.78s             Find: Descendants matching type Button
t =    10.78s             Find: Elements matching predicate '"Cancel" IN identifiers'
t =    10.79s             Wait for app to idle
t =    11.08s         Synthesize event
t =    11.13s             Scroll element to visible
t =    11.14s             Assertion Failure: UI Testing Failure - Failed to scroll to visible (by AX action) Button 0x7f7fcaebde40: traits: 8589934593, {{353.0, 26.0}, {53.0, 30.0}}, label: 'Cancel', error: Error -25204 performing AXAction 2003
Vinpai
fonte
@Joe Masilotti alguma ideia?
Vinpai,
É apenas uma verificação de integridade, mas o botão Cancelar está na tela ou precisa ser rolado até ele? Sei que ainda há problemas em que rolar para os elementos nem sempre funciona.
Joe Masilotti
@JoeMasilotti botão cancelar está na tela. O botão Cancelar é o botão padrão do sistema que faz parte do UISearchbar. Estava funcionando bem no Xcode 7.0.1 quando eu fiz [self.buttons [@ "Cancelar"] toquei];
Vinpai
1
@Vinpai o que acontece quando você adiciona um app.tables.cells.allElementsBoundByAccessibilityElement.countantes de tocar no botão? Só por curiosidade - às vezes isso me ajudou a "atualizar" a tela.
bolos88,
@Konnor, tentei com a API que você sugeriu, mas está falhando quando toco no botão Cancelar. Quando eu
consulto o

Respostas:

140

Eu acho que aqui o botão "Cancelar" retorna falsepara a hittablepropriedade, que está impedindo que ele toque.

Se você ver tap()na documentação diz

/*!
 * Sends a tap event to a hittable point computed for the element.
 */
- (void)tap;

Parece que as coisas estão quebradas com o XCode 7.1. Para me manter (e você também;)) desbloqueado contra esses problemas, escrevi uma extensão XCUIElementque permite tocar no elemento mesmo que ele não seja atingível. Seguir pode ajudá-lo.

/*Sends a tap event to a hittable/unhittable element.*/
extension XCUIElement {
    func forceTapElement() {
        if self.hittable {
            self.tap()
        }
        else {
            let coordinate: XCUICoordinate = self.coordinateWithNormalizedOffset(CGVectorMake(0.0, 0.0))
            coordinate.tap()
        }
    }
}

Agora você pode ligar como

button.forceTapElement()

Atualização - Para o swift 3, use o seguinte:

extension XCUIElement {
    func forceTapElement() {
        if self.isHittable {
            self.tap()
        }
        else {
            let coordinate: XCUICoordinate = self.coordinate(withNormalizedOffset: CGVector(dx:0.0, dy:0.0))
            coordinate.tap()
        }
    }
}
Sandy
fonte
Obrigado pela correção. Eu estava encontrando um problema semelhante com cell.tap()e isso corrigiu. Algo parece ter mudado no Xcode7.1 fazendo com que alguns elementos não sejam mais atingíveis
francisOpt
Eu tenho uma barra de navegação personalizada backButtonItem que não é 'atingível' no Xcode 7.1, e esta solução funciona para mimself.app.navigationBars["Nav Title"].staticTexts["Custom Back Btn Title"].forceTapElement()
Alex
Obrigado - funcionou para o meu mesmo problema.
Tache
7
No meu caso funcionou quando a torneira está no centro da vista. Altere o deslocamento para (0,5, 0,5). let coordinate: XCUICoordinate = self.coordinateWithNormalizedOffset(CGVectorMake(0.5, 0.5))
Graham Perks de
1
Ótimo trabalho. Eu estava quase começando a matar meu macbook antes de ver isso.
ChaosSpeeder
11

Para mim, a causa raiz era que os objetos que eu queria tocar

  • foram definidos como ocultos (e para trás)
  • foram removidos e reconectados

Em ambos os casos, a isAccessibilityElementpropriedade foi falseposteriormente. Definindo de volta para trueconsertá-lo.

cachorro
fonte
3
Esse era exatamente o meu problema. Estranhamente, começou a acontecer no iOS 11 (estava funcionando bem no iOS 10).
Ricardo Sanchez-Saez
4

Esta questão se classifica bem para as consultas do Google em torno do termo "Falha ao rolar para o botão visível (por ação AX)" . Dada a idade da pergunta, estava inclinado a pensar que esse não era mais um problema com a estrutura do XCUITest, como sugere a resposta aceita.

Achei que esse problema era devido ao fato de XCElementexistir, mas estar escondido atrás do teclado do software. O erro é emitido pela estrutura, uma vez que é incapaz de rolar uma exibição existente para ser tocada. No meu caso, o botão em questão às vezes ficava atrás do teclado do software .

Descobri que o teclado do software do Simulador iOS pode ser desativado em alguns casos (por exemplo: em sua máquina) e ativado em outros (por exemplo: em seu CI). No meu caso, desliguei o teclado do software em uma máquina e, por padrão, ele foi ativado em outras.

Solução: ignore o teclado antes de tentar tocar nos botões que podem estar atrás dele.

Descobri que tocar em algum lugar que dispensava explicitamente o teclado antes de tocar no botão resolveu meu problema em todos os ambientes.

Eu adicionei algumas ações para fazer o respondente atual resignFirstResponder. As visualizações por trás das minhas visualizações de texto forçarão o primeiro respondente a renunciar, então toco em algum lugar logo abaixo da última área de texto.

 /// The keyboard may be up, dismiss it by tapping just below the password field
let pointBelowPassword = passwordSecureTextField.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1))
pointBelowPassword.press(forDuration: 0.1)
Jessedc
fonte
2

Por favor, verifique a característica do elemento, eu estava enfrentando o mesmo problema com TableViewSectionHeader, eu estava tentando tocar, mas estava falhando em todos os pontos

insira a descrição da imagem aqui

Nagaraj
fonte
1

A solução alternativa de Sandy pareceu ajudar por um tempo, mas depois não mais - mudei assim:

func waitAndForceTap(timeout: UInt32 = 5000) {
    XCTAssert(waitForElement(timeout: timeout))
    coordinate(withNormalizedOffset: CGVector(dx:0.5, dy:0.5)).tap()
}

O ponto principal é que, como o problema é que a verificação isHittable lança uma exceção, eu não faço essa verificação e vou direto para as coordenadas depois que o elemento é encontrado.

Aistė Stikliūtė
fonte
0

No meu caso, foi um elemento de interface do usuário adicionado de forma programática cobrindo o botão.

PruitIgoe
fonte
0

Se você estiver usando o simulador AppCenter para executar os testes, certifique-se de que está executando os testes na mesma versão do dispositivo que o simulador local. Perdi 3 dias de trabalho por causa disso.

fdelam
fonte
0

No espírito das coisas que podem abranger seu elemento, coloquei o depurador RN parcialmente sobreposto no topo do meu ícone:

insira a descrição da imagem aqui

Jeroen Vannevel
fonte