Como testar funções e aplicações com tecnologia sem servidor - AWS Lambda

Como testar funções e aplicações com tecnologia sem servidor

Os testes de funções com tecnologia sem servidor usam tipos e técnicas de teste tradicionais, mas você também deve considerar testar aplicações com tecnologia sem servidor como um todo. Os testes baseados em nuvem fornecerão a medida mais precisa da qualidade das suas funções e aplicações com tecnologia sem servidor.

Uma arquitetura de aplicações com tecnologia sem servidor inclui serviços gerenciados que fornecem funcionalidade de aplicações  críticas por meio de chamadas de API. Por esse motivo, seu ciclo de desenvolvimento deve incluir testes automatizados que verifiquem a funcionalidade quando sua função e seus serviços interagem.

Se você não criar testes baseados em nuvem, poderá encontrar problemas devido às diferenças entre o ambiente local e o ambiente implantado. Seu processo de integração contínua deve executar testes em comparação com um conjunto de recursos provisionados na nuvem antes de promover seu código para o próximo ambiente de implantação, como GQ, Preparação ou Produção.

Continue lendo este breve guia para aprender sobre estratégias de testes para aplicações com tecnologia sem servidor ou acesse o repositório de exemplos de testes com tecnologia sem servidor para conhecer exemplos práticos, específicos da linguagem e do runtime escolhidos.

illustration showing the relationship between types of tests

Para testes com tecnologia sem servidor, você ainda escreverá testes unitários, de integração e de ponta a ponta.

  • Testes unitários: testes executados em comparação com um bloco de código isolado. Por exemplo, verificar a lógica de negócios para calcular a taxa de entrega de acordo com um item e um destino determinado.

  • Testes de integração: testes envolvendo dois ou mais componentes ou serviços que interagem, normalmente em um ambiente de nuvem. Por exemplo, a verificação de eventos de processos de uma função em uma fila.

  • Testes de ponta a ponta: testes que verificam o comportamento em toda a aplicação. Por exemplo, garantir que a infraestrutura seja configurada corretamente e que os eventos fluam entre os serviços conforme o esperado para registrar o pedido de um cliente.

Resultados de negócios direcionados

Testar soluções com tecnologia sem servidor pode exigir um pouco mais de tempo para configurar testes que verifiquem as interações orientadas por eventos entre os serviços. Tenha em mente as seguintes questões práticas de negócios ao ler este guia:

  • Aumentar a qualidade da sua aplicação

  • Diminuir o tempo para criar recursos e corrigir bugs

A qualidade de uma aplicação depende do teste de vários cenários para verificar a funcionalidade. Considerar cuidadosamente os cenários de negócios e automatizar esses testes para serem executados em comparação com serviços em nuvem aumentará a qualidade da sua aplicação.

Bugs de software e problemas de configuração têm o menor impacto no custo e na programação quando detectados durante um ciclo de desenvolvimento iterativo. Se os problemas não forem detectados durante o desenvolvimento, a descoberta e a correção em produção exigirão mais esforços de mais pessoas.

Uma estratégia de teste com tecnologia sem servidor bem planejada aumentará a qualidade do software e melhorará o tempo de iteração ao verificar a performance das suas aplicações e funções do Lambda, conforme esperado em um ambiente de nuvem.

O que testar

Recomendamos a adoção de uma estratégia de testes que teste os comportamentos dos serviços gerenciados, a configuração da nuvem, as políticas de segurança e a integração com seu código para melhorar a qualidade do software. Os testes de comportamento, também conhecidos como testes da caixa preta, verificam se um sistema funciona conforme o esperado sem o conhecimento de todos os componentes internos.

  • Execute testes unitários para verificar a lógica de negócios dentro das funções do Lambda.

  • Verifique se os serviços integrados foram realmente invocados e  se os parâmetros de entrada estão corretos.

  • Verifique se um evento passa por todos os serviços esperados de ponta a ponta em um fluxo de trabalho.

Na arquitetura tradicional baseada em servidor, as equipes frequentemente definem um escopo de testes para incluir somente o código executado no servidor de aplicações. Outros componentes, serviços ou dependências são frequentemente considerados externos e fora do escopo dos testes.

As aplicações com tecnologia sem servidor geralmente consistem em pequenas unidades de trabalho, como funções do Lambda que recuperam produtos de um banco de dados, processam itens de uma fila ou redimensionam uma imagem no armazenamento. Cada componente é executado no seu próprio ambiente. As equipes provavelmente serão responsáveis por muitas dessas pequenas unidades em uma única aplicação.

