Ao escrever testes de unidade, é comum usar acessórios: poucos dados testáveis, para que possamos dizer: 1. Faça com que todos os clientes incluam Willy Wonka. 2. Exclua o cliente 3 e agora obtenha clientes não deve mais incluir Willy Wonka.
Isso é bom para testes de unidade. Use configuração / desmontagem para recarregar os equipamentos ou reverter a transação. Portanto, os testes de criação, atualização e exclusão são feitos dentro de uma transação . Os novos dados temporários duram apenas a duração desse teste e são redefinidos.
Mas e quando separamos o servidor REST do cliente REST?
Queremos garantir que nosso cliente REST não esteja apenas lendo corretamente, mas criando, atualizando e excluindo corretamente.
Não consegui encontrar exemplos ou sugestões de como fazer isso em um servidor REST de teste remoto.
Supondo que eu tenho um servidor REST de teste que serve apenas equipamentos. Toda a natureza apátrida do HTTP significa que seria difícil enviar uma mensagem do tipo "BEGIN TRANSACTION" e "ROLLBACK TRANSACTION" ou "RELOAD FIXTURES", certo?
Não posso ser o primeiro a querer fazer isso, então sinto que preciso de uma maneira diferente de pensar sobre isso.
Alguma sugestão?
fonte
Respostas:
Idealmente, os sistemas de software têm limites e interfaces de sistema bem definidos entre eles. Os serviços REST são bons exemplos disso.
Para esse fim, eu recomendaria não fazer o que você está tentando fazer.
Especificamente:
O que eu sugeriria é:
Construindo testes para seu cliente REST, para garantir que ele se comporte corretamente, com entrada e saída específicas. Conta para valores bons (esperados) e ruins (inesperados).
Construindo testes para o serviço REST (se você o controlar), para se comportar de acordo com a função pretendida
Mantenha os testes próximos ao domínio do problema, para que eles possam ajudar a orientar o design e o desenvolvimento do que é importante nesse contexto
fonte
Dois ângulos a serem lembrados aqui:
fonte
Acho que fingir as respostas do servidor REST é a melhor maneira de testar o cliente.
Para Ruby, há a gema FakeWeb que você pode usar para emitir respostas falsas - https://github.com/chrisk/fakeweb .
Além disso, em JavaScript, você pode usar algo como Sinon.JS, que fornece um servidor falso - http://sinonjs.org/docs/#fakeServer .
fonte
Como já foi dito, se você estiver testando um cliente, não precisará ir tão longe quanto criar, excluir etc. no servidor. Na maioria das vezes, você nem precisa zombar de um servidor. Você realmente só precisa ter certeza de que está fazendo as solicitações corretas e manipulando as respostas corretamente, seja em Ruby, Python, PHP ou qualquer outra coisa, em algum momento seu cliente provavelmente usará um método de uma biblioteca HTTP para uma solicitação e basta zombar desse método, verificar como ele é chamado e retornar um resultado de teste.
Veja um hipotético cliente Python que é usado
urllib2
para fazer solicitações. Você provavelmente tem algum método no cliente, vamos chamá-loget()
, que tem uma chamada paraurllib2.Request()
ele. Você realmente só precisa zombar da chamada da sua própria turmaget()
.Este exemplo muito simplificado usa a biblioteca Mock do Python para testar uma
your.Client
classe hipotética com umget_object()
método que gera a URL correta para obter algo de alguma API. Para fazer a solicitação, o cliente chama seuget()
método com esse URL. Aqui, esse método é ridicularizado (your.Client.get
é "corrigido" para que esteja sob o controle deyour_mock
) e o teste verifica se o terminal correto foi solicitado.O método simulado retorna a resposta JSON configurada (
your_mock.return_value
) que o cliente deve manipular e você faria outras afirmações para testar se tratou os dados esperados da maneira esperada.fonte
O que você descreve é um cenário de teste de integração. Estes geralmente são um pouco difíceis de configurar e derrubar. Isso os torna lentos para executar e muitas vezes quebradiços.
A abordagem com equipamentos é igualmente desajeitada e desajeitada, mas é a maneira padrão de algumas estruturas, como o Rails, e já é suportada. Eles precisam do caso de teste abstrato ou algo semelhante para preparar o banco de dados com acessórios. (Cuidado com a nomeação incomum de categorias de teste no Rails, os testes de unidade com equipamentos de banco de dados também são estritamente testes de integração.)
A maneira como eu abordaria seu cenário é aceitar ter controle específico do teste sobre o estado do aplicativo da API ou seu banco de dados. Você pode ter pontos de extremidade adicionais para configuração e desmontagem, que estão presentes apenas no ambiente de teste. Ou, alternativamente, você fala com o banco de dados (ou o que quer que esteja usando) nas costas do seu aplicativo / API.
Se você acha que isso é muito esforço (no sentido de indevido), considere que a abordagem com acessórios para bancos de dados faz exatamente isso: usando meios adicionais específicos de teste para manipular o banco de dados ou o estado do aplicativo.
Não acho que essa discussão tenha a ver com a natureza sem estado do HTTP, no entanto. HTTP é sem estado, mas o aplicativo definitivamente não é, na maioria dos casos. Parece um pouco como você procurando por rigor REST. Você também pode ter todos os recursos totalmente criativos, legíveis e excluídos. Nesse caso, você pode simplesmente fazer todas as configurações e desmontagens por meios regulares da API. Porém, isso geralmente não é feito na prática, porque você não deseja incluir determinadas operações a partir do entendimento comercial de seu aplicativo, pelo menos não fora do ambiente de teste.
fonte
Monkey Patch
No meu trabalho, fazemos ATDD usando uma estrutura xUnit existente e chamadas de rede de correção de macaco entre o cliente e o servidor. No mesmo espaço de processo que carregamos o cliente, o patch do macaco é chamado de rede para a parte superior do código da pilha do servidor REST. Todas as chamadas são emitidas do cliente como normalmente seriam, e o código do servidor recebe as solicitações exatamente como elas normalmente apareceriam.
Benefícios
Tradeoffs
fonte