Swift espera expectativas anteriores com o manipulador de tempo
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.
Swift espera expectativas anteriores com o manipulador de tempo
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.
mokacoding.
Testando callbacks em Swift com XCTest.
Esta publicação será a primeira de uma série em Testes Práticos em Swift. Planejo que as postagens cubram um único tópico e sejam focadas na implementação do código. O plano é liberar pelo menos uma publicação por semana, e eu já tenho 5 tópicos sobre os quais eu gostaria de escrever. O feedback é muito apreciado.
Como você testa o código assíncrono que chama um retorno de chamada?
Diga que você tenha uma classe que execute uma operação assíncrona e executa um fechamento de retorno de encerramento passado como um parâmetro de método.
Você já pode ter experimentado que escrever testes de código como doSomethingAsync da maneira tradicional resultará em comportamentos inesperados e falsos positivos.
A razão pela qual isso acontece é porque, por padrão, o XCTest é síncrono, como a maioria do código do aplicativo que geralmente escrevemos, enquanto o que você está tentando testar é assíncrono. Isso significa que a execução dos testes vai para a próxima linha de código logo após o método assíncrono ser chamado e o teste completo termina antes do encerramento do retorno de chamada ser executado.
O framework XCTest fornece uma API útil para testar o comportamento do código assíncrono: XCTestExpectation.
Vamos dar uma olhada em como testar doSomethingAsync usando XCTestExpectation. Você também pode acompanhar o projeto de exemplo para esta publicação.
Como você pode ver, há três etapas no processo.
Defina uma expectativa com uma descrição significativa. Continue com as fases de configuração e exercício do teste, chamando o método assíncrono e cumprindo a expectativa no final do fechamento de retorno de chamada. Faça com que o corredor de teste aguarde que a expectativa seja cumprida, para que as operações assíncronas possam ser concluídas e as afirmações verificadas.
É importante fornecer uma descrição significativa porque essa descrição é relatada na mensagem de falha de uma expectativa não cumprida:
Quando o teste com mensagens de falha descritiva é muito importante para tornar seu futuro e o resto da equipe identificar o motivo de falha o mais rápido possível.
Espero que você tenha achado esta publicação útil e agradeceria muito os comentários sobre o formato nos comentários abaixo ou me enviando um ping no Twitter @mokagio.
Se você precisar de ajuda com seus testes assíncronos, não hesite em entrar em contato, eu ficaria feliz em ajudar.
Fique atento ao próximo artigo em que veremos como testar chamadas assíncronas de objetos delegados. Se você não quiser perder, certifique-se de se inscrever no boletim informativo.
Deixe a base do código melhor do que você encontrou.
mokacoding.
Oi, Giovanni Lodi e este é o meu blog. Eu escrevo aqui pelo menos uma vez por mês, em testes de software, produtividade e desenvolvimento de iOS.
aguarde Expectativas com tempo limite: manipulador:
Espera até que todas as expectativas sejam cumpridas ou o tempo limite seja alcançado.
Declaração.
Parâmetros.
A quantidade de tempo dentro do qual todas as expectativas devem ser cumpridas.
Um bloqueio opcional XCWait Completion Handler para invocar quando todas as expectativas foram cumpridas ou quando o tempo limite de espera é disparado. (O tempo limite é sempre tratado como uma falha de teste).
Discussão.
Este método cria um ponto de sincronização no fluxo de um teste. Apenas um espera For Expectations With Timeout: manipulador: pode estar ativo em qualquer momento, mas múltiplas seqüências discretas de "criar expectativas e aguardar que sejam cumpridas & quot; podem ser encadeados.
Este método aguarda as expectativas criadas apenas com os métodos de conveniência da XCTest Case & # x27 ;. Este método não espera as expectativas criadas manualmente por meio de inicializações no XCTest Expectation ou suas subclasses.
Para aguardar as expectativas criadas manualmente, use a espera para Expectativas: tempo limite: ou aguarde For Expectations: timeout: impor métodos Order: ou os métodos correspondentes no XCTWaiter, passando uma lista explícita de expectativas.
Os clientes não devem manipular o loop de execução ao usar esta API.
À espera de expectativas.
Espera um grupo de expectativas até o tempo limite especificado.
Espera uma série de expectativas e especifica se elas devem ser cumpridas na ordem dada.
Um bloco a ser chamado quando uma chamada para aguardar For Expectations With Timeout: manipulador: todas as expectativas foram cumpridas, ou expirou.
Códigos de erro para erros que podem ocorrer enquanto espera que as expectativas sejam cumpridas.
Domínio de erro para erros que podem ocorrer enquanto espera que as expectativas sejam cumpridas.
Teste assíncrono.
O teste assíncrono foi feito muito mais fácil com a introdução das expectativas ea classe XCTestExpectation. Além do suporte básico de expectativa incluído, há métodos auxiliares para testar KVO, Notificações e usar Predicados. As expectativas são criadas por métodos auxiliares no XCTestCase.
Principios básicos da expectativa.
Esta é a expectativa básica, você chama de preenchimento () nela.
Você precisa esperar que as expectativas sejam cumpridas por qualquer processo assíncrono que você está testando. Como o nome indica que ele aguardará todas as expectativas que você criou no teste. Eu geralmente só tenho um.
Expectativas complexas.
Eu escrevi o código de teste para uma NSNotification uma vez - sugada e foi uma perda de tempo. Existem alguns bons métodos de fábrica de expectativa, desde que cobrem alguns casos complicados que você definitivamente deve pensar em usar primeiro, não só faz seu teste mais enxuto, mas está escrito para você.
Expectativas do KVO.
Se o teste do cumprimento do KVO definitivamente usa uma expectativa do KVO. Mesmo se não testar explicitamente o KVO, considere se seu teste está interagindo com um objeto compatível com o KVO. HopeValue pode ser nulo para esperar que o valor mude para qualquer outro valor. As expectativas com manipuladores opcionais serão preenchidas se não forem fornecidas. Se você usar seu próprio retorno de manipulador para cumprir a expectativa.
Expectativas de notificação.
Espere um NSNotification em uma linha. Se você não especificar um manipulador, ele será preenchido pela primeira notificação correspondente do objeto especificado, caso contrário, o manipulador deve retornar verdadeiro para atender a expectativa.
Predicar Expectativas.
Durante o teste, o NSPredicate será periodicamente avaliado. Uma vez que é verdade, a expectativa será cumprida, a menos que você especifique um manipulador, caso em que seu manipulador também deve retornar.
É isso mesmo para as expectativas padrão. Gostaria que houvesse uma expectativa de delegado na biblioteca padrão, que iria amarrar as coisas bem e ter os testes assíncronos mais comuns cobertos. Eu tenho uma rápida implementação de um aqui, mas um incluído no XCTest seria ótimo.
Este foi originalmente postado para Ashton-W.
Ao bater palmas mais ou menos, você pode nos indicar quais são as histórias que realmente se destacam.
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.
mokacoding.
Testando callbacks em Swift com XCTest.
Esta publicação será a primeira de uma série em Testes Práticos em Swift. Planejo que as postagens cubram um único tópico e sejam focadas na implementação do código. O plano é liberar pelo menos uma publicação por semana, e eu já tenho 5 tópicos sobre os quais eu gostaria de escrever. O feedback é muito apreciado.
Como você testa o código assíncrono que chama um retorno de chamada?
Diga que você tenha uma classe que execute uma operação assíncrona e executa um fechamento de retorno de encerramento passado como um parâmetro de método.
Você já pode ter experimentado que escrever testes de código como doSomethingAsync da maneira tradicional resultará em comportamentos inesperados e falsos positivos.
A razão pela qual isso acontece é porque, por padrão, o XCTest é síncrono, como a maioria do código do aplicativo que geralmente escrevemos, enquanto o que você está tentando testar é assíncrono. Isso significa que a execução dos testes vai para a próxima linha de código logo após o método assíncrono ser chamado e o teste completo termina antes do encerramento do retorno de chamada ser executado.
O framework XCTest fornece uma API útil para testar o comportamento do código assíncrono: XCTestExpectation.
Vamos dar uma olhada em como testar doSomethingAsync usando XCTestExpectation. Você também pode acompanhar o projeto de exemplo para esta publicação.
Como você pode ver, há três etapas no processo.
Defina uma expectativa com uma descrição significativa. Continue com as fases de configuração e exercício do teste, chamando o método assíncrono e cumprindo a expectativa no final do fechamento de retorno de chamada. Faça com que o corredor de teste aguarde que a expectativa seja cumprida, para que as operações assíncronas possam ser concluídas e as afirmações verificadas.
É importante fornecer uma descrição significativa porque essa descrição é relatada na mensagem de falha de uma expectativa não cumprida:
Quando o teste com mensagens de falha descritiva é muito importante para tornar seu futuro e o resto da equipe identificar o motivo de falha o mais rápido possível.
Espero que você tenha achado esta publicação útil e agradeceria muito os comentários sobre o formato nos comentários abaixo ou me enviando um ping no Twitter @mokagio.
Se você precisar de ajuda com seus testes assíncronos, não hesite em entrar em contato, eu ficaria feliz em ajudar.
Fique atento ao próximo artigo em que veremos como testar chamadas assíncronas de objetos delegados. Se você não quiser perder, certifique-se de se inscrever no boletim informativo.
Deixe a base do código melhor do que você encontrou.
mokacoding.
Oi, Giovanni Lodi e este é o meu blog. Eu escrevo aqui pelo menos uma vez por mês, em testes de software, produtividade e desenvolvimento de iOS.
aguarde Expectativas com tempo limite: manipulador:
Espera até que todas as expectativas sejam cumpridas ou o tempo limite seja alcançado.
Declaração.
Parâmetros.
A quantidade de tempo dentro do qual todas as expectativas devem ser cumpridas.
Um bloqueio opcional XCWait Completion Handler para invocar quando todas as expectativas foram cumpridas ou quando o tempo limite de espera é disparado. (O tempo limite é sempre tratado como uma falha de teste).
Discussão.
Este método cria um ponto de sincronização no fluxo de um teste. Apenas um espera For Expectations With Timeout: manipulador: pode estar ativo em qualquer momento, mas múltiplas seqüências discretas de "criar expectativas e aguardar que sejam cumpridas & quot; podem ser encadeados.
Este método aguarda as expectativas criadas apenas com os métodos de conveniência da XCTest Case & # x27 ;. Este método não espera as expectativas criadas manualmente por meio de inicializações no XCTest Expectation ou suas subclasses.
Para aguardar as expectativas criadas manualmente, use a espera para Expectativas: tempo limite: ou aguarde For Expectations: timeout: impor métodos Order: ou os métodos correspondentes no XCTWaiter, passando uma lista explícita de expectativas.
Os clientes não devem manipular o loop de execução ao usar esta API.
À espera de expectativas.
Espera um grupo de expectativas até o tempo limite especificado.
Espera uma série de expectativas e especifica se elas devem ser cumpridas na ordem dada.
Um bloco a ser chamado quando uma chamada para aguardar For Expectations With Timeout: manipulador: todas as expectativas foram cumpridas, ou expirou.
Códigos de erro para erros que podem ocorrer enquanto espera que as expectativas sejam cumpridas.
Domínio de erro para erros que podem ocorrer enquanto espera que as expectativas sejam cumpridas.
Teste assíncrono.
O teste assíncrono foi feito muito mais fácil com a introdução das expectativas ea classe XCTestExpectation. Além do suporte básico de expectativa incluído, há métodos auxiliares para testar KVO, Notificações e usar Predicados. As expectativas são criadas por métodos auxiliares no XCTestCase.
Principios básicos da expectativa.
Esta é a expectativa básica, você chama de preenchimento () nela.
Você precisa esperar que as expectativas sejam cumpridas por qualquer processo assíncrono que você está testando. Como o nome indica que ele aguardará todas as expectativas que você criou no teste. Eu geralmente só tenho um.
Expectativas complexas.
Eu escrevi o código de teste para uma NSNotification uma vez - sugada e foi uma perda de tempo. Existem alguns bons métodos de fábrica de expectativa, desde que cobrem alguns casos complicados que você definitivamente deve pensar em usar primeiro, não só faz seu teste mais enxuto, mas está escrito para você.
Expectativas do KVO.
Se o teste do cumprimento do KVO definitivamente usa uma expectativa do KVO. Mesmo se não testar explicitamente o KVO, considere se seu teste está interagindo com um objeto compatível com o KVO. HopeValue pode ser nulo para esperar que o valor mude para qualquer outro valor. As expectativas com manipuladores opcionais serão preenchidas se não forem fornecidas. Se você usar seu próprio retorno de manipulador para cumprir a expectativa.
Expectativas de notificação.
Espere um NSNotification em uma linha. Se você não especificar um manipulador, ele será preenchido pela primeira notificação correspondente do objeto especificado, caso contrário, o manipulador deve retornar verdadeiro para atender a expectativa.
Predicar Expectativas.
Durante o teste, o NSPredicate será periodicamente avaliado. Uma vez que é verdade, a expectativa será cumprida, a menos que você especifique um manipulador, caso em que seu manipulador também deve retornar.
É isso mesmo para as expectativas padrão. Gostaria que houvesse uma expectativa de delegado na biblioteca padrão, que iria amarrar as coisas bem e ter os testes assíncronos mais comuns cobertos. Eu tenho uma rápida implementação de um aqui, mas um incluído no XCTest seria ótimo.
Este foi originalmente postado para Ashton-W.
Ao bater palmas mais ou menos, você pode nos indicar quais são as histórias que realmente se destacam.
No comments:
Post a Comment