Friday 2 March 2018

Waitforexpectationswithtimeout handler


Waitforexpectationswithtimeout handler
Obter através da App Store Leia esta publicação em nosso aplicativo!
XCTestCase waitForExpectationsWithTimeout: manipulador: jogando EXC_BAD_ACCESS quando a expectativa não é cumprida.
Estou testando uma chamada assíncrona usando XCTestExpectation.
O código a seguir funciona (o teste é bem-sucedido) quando o CompleteHandler é executado antes do tempo limite de 1 segundo dado.
No entanto, se o completeHandler não for chamado e, portanto, a expectativa não cumprida, em vez de obter uma falha de teste ao chamar waitForExpectationsWithTimeout, recebo um EXC_BAD_ACCESS, o que não é muito útil, pois isso impossibilita a exibição de todos os resultados do teste de teste.
Como posso evitar isso e obter uma falha de teste normal?
Parece que o que está causando o EXC_BAD_ACCESS está passando uma descrição nula ao criar a expectativa.
Passar qualquer string para esta chamada faz com que funcione e obtemos a falha de teste esperada quando a expectativa não for cumprida.

OHHTTPSs e testes assíncronos.
Clone este wiki localmente.
Como OHHTTPStubs é uma biblioteca geralmente usada em testes unitários que invocam solicitações de rede, esses testes geralmente são assíncronos. Isso significa que as solicitações de rede geralmente são enviadas de forma assíncrona, em um segmento separado ou fila diferente do segmento usado para executar a caixa de teste.
Como conseqüência, você terá que garantir que seus Testes de Unidade esperem que os pedidos terminem (e sua resposta chegou) antes de realizar as afirmações em seus casos de teste, pois, de outra forma, o seu código que faz as afirmações será executado antes que o pedido tenha tido tempo para obter sua resposta.
Por exemplo, isso não funcionará, porque sendAsynchronousRequest: queue: completionHandler: retornará imediatamente (desencadeando a solicitação de rede em segundo plano) e, portanto, o método testFoo chegará ao fim antes que o bloco completeHandler tenha tido tempo para ser chamado.
Portanto, sua estrutura de teste verá que o teste não desencadeou nenhuma falha de afirmação e marcará o teste como bem sucedido, mesmo se o bloco finalHandler for chamado mais tarde e acionar uma falha de afirmação (tardia) porque os dados são nulos, mas também seria atrasado.
Com o Xcode 6, o XCTest agora tem um novo recurso, chamado XCTestExpectation, apenas para fazer isso e lidar com testes em código assíncrono. Mattt fala sobre isso aqui em um dos artigos da grande NSHipster.
A idéia por trás disso é:
Crie uma XCTestExpectation usando o método expectationWithDescription:, dando-lhe uma descrição personalizada agradável Chamando o waitForExpectationsWithTimeout: manipulador: método quando você deseja aguardar suas chamadas assíncronas para terminar. Na sua conclusão, o operador ou qualquer método que sua operação assíncrona mande quando terminar, o objeto XCTestExpectation criado anteriormente para marcá-lo como ... cumprido.
Então, como seu nome indica, waitForExpectationsWithTimeout: manipulador: aguardará que todas as expectativas previamente declaradas sejam cumpridas ou para o tempo limite a ser alcançado e ligue para o bloco passado para o manipulador: parâmetro (se for fornecido). Também falhará automaticamente se houveram algumas expectativas que não foram cumpridas quando o tempo limite foi atingido.
Para terminar este artigo, um erro comum que você pode ver se você [OHHTTPStubs removeAllStubs] no final de seus testes de unidade (por exemplo, no método tearDown), mas falhou em aguardar que o teste assíncrono tenha uma resposta antes de deixar o caso de teste fim. Nesse caso, você pode encontrar o problema aqui descrito. Esteja ciente de que, ao ter este erro, provavelmente significa que você esqueceu de aguardar a conclusão das operações assíncronas!
&cópia de; 2018 GitHub, Inc. Termos Privacidade Segurança Status Ajuda.
Você não pode executar essa ação neste momento.
Você fez login com outra guia ou janela. Recarregue para atualizar sua sessão. Você se separou em outra guia ou janela. Recarregue para atualizar sua sessão.