Algumas funcionalidades da aplicação podem ser delegadas inteiramente para serviços gerenciados, como o Amazon S3, ou criadas sem o uso de qualquer código desenvolvido internamente. Não há necessidade de testar esses serviços gerenciados, mas é necessário testar a integração com esses serviços.

Como testar com tecnologia sem servidor

Você provavelmente está familiarizado com a forma de testar aplicações implantadas localmente: você escreve testes que são executados em comparação com o código executado inteiramente no sistema operacional da área de trabalho ou dentro de contêineres. Por exemplo, você pode invocar um componente de serviço Web local com uma solicitação e, em seguida, fazer declarações sobre a resposta.

As soluções com tecnologia sem servidor são criadas com base no seu código de função e em serviços gerenciados baseados em nuvem, como filas, bancos de dados, barramentos de eventos e sistemas de mensagens. Esses componentes são todos conectados por meio de uma arquitetura orientada por eventos, na qual as mensagens, chamadas de eventos, fluem de um recurso para outro. Essas interações podem ser síncronas, como quando um serviço Web retorna resultados imediatamente, ou uma ação assíncrona que é concluída posteriormente, como colocar itens em uma fila ou iniciar uma etapa do fluxo de trabalho. Sua estratégia de testes deve incluir ambos os cenários e testar as interações entre os serviços. Para interações assíncronas, talvez seja necessário detectar efeitos colaterais em componentes downstream que podem não ser imediatamente observáveis.

Replicar todo um ambiente de nuvem, incluindo filas, tabelas de banco de dados, barramentos de eventos, políticas de segurança e muito mais, não é prático. Você inevitavelmente encontrará problemas devido às diferenças entre seu ambiente local e seus ambientes implantados na nuvem. As variações entre seus ambientes aumentarão o tempo de reprodução e correção de bugs.

Em aplicações com tecnologia sem servidor, os componentes da arquitetura geralmente existem inteiramente na nuvem. Portanto, são necessários testes com códigos e serviços na nuvem para desenvolver recursos e corrigir bugs.

Técnicas de teste

Na realidade, sua estratégia de testes provavelmente incluirá uma combinação de técnicas para aumentar a qualidade das suas soluções. Você usará testes interativos rápidos para depurar funções no console, testes de unidade automatizados para verificar a lógica de negócios isolada, verificação de chamadas para serviços externos com simulações e testes ocasionais em comparação com emuladores que imitam um serviço.

  • Testes na nuvem: você implanta infraestrutura e código para testar com serviços reais, políticas de segurança, configurações e parâmetros específicos da infraestrutura. Os testes baseados em nuvem fornecem a medida mais precisa da qualidade do seu código.

    Depurar uma função no console é uma forma rápida de testar na nuvem. Você pode escolher entre uma biblioteca de eventos de teste de exemplo ou criar um evento personalizado para testar uma função isoladamente. Você também pode compartilhar eventos de teste por meio do console com sua equipe.

    Para automatizar os testes no ciclo de vida de desenvolvimento e construção, você precisará testar fora do console. Consulte as seções de testes específicos da linguagem neste guia para obter estratégias e recursos de automação.

  • Testar com simulações (também chamadas de imitações): as simulações são objetos no seu código que simulam e substituem um serviço externo. As simulações fornecem um comportamento predefinido para verificar as chamadas e parâmetros de serviços. Uma imitação é a implementação de uma simulação que usa atalhos para simplificar ou melhorar a performance. Por exemplo, a imitação de um objeto de acesso a dados pode retornar dados de um datastore na memória. As simulações podem imitar e simplificar dependências complexas, mas também podem levar a mais simulações para substituir dependências aninhadas.

  • Testar com emuladores: você pode configurar aplicações (às vezes, de terceiros) para imitar um serviço de nuvem no seu ambiente local. Velocidade é o ponto forte deles, mas a configuração e a paridade com os serviços de produção são o ponto fraco. Use emuladores com moderação.

Testes na nuvem

Os testes na nuvem são valiosos para todas as fases dos testes, incluindo testes unitários, testes de integração e testes de ponta a ponta. Quando você executa testes comparados com um código baseado na nuvem que também interage com serviços baseados na nuvem, você obtém a medida mais precisa da qualidade do seu código.

Uma maneira conveniente de executar uma função do Lambda na nuvem é por meio de um evento de teste no AWS Management Console. Um evento de teste é uma entrada JSON para sua função. Se a função não necessitar de entrada, o evento poderá ser um documento JSON vazio ({}). O console fornece eventos de exemplo para uma variedade de integrações de serviços. Depois de criar um evento no console, você também pode compartilhá-lo com sua equipe para tornar os testes mais fáceis e consistentes.

Saiba como depurar uma função de exemplo no console.

nota

Embora executar funções no console seja uma maneira rápida de depurar, a automatização dos ciclos de teste é essencial para aumentar a qualidade e a velocidade de desenvolvimento da aplicação.

Exemplos de automação de testes estão disponíveis no repositório de exemplos de testes com tecnologia sem servidor. A linha de comando a seguir executa um exemplo de teste de integração automatizado no Python:

python -m pytest -s tests/integration -v

Embora o teste seja executado localmente, ele interage com recursos baseados na nuvem. Esses recursos foram implantados usando a ferramenta da linha de comando do AWS SAM e AWS Serverless Application Model. O código de teste primeiro recupera as saídas da pilha implantada, que inclui o endpoint da API, o ARN da função e a função de segurança. Em seguida, o teste envia uma solicitação ao endpoint da API, que responde com uma lista de buckets do Amazon S3. Esse teste é executado inteiramente com recursos baseados na nuvem para verificar se esses recursos estão implantados e protegidos e se funcionam conforme esperado.

========================= test session starts ========================= platform darwin -- Python 3.10.10, pytest-7.3.1, pluggy-1.0.0 -- /Users/t/code/aws/serverless-test-samples/python-test-samples/apigw-lambda/venv/bin/python cachedir: .pytest_cache rootdir: /Users/t/code/aws/serverless-test-samples/python-test-samples/apigw-lambda plugins: mock-3.10.0 collected 1 item tests/integration/test_api_gateway.py::TestApiGateway::test_api_gateway --> Stack outputs: HelloWorldApi = https://p7teqs3162.execute-api.us-east-2.amazonaws.com/Prod/hello/ > API Gateway endpoint URL for Prod stage for Hello World function PythonTestDemo = arn:aws:lambda:us-east-2:123456789012:function:testing-apigw-lambda-PythonTestDemo-iSij8evaTdxl > Hello World Lambda Function ARN PythonTestDemoIamRole = arn:aws:iam::123456789012:role/testing-apigw-lambda-PythonTestDemoRole-IZELQQ9MG4HQ > Implicit IAM Role created for Hello World function --> Found API endpoint for "testing-apigw-lambda" stack... --> https://p7teqs3162.execute-api.us-east-2.amazonaws.com/Prod/hello/ API Gateway response: amplify-dev-123456789-deployment|myapp-prod-p-loggingbucket-123456|s3-java-bucket-123456789 PASSED ========================= 1 passed in 1.53s =========================

Para o desenvolvimento de aplicações nativas de nuvem, os testes na nuvem oferecem os seguintes benefícios:

  • Você pode testar todos os serviços disponíveis.

  • Você está sempre usando as APIs de serviço e os valores de retorno mais recentes.

  • Um ambiente de teste na nuvem se assemelha muito ao seu ambiente de produção.

  • Os testes podem abranger políticas de segurança, cotas de serviço, configurações e parâmetros específicos da infraestrutura.

  • Cada desenvolvedor pode criar rapidamente um ou mais ambientes de teste na nuvem.

  • Os testes na nuvem aumentam a confiança de que seu código será executado corretamente na produção.

Os testes na nuvem têm algumas desvantagens. O aspecto negativo mais óbvio dos testes na nuvem é que as implantações em ambientes de nuvem geralmente demoram mais do que as implantações em ambientes de área de trabalho locais.

Ferramentas, como o AWS Serverless Application Model (AWS SAM) Accelerate, o modo de observação do kit de desenvolvimento em nuvem (CDK da AWS) e o SST (terceiros) reduzem a latência envolvida nas iterações de implantação na nuvem. Essas ferramentas podem monitorar sua infraestrutura e seu código e implantar automaticamente atualizações incrementais no seu ambiente de nuvem.

nota

Veja como criar infraestrutura como código no Guia do desenvolvedor de tecnologia sem servidor para saber mais sobre o AWS Serverless Application Model, AWS CloudFormation e AWS Cloud Development Kit (AWS CDK).