Waitforexpectationswithtimeout handler
Obter através da App Store Leia esta publicação em nosso aplicativo!
XCTestCase # waitFalseExpectationUntilTimeout implementação.
Estou trabalhando em um projeto iOS e eu estou no comando de testar a maioria das partes dele. À medida que eu escrevo alguns testes, muitas vezes eu tenho a necessidade de aguardar um método assíncrono para finalizar e, em seguida, teste que algo não aconteceu.
Por exemplo, tente iniciar sessão com um nome de usuário e senha inválidos, aguarde até que as comunicações de rede sejam finalizadas e, em seguida, teste que o usuário não conseguiu fazer o login.
Swift tem alguns métodos astutos para testar esse tipo de coisas; aqueles que eu uso mais são expectationForPredicate e waitForExpectationsWithTimeout. Esses métodos são bons para testar que algo aconteceu depois que o método assíncrono termina. No entanto, para testar que algo não aconteceu (o que eu quero), não parece haver nada projetado especificamente para isso.
Não consigo usar predicados, porque isso fará com que o teste expire cedo. Eu não consigo modificar o código que está sendo testado porque é um retorno de retorno do ciclo de vida do aplicativo e nós testadores geralmente não modificamos nenhum código, nós apenas testamos.
É por isso que eu projetei esse método.
A principal coisa que a função faz é agendar um cronômetro e atender a todas as expectativas logo antes do período de espera. O método TimeTimeout expira. Essa é a melhor maneira de lidar com essa situação? O que posso melhorar com este método (além de comentar)? Quaisquer problemas de concorrência que eu deveria estar preocupado?
Para adicionar algum contexto, waitForExpectationsWithTimeout fará com que o teste falhe se não forem cumpridas as expectativas antes do tempo limite, e é por isso que eu tinha que cumprir todas as expectativas logo antes de esse tempo limite ocorrer.
Esta é uma solução extremamente complicada para um problema relativamente simples.
O método waitForExpectationsWithTimeout deve ser efetivamente usado somente para garantir que uma expectativa assíncrona particular tenha sido cumprida.
Então, no caso em que estamos testando se o usuário foi ou não logado com sucesso, seria tentador escrever algo ao longo das linhas de:
Mas, problemática, esse teste pode falhar por dois motivos:
O usuário não foi logado com sucesso. A expectativa não foi cumprida no prazo.
Se o teste falhar, não podemos ter certeza se ele teria passado um limite de tempo mais longo ou se ele retornou muito rápido, mas não foi bem-sucedido.
Então, precisamos modificar nosso teste para se parecer mais com isso:
Agora, o teste determina se o código assíncrono foi ou não executado e, em caso afirmativo, verificamos se o login foi ou não um sucesso (ou o que a variável de sucesso representa aqui).
Agora, você está procurando o caso oposto. Você quer saber se o usuário iniciou ou não o logon, mas se o usuário foi impedido ou não de fazer logon. E é tão simples como inverter um XCTAssertTrue para um XCTAssertFalse.
Importante, esse padrão não requer nenhum código complicado (que, naturalmente, devemos escrever testes em torno de nós mesmos). Nossos testes estão usando coisas puramente fora da caixa de teste Xcode - exatamente o que qualquer um que olhe nossa base de código esperaria ver. É muito direto o que está acontecendo aqui.
E podemos distinguir se a chamada assíncrona já aconteceu ou se aconteceu, mas obtivemos um resultado ruim. Há uma grande diferença aqui entre um teste falhando porque o código assíncrono não foi executado antes do nosso tempo e ele correu, mas deu um resultado incorreto. Nós precisamos distinguir claramente entre esses resultados e, assim, não exige escrever nenhum código complicado.
Uma nota importante aqui, certifique-se de que cumprir a expectativa é a última coisa que você faz nas devoluções de chamada assíncronas, ou você pode configurar uma condição de corrida.
E, finalmente, seus testes certamente devem ser muito mais robustos do que isso. Em última análise, devemos testar com respostas de rede simuladas e devemos saber, para cada teste, exatamente qual resposta de rede obteremos. Devemos testar que, qualquer que seja o código que esteja fazendo, o login retorna as informações corretas para nós. Há uma diferença entre o servidor permitindo que o usuário faça logon com sucesso e negue o usuário com credenciais inválidas. Há também uma diferença entre credenciais inválidas e obter qualquer número de vários erros de servidor (mais comumente, erros no intervalo 5xx). Obter um 503 e obter uma resposta de credencial inválida está longe da mesma coisa, e seus testes devem validar você está recebendo o que você espera obter.
Então, basicamente, acabei de lhe dizer que eliminasse completamente todo o código que você escreveu. E vou ficar de acordo com isso. Não há nenhum motivo para o código que você escreveu para existir. Mas, ainda podemos falar sobre alguns dos problemas que seu código existente possui.
Esse nome de função tem um nome estranho: waitFalseExpectationsUntilTimeout. É difícil para mim contar pelo nome sozinho o que esperar que esse método faça. Parece semelhante ao método waitForExpectationsWithTimeout (tempo limite: NSTimeInterval, manipulador: XCWaitCompletionHandler?), Mas tem essa série de expectativas estranhas que eu deveria passar. O nome precisa ser melhor. Algo como AssertUnfulFilledExpectationsWithTimeout.
Mesmo com o melhor nome, estamos aqui em problemas extraordinários. Tanto quanto posso ver, não existe um meio público de verificar se uma expectativa já foi ou não cumprida anteriormente. Seu código realmente não faz nada além do cumprimento de todas as expectativas no último momento antes do teste ser concluído. Não assegura que não foram cumpridas anteriormente.
Esta variável merece um nome melhor, e essa lógica quer merecer um comentário ou deve ser completamente eliminada. Eu optaria por eliminá-lo completamente e atirar uma exceção se o usuário tiver passado um valor inferior a 0,5. E, finalmente, essa lógica é, em última análise, problemática, porque você pode acabar com tempo negativo (se o tempo limite for inferior a 0,5).
Você provavelmente deve optar por alguma lógica que se parece mais com isso:
Finalmente, existem várias questões com a classe aninhada:
Primeiro, não precisamos marcar isso como uma função @objc. Podemos, em vez disso, marcar como dinâmico.
Em segundo lugar, somos forjados, mas não somos Jedi. Isso não passaria o meu conjunto pessoal de regras de swiftlint, onde force-casting é considerado um erro e se recusa a compilar.
Em terceiro lugar, expc é um nome de variável sem sentido, e não há valor real para abreviar aqui.
Em quarto lugar, você cumpriu com erros ortográficos, embora tenha sido escrito corretamente várias outras vezes neste contexto em virtude de nomes de métodos de preenchimento automático.
Em quinto lugar, por que não adicionamos apenas um método à extensão para lidar com isso em vez de complicar com uma classe aninhada com um nome estranho?
Então, essa é uma versão significativamente limpa e segura do seu código. mas, novamente, não afirmaram que essas expectativas não foram cumpridas antes de você as cumprir (tanto quanto eu sei que é impossível). E, finalmente, é um monte de código para implementar, testar, manter e verificar se funciona. e isso é especialmente assim, quando comparamos isso com a simples expectativa + asserção combo que esbocei no topo desta resposta.
Eu queria adicionar um adendo no caso de o problema ser que existe um determinado bloco de código que só é executado no caso de um login bem-sucedido. Se este é o cenário, existem apenas duas possibilidades.
A primeira é que existem blocos separados de sucesso e falha. Algo nesse sentido:
Neste caso, a essência é aproximadamente a mesma que o que esbocei no topo. Nós queremos cumprir a expectativa em ambos os blocos, mas no bloco de sucesso, vamos apenas adicionar um XCTFail ("Usuário foi autorizado para fazer login") para que ainda aguardemos esse bloco (ou o bloco de falha) para executar, mas, se for esse caminho, falhamos pelo motivo específico de que o ramo errado foi inserido (em vez de simplesmente seguir o caminho certo, mas não levá-lo rapidamente).
O outro caso é que existe apenas um retorno de chamada para o caminho de sucesso:
Se ESTE é o design, não tenho a menor idéia de como seu aplicativo consegue dar qualquer comentário ao usuário, de modo que algo deu errado durante o processo de login. Eu sei que você não pode modificar o código, mas você precisa estar dizendo às pessoas que podem precisar para solucionar esse problema.

OHHTTPStubs 3.1.9.
Adicione a Dash.
Adicione ao Xcode.
& # 9679; Olivier Halligon Versions & # x25BC; 3.1.9 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 2.4.0 2.3.1 2.3.0 2.2.1 2.2. 1-RC 2.2.0-RC 2.1.0-rc.1 2.1.0-RC 2.0.0 1.2.2 1.2.1 1.2.0 1.1.2 1.1.1 1.1.0 1.0.1 Documentado 52% Licença MIT.
Índice.
Referência da classe XCTestCaseAsync.
Métodos de instância.
__file: line: expectationWithDescription:
__file: line: waitForExpectationsWithTimeout: manipulador:
expectationWithDescription:
Discussão.
Descrição @param Esta seqüência de caracteres será exibida no registro de teste para ajudar a diagnosticar falhas.
@discussão Cria e retorna uma expectativa associada ao caso de teste.
Declarado em
waitForExpectationsWithTimeout: manipulador:
Discussão.
@param timeout A quantidade de tempo dentro do qual todas as expectativas devem ser cumpridas.
@param handlerOrNil Se fornecido, o manipulador será invocado tanto no tempo limite quanto no cumprimento de todas as expectativas. O tempo limite é sempre tratado como uma falha de teste.
@discussion - waitForExpectationsWithTimeout: manipulador: cria um ponto de sincronização no fluxo de um teste. Somente um - waitForExpectationsWithTimeout: manipulador: pode estar ativo em qualquer momento, mas múltiplas seqüências discretas de espera podem ser encadeadas.
-waitForExpectationsWithTimeout: manipulador: executa o ciclo de execução ao manipular eventos até que todas as expectativas sejam cumpridas ou o tempo limite seja atingido. Os clientes não devem manipular o loop de execução ao usar esta API.
Declarado em
&cópia de; 2018 Olivier Halligon. Todos os direitos reservados aos autores originais. (Última atualização: 2018-12-16)

Teste assíncrono com Xcode 6.
Em 2018, a Apple enviou uma plataforma de teste renovada no Xcode chamada XCTest, e houve muita alegria. A estrutura antiga não tinha sido atualizada há anos, e várias ferramentas e frameworks de teste de terceiros surgiram para fornecer novos recursos e recursos. Foi bom ver as ferramentas incorporadas recebendo algum amor novamente, e este ano, a Apple está enviando alguns recursos com o Xcode 6 que faltavam na atualização do ano passado. Um que particularmente me agrada ver é o suporte para testes assíncronos.
Se tivermos um teste que tenha que iniciar uma tarefa assíncrona, seja executado em outro tópico ou no runloop do thread principal, como podemos testá-lo?
Considere uma solicitação na web. Poderíamos iniciar uma solicitação na web e passar em um bloco de conclusão, depois fazer as nossas afirmações de teste, seja no manipulador de conclusão ou não. No entanto, como o pedido na Web ainda não foi feito, muito menos uma resposta recebida nem o nosso bloqueio de conclusão foi chamado, nosso método de teste vai sair antes que as afirmações sejam testadas.
Vamos ver um teste para uma classe que faz o download de páginas da web. Normalmente, não queremos fazer pedidos reais na web em testes. Em vez disso, nós superamos os pedidos usando alguma ferramenta (eu sou parcial para OHHTTPStubs). Mas para os propósitos desses exemplos, iremos quebrar algumas regras e fazer pedidos reais da web.
Podemos dar à classe em teste um URL e bloco de manipulação de conclusão, e irá baixar a página e chamar o bloco, passando por uma seqüência de caracteres contendo a página da web ou uma string vazia se ocorrer uma falha. Não é uma ótima API, mas, novamente, estamos quebrando algumas regras. No entanto, o código de teste abaixo nunca falhará. O método de teste retornará sem dar a conclusão do bloqueio de Handler uma chance de ser chamado.
Antes da versão do XCódigo 6 da XCTest, apenas usando o que vem na lata com Xcode, poderíamos sentar e girar em um ciclo de tempo que chama o loop de execução do thread principal até a resposta chegar ou algum período de tempo limite tenha decorrido. Aqui está o código de teste de trabalho, o antigo caminho.
O loop while roda o loop de execução do thread principal por 10 milissegundos de cada vez até a resposta chegar, ou até 5 segundos decorrer sem que ele tenha chegado. Isso é útil. Não é terrível. Não é o fim do mundo do desenvolvimento de software ", mas não é ótimo.
Agora, é uma maneira melhor.
Altas expectativas.
Com Xcode 6, a Apple adicionou expectativas de teste ao framework XCTest na forma da classe XCTestExpectation. Quando criamos uma expectativa de teste, a estrutura de teste espera que ela seja cumprida em algum momento no futuro. Nosso código de teste cumpre a expectativa no bloco de conclusão com uma chamada para o método XCTestExpectation. Isso toma o lugar de definir uma bandeira como responseHasArrived no exemplo anterior. Em seguida, contamos que o framework de teste espera (com um tempo limite) para que suas expectativas sejam cumpridas através do método XCTestCase waitForExpectationsWithTimeout: handler:. Se o manipulador de conclusão for executado dentro do tempo limite e as chamadas forem cumpridas, todas as expectativas do teste serão cumpridas. Caso contrário, o teste irá viver uma existência triste, solitária, não cumprida, até que se torne fora do escopo. E vivendo uma existência triste, solitária e insatisfeita, quero dizer que a expectativa falha no teste após o tempo limite.
A expectativa falhada não deveria se sentir tão abatida. Lembre-se de que um resultado falido não é o sinal de um teste ruim; um resultado indeterminado é. Essa expectativa pode sentir orgulho, pois declara falha.
Aqui é um exemplo usando XCTestExpectation:
Crie a expectativa com uma descrição para tornar os resultados mais legíveis. No bloco de conclusão, chame [expectativa preenchida] para dizer o teste que esta expectativa, de fato, foi cumprida. Então, saia no waitForExpectationsWithTimeout: manipulador: até que a solicitação seja enviada, a resposta chega e o nosso manipulador de conclusão é chamado ou o tempo limite ocorre.
Isso é bom, objetivo-C, mas também podemos fazê-lo na nova e brilhante linguagem swift da Apple.
E isso é isso. É uma classe fácil de usar para testar o código assíncrono.
Não podemos obter informações suficientes sobre iOS 8 e Swift? Junte-se a nós para o início do iOS com Swift e Advanced iOS bootcamps.
Cursos iOS Big Nerd Ranch.
Interessado em aprender mais sobre nossos cursos básicos e avançados de iOS?
Aprenda com os especialistas em um Bootcamp Big Nerd Ranch!
Big Nerd Ranch Screencasts.
Interessado em nivelar suas habilidades de codificação dos mesmos autores do Big Nerd Ranch Guide? Assine a The Frontier hoje!
Posts Relacionados:
Charles Brian Quinn.
Comentários recentes.
Desenvolvimento de aplicativos.
Treinamento em equipe.
Empresa.
Direitos autorais e cópia; 1998 - 2018 Big Nerd Ranch, LLC. Todos os direitos reservados. | Política de Privacidade.

No comments:

Post a Comment