Diferentemente dos testes locais, os testes na nuvem exigem recursos adicionais que podem gerar custos de serviço. A criação de ambientes de teste isolados pode aumentar a carga sobre suas equipes de DevOps, especialmente em organizações com controles rígidos sobre contas e infraestrutura. Mesmo assim, ao trabalhar com cenários de infraestrutura complexos, o custo do tempo do desenvolvedor para configurar e manter um ambiente local complexo pode ser semelhante (ou mais caro) ao de usar ambientes de teste descartáveis criados com ferramentas de automação de infraestrutura como código.

Testar na nuvem, mesmo com essas considerações, ainda é a melhor maneira de garantir a qualidade das suas soluções com tecnologia sem servidor.

Testar com simulações

Testar com simulações é uma técnica em que você cria objetos de substituição no seu código para simular o comportamento de um serviço em nuvem.

Por exemplo, você pode escrever um teste que usa uma simulação do serviço do Amazon S3 que retorna uma resposta específica sempre que o método CreateObject é chamado. Quando um teste é executado, a simulação retorna essa resposta programada sem chamar o Amazon S3 ou qualquer outro endpoint de serviço.

Objetos simulados são frequentemente gerados por uma estrutura simulada para reduzir o esforço de desenvolvimento. Algumas estruturas simuladas são genéricas e outras são criadas especificamente para AWS SDKs, como o Moto, uma biblioteca Python para simular serviços e recursos da AWS.

Observe que os objetos simulados diferem dos emuladores porque os simuladores normalmente são criados ou configurados por um desenvolvedor como parte do código de teste, enquanto os emuladores são aplicações autônomas que expõem a funcionalidade da mesma maneira que os sistemas que elas emulam.

As vantagens de usar simulações incluem o seguinte:

  • Elas podem simular serviços de terceiros que estão além do controle da aplicação, como APIs e provedores de software como serviço (SaaS), sem precisar de acesso direto a esses serviços.

  • As simulações são úteis para testar condições de falha, especialmente quando essas condições são difíceis de simular, como uma interrupção do serviço.

  • A simulação pode fornecer testes locais rápidos depois de configurada.

  • As simulações podem fornecer um comportamento substituto para praticamente qualquer tipo de objeto. Portanto, as estratégias de simulação podem criar cobertura para uma variedade mais ampla de serviços do que os emuladores.

  • Quando novos recursos ou comportamentos são disponibilizados, os testes com simulações podem reagir mais rapidamente. Ao usar uma estrutura simulada genérica, você poderá simular novos recursos assim que o AWS SDK atualizado estiver disponível.

O teste com simulação tem as seguintes desvantagens:

  • As simulações geralmente exigem uma quantidade significativa de esforços de definição e configuração, especificamente na tentativa de determinar valores de retorno de diferentes serviços para simular respostas adequadamente.

  • As simulações são escritas, configuradas e devem ser mantidas pelos desenvolvedores, aumentando suas responsabilidades.

  • Talvez você precise ter acesso à nuvem para entender as APIs e os valores de retorno dos serviços.

  • As simulações podem ser difíceis de manter. Quando as assinaturas simuladas da API de nuvem mudam ou os esquemas de valor de retorno evoluem, é preciso atualizar as simulações. As simulações também exigem atualizações se você estender a lógica da aplicação para fazer chamadas para novas APIs.

  • Os testes que usam simulações podem passar em ambientes de área de trabalho, mas falhar na nuvem. Os resultados podem não corresponder à API atual. A configuração e as cotas do serviço não podem ser testadas.

  • As estruturas simuladas se limitam a testar ou detectar uma política do AWS Identity and Access Management (IAM). Embora as simulações sejam melhores para simular quando a autorização falha ou uma cota é excedida, os testes não podem determinar que resultado realmente ocorrerá em um ambiente de produção.

Testar com emulação

Os emuladores normalmente são uma aplicação executada localmente que imita um serviço da AWS de produção.

Os emuladores têm APIs semelhantes às APIs equivalentes da nuvem e fornecem valores de retorno semelhantes. Eles também podem simular mudanças de estado iniciadas por chamadas de API. Por exemplo, você pode usar o AWS SAM para executar uma função com o AWS SAM local para emular o serviço do Lambda para poder invocar rapidamente uma função. Consulte o AWS SAM local no Guia do desenvolvedor do AWS Serverless Application Model para obter detalhes.

As vantagens do teste com emuladores incluem o seguinte:

  • Os emuladores podem facilitar iterações e testes rápidos de desenvolvimento local.

  • Os emuladores fornecem um ambiente familiar para desenvolvedores acostumados a desenvolver código em um ambiente local. Por exemplo, se você estiver familiarizado com o desenvolvimento de uma aplicação de n camadas, talvez tenha um mecanismo de banco de dados e um servidor Web, semelhantes aos executados em produção na sua máquina local para fornecer uma capacidade de teste rápida, local e isolada.

  • Os emuladores não exigem qualquer alteração na infraestrutura de nuvem (como contas de desenvolvedores na nuvem). Por isso, é fácil implementar com os padrões de teste existentes.

Testar com emuladores tem as seguintes desvantagens:

  • Os emuladores podem ser difíceis de configurar e replicar, especialmente quando usados em pipelines de CI/CD. Isso pode aumentar a workload da equipe de TI ou dos desenvolvedores que gerenciam seu próprio software.

  • Os recursos e APIs emulados geralmente ficam atrasados em relação às atualizações do serviço. Isso pode causar erros porque o código testado não corresponde à API real e impede a adoção de novos recursos.

  • Os emuladores precisam de suporte, atualizações, correções de bugs e aprimoramentos de paridade de recursos. Eles são de responsabilidade do autor do emulador, que pode ser uma empresa externa.

  • Os testes que dependem de emuladores podem fornecer resultados bem-sucedidos localmente, mas falham na nuvem devido a políticas de segurança de produção, configurações entre serviços ou excesso de cotas do Lambda.

  • Muitos serviços da AWS não têm emuladores disponíveis. Se você depende da emulação, talvez não tenha uma opção de teste satisfatória para partes da sua aplicação.

Práticas recomendadas

As seções a seguir fornecem recomendações para testes bem-sucedidos de aplicações com tecnologia sem servidor.

Você pode encontrar exemplos práticos de testes e automação de testes no repositório de exemplos de testes com tecnologia sem servidor.

Priorize os testes na nuvem

Os testes na nuvem fornecem a cobertura de teste mais confiável, precisa e completa. A realização de testes no contexto da nuvem testará de forma abrangente não apenas a lógica de negócios, mas também as políticas de segurança, as configurações de serviços, as cotas, as assinaturas de API e os valores de retorno mais atualizados.

Estruture seu código quanto à capacidade de teste

Simplifique seus testes e funções do Lambda separando o código específico do Lambda da sua principal lógica de negócios.

Seu manipulador de funções do Lambda deve ser um pequeno adaptador que absorve dados de eventos e transmite somente os detalhes importantes para seus métodos de lógica de negócios. Com essa estratégia, você pode realizar testes abrangentes na sua lógica de negócios sem se preocupar com detalhes específicos do Lambda. Suas funções do AWS Lambda não devem exigir a configuração de um ambiente complexo ou uma grande quantidade de dependências para criar e inicializar o componente em teste.

De um modo geral, você deve escrever um manipulador que extraia e valide dados do evento de entrada e dos objetos de contexto e, em seguida, envie essa entrada aos métodos que executam sua lógica de negócios.

Acelerar loops de feedback de desenvolvimento

Existem ferramentas e técnicas para acelerar os loops de feedback de desenvolvimento. Por exemplo, o AWS SAM Accelerate e o modo de observação do AWS CDK diminuem o tempo necessário para atualizar os ambientes de nuvem.

Os exemplos no repositório de exemplos de testes com tecnologia sem servidor do GitHub exploram algumas dessas técnicas.

Também recomendamos que você crie e teste os recursos de nuvem o mais cedo possível durante o desenvolvimento, não somente após um registro no controle de origem. Essa prática permite uma exploração e experimentação mais rápidas no desenvolvimento de soluções. Além disso, automatizar a implantação em uma máquina de desenvolvimento ajuda a descobrir problemas de configuração da nuvem com mais rapidez e reduz o esforço desperdiçado em atualizações e processos de revisão de código.

Foco nos testes de integração

Ao criar aplicações com o Lambda, testar os componentes juntos é a melhor prática.

Os testes executados em comparação com dois ou mais componentes arquitetônicos são chamados de testes de integração. O objetivo dos testes de integração é entender não apenas como seu código será executado em todos os componentes, mas também como o ambiente que hospeda seu código se comportará. Testes de ponta a ponta são tipos especiais de testes  de integração que verificam o comportamento em toda uma aplicação.

Para criar testes de integração, implante sua aplicação em um ambiente de nuvem. Isso pode ser feito em um ambiente local ou por meio de um pipeline de CI/CD. Em seguida, escreva testes para exercitar o sistema em teste (SUT) e validar o comportamento esperado.

Por exemplo, o sistema em teste pode ser uma aplicação que usa o API Gateway, Lambda e DynamoDB. Um teste pode fazer uma chamada HTTP sintética para um endpoint do API Gateway e validar se a resposta incluiu a carga útil esperada. Esse teste valida se o código do AWS Lambda está correto e se cada serviço está configurado corretamente para processar a solicitação, incluindo as permissões do IAM entre eles. Além disso, você pode criar o teste para gravar registros de vários tamanhos para verificar se suas cotas de serviço, como o tamanho máximo do registro no DynamoDB, estão configuradas corretamente.

Diagrama mostrando um sistema em teste composto de três serviços.

Criar ambientes de teste isolados

Os testes na nuvem normalmente exigem ambientes de desenvolvedores isolados para que não haja sobreposição de testes, dados e eventos.

Uma abordagem é fornecer a cada desenvolvedor uma conta da AWS dedicada. Isso evitará conflitos com a nomenclatura de recursos que podem ocorrer quando vários desenvolvedores trabalhando em uma base de código compartilhada tentarem implantar recursos ou invocar uma API.

Os processos de teste automatizados devem criar recursos com nomes exclusivos para cada pilha. Por exemplo, você pode configurar scripts ou arquivos de configuração TOML para que os comandos sam deploy ou sam sync da CLI do AWS SAM especifiquem automaticamente uma pilha com um prefixo exclusivo.

Em alguns casos, os desenvolvedores compartilham uma conta da AWS. Isso pode ocorrer devido à existência de recursos em sua pilha que são caros para operar ou de provisionar e configurar. Por exemplo, um banco de dados pode ser compartilhado para facilitar a configuração e a propagação adequada dos dados.

Se os desenvolvedores compartilharem uma conta, você deverá definir limites para identificar a propriedade e eliminar a sobreposição. Uma maneira de fazer isso é prefixar os nomes das pilhas com os IDs de usuário dos desenvolvedores. Outra abordagem popular é configurar pilhas com base em ramificações de código. Com os limites das ramificações, os ambientes são isolados, mas os desenvolvedores ainda podem compartilhar recursos, como um banco de dados relacional. Essa abordagem é a melhor prática quando os desenvolvedores trabalham em mais de uma ramificação ao mesmo tempo.

Os testes na nuvem são valiosos para todas as fases dos testes, incluindo testes unitários, testes de integração e testes de ponta a ponta. Manter o isolamento adequado é essencial. Porém, você ainda quer que seu ambiente de GQ seja o mais parecido possível com seu ambiente de produção. Por esse motivo, as equipes adicionam processos de controle de mudanças para ambientes de GQ.

Para ambientes de pré-produção e de produção, geralmente são estabelecidos limites no nível da conta para isolar as workloads dos problemas de vizinho barulhento e implementar controles de segurança com privilégio mínimo para proteger dados confidenciais. As workloads têm cotas. Você não quer que seus testes consumam cotas alocadas para produção (vizinho barulhento) ou tenham acesso aos dados do cliente. O teste de carga é outra atividade que você deve isolar da sua pilha de produção.

Em todos os casos, os ambientes devem ser configurados com alertas e controles para evitar gastos desnecessários. Por exemplo, você pode limitar o tipo, a camada ou o tamanho dos recursos que podem ser criados e configurar alertas por e-mail quando os custos estimados excederem um determinado limite.

Use simulações para lógica de negócios isolada

As estruturas simuladas são uma ferramenta valiosa para escrever testes unitários rápidos. Elas são especialmente benéficas quando os testes abrangem lógicas de negócios internas complexas, como cálculos ou simulações matemáticas ou financeiras. Procure testes unitários que tenham um grande número de casos de teste ou variações de entrada, nos quais essas entradas não alterem o padrão ou o conteúdo das chamadas para outros serviços de nuvem.

O código coberto por testes unitários com simulações também deve ser abordado por testes na nuvem. Isso é recomendado porque o laptop de um desenvolvedor ou o ambiente de uma máquina de criação pode ser configurado de forma diferente de um ambiente de produção na nuvem. Por exemplo, suas funções do Lambda podem usar mais memória ou tempo do que o alocado quando executadas com determinados parâmetros de entrada. Ou seu código pode incluir variáveis de ambiente que não estão configuradas da mesma forma (ou não estão configuradas) e as diferenças podem fazer com que o código se comporte de forma diferente ou apresente falha.

O benefício das simulações é menor para testes de integração porque o nível de esforço para implementar as simulações necessárias aumenta com o número de pontos de conexão. Os testes de ponta a ponta não devem usar simulações porque eles geralmente lidam com estados e lógica complexa que não podem ser facilmente simulados com estruturas de simulação.

Por fim, evite usar serviços de nuvem simulados para validar a implementação adequada das chamadas de serviço. Em vez disso, faça chamadas de serviço de nuvem na nuvem para validar o comportamento, a configuração e a implementação funcional.

Usar emuladores com moderação

Os emuladores podem ser convenientes em alguns casos de uso, por exemplo, para uma equipe de desenvolvimento com acesso limitado, não confiável ou lento à Internet. Mas, na maioria das circunstâncias, opte por usar emuladores com moderação.

Ao evitar emuladores, você poderá criar e inovar com os recursos de serviço mais recentes e APIs atualizadas. Você não ficará preso esperando os lançamentos de fornecedores para obter paridade de recursos. Você reduzirá suas despesas iniciais e contínuas de compra e configuração em vários sistemas de desenvolvimento e máquinas de criação. Além disso, você evitará o problema de muitos serviços em nuvem simplesmente não terem emuladores disponíveis. Uma estratégia de teste que depende de emulação impossibilitará o uso desses serviços (resultando em soluções alternativas potencialmente mais caras) ou produzirá código e configurações que não foram bem testados.

Ao usar a emulação para testes, você ainda deve testar na nuvem para verificar a configuração e testar as interações com serviços em nuvem que só podem ser simulados ou reproduzidos em um ambiente emulado.

Testes de desafios no local

Ao usar emuladores e chamadas simuladas para testar no desktop local, você pode observar inconsistências de teste à medida que seu código progride de ambiente para ambiente em seu pipeline de CI/CD. Os testes unitários para validar a lógica de negócios da aplicação no desktop podem não testar com precisão aspectos críticos dos serviços em nuvem.

Os exemplos a seguir fornecem casos a serem observados nos testes realizados no local com simulações e emuladores:

Exemplo: a função do Lambda cria um bucket do S3

Se a lógica de uma função do Lambda depender da criação de um bucket do S3, um teste completo deverá confirmar que o Amazon S3 foi chamado e que o bucket foi criado com sucesso.

  • Em uma configuração de teste de simulação, você pode simular uma resposta bem-sucedida e potencialmente adicionar um caso de teste para lidar com uma resposta de falha.

  • Em um cenário de teste de emulação, a API CreateBucket pode ser chamada, mas você precisa estar ciente de que a identidade que faz a chamada local não se origina do serviço do Lambda. A identidade da chamada não assumirá uma função de segurança como na nuvem. Portanto, uma autenticação de espaço reservado será usada em seu lugar, possivelmente com uma função ou identidade de usuário mais permissiva que será diferente quando executada na nuvem.

As configurações de simulação e emulação testarão o que a função do Lambda fará se chamar o Amazon S3; no entanto, esses testes não verificarão se a função do Lambda, conforme configurada, é capaz de criar com êxito o bucket do Amazon S3. Você deve garantir que a função atribuída à função tenha uma política de segurança anexada que permita que a função execute a ação s3:CreateBucket. Caso contrário, a função provavelmente falhará quando implantada em um ambiente de nuvem.

Exemplo: a função do Lambda processa mensagens de uma fila do Amazon SQS

Se uma fila do Amazon SQS for a origem de uma função do Lambda, um teste completo deverá verificar se a função do Lambda vai ser invocada com êxito quando uma mensagem for colocada em uma fila.

Os testes de emulação e simulação geralmente são configurados para executar o código da função do Lambda diretamente e para simular a integração do Amazon SQS passando uma carga útil de eventos JSON (ou um objeto desserializado) como entrada do manipulador da função.

O teste local que simula a integração do Amazon SQS testará o que a função do Lambda fará quando for chamada pelo Amazon SQS com uma determinada carga útil, mas o teste não verificará se o Amazon SQS invocará com êxito a função do Lambda quando ela for implantada em um ambiente de nuvem.

Alguns exemplos de problemas de configuração que você pode encontrar com o Amazon SQS e o Lambda incluem o seguinte:

  • O tempo limite de visibilidade do Amazon SQS é muito baixo, resultando em várias invocações quando apenas uma foi planejada.

  • A função de execução da função do Lambda não permite a leitura de mensagens da fila (por meio de sqs:ReceiveMessagesqs:DeleteMessage ou sqs:GetQueueAttributes).

  • O evento de exemplo que é passado para a função do Lambda excede a cota de tamanho de mensagem do Amazon SQS. Portanto, o teste é inválido porque o Amazon SQS nunca seria capaz de enviar uma mensagem desse tamanho.

Como mostrado nesses exemplos, os testes que abrangem a lógica de negócios, mas não as configurações entre os serviços de nuvem, provavelmente fornecerão resultados não confiáveis.

Perguntas frequentes

Tenho uma função do Lambda que executa cálculos e retorna um resultado sem chamar qualquer outro serviço. Preciso realmente testá-la na nuvem?

Sim. As funções do Lambda têm parâmetros de configuração que podem alterar o resultado do teste. Todo código de função do Lambda tem uma dependência nas configurações de tempo limite e memória, o que pode causar falha da função se essas configurações não forem definidas corretamente. As políticas do Lambda também permitem o registro de saída padrão para o Amazon CloudWatch. Mesmo que seu código não chame o CloudWatch diretamente, é necessária uma permissão para ativar o registro. Essa permissão necessária não pode ser simulada ou emulada com precisão.

Como os testes na nuvem podem ajudar nos testes unitários? Caso esteja na nuvem e se conecte a outros recursos, não é um teste de integração?

Nós definimos testes unitários como testes que operam isoladamente em componentes da arquitetura, mas isso não impede que os testes incluam componentes que possam chamar outros serviços ou usar alguma comunicação de rede.

Muitas aplicações com tecnologia sem servidor têm componentes da arquitetura que podem ser testados isoladamente, mesmo na nuvem. Um exemplo é uma função do Lambda que recebe entradas, processa os dados e envia uma mensagem para uma fila do Amazon SQS. Um teste unitário dessa função provavelmente testaria se os valores de entrada resultariam na presença de determinados valores na mensagem colocada em fila.

Considere um teste escrito usando o padrão Organizar, Agir, Declarar:

  • Organizar: aloque recursos (uma fila para receber mensagens e a função em teste).

  • Agir: chame a função em teste.

  • Declarar: recupere a mensagem enviada pela função e valide a saída.

Uma abordagem de teste de simulação consistiria em simular a fila com um objeto simulado em andamento e em criar uma instância em andamento da classe ou do módulo que conteria o código da função do Lambda. Durante a fase Declarar, a mensagem colocada em fila seria recuperada do objeto simulado.

Em uma abordagem baseada em nuvem, o teste criaria uma fila do Amazon SQS para fins do teste e implantaria a função do Lambda com variáveis de ambiente configuradas para usar a fila isolada do Amazon SQS como destino de saída. Depois de executar a função do Lambda, o teste recuperaria a mensagem da fila do Amazon SQS.

O teste baseado em nuvem executaria o mesmo código, declararia o mesmo comportamento e validaria a correção funcional da aplicação. No entanto, ele teria a vantagem adicional de poder validar as configurações da função do Lambda: o perfil do IAM, as políticas do IAM e as configurações de tempo limite e memória da função.

Próximas etapas e recursos

Use os recursos a seguir para saber mais e explore os exemplos práticos dos testes.

Exemplos de implementações

O repositório de exemplos de testes com tecnologia sem servidor no GitHub contém exemplos concretos de testes que seguem os padrões e as práticas recomendadas descritos neste guia. O repositório contém exemplos de códigos e o passo a passo guiado dos processos de simulação, emulação e teste em nuvem descritos nas seções anteriores. Use esse repositório para se atualizar com as orientações mais recentes sobre testes com tecnologia sem servidor da AWS.

Outras fontes de leitura

Visite o Serverless Land para acessar os blogs, vídeos e treinamentos mais recentes sobre tecnologias sem servidor da AWS.

A leitura das seguintes publicações do blog da AWS também é recomendada:

Ferramentas