O blog da AWS

Acelerando o desenvolvimento de workflows com a API TestState no AWS Step Functions

Este post foi escrito por Ben Freiberg, arquiteto sênior de soluções.

Os desenvolvedores geralmente escolhem o AWS Step Functions para orquestrar os serviços que compõem seus aplicativos. O Step Functions é um serviço visual de fluxo de trabalho que facilita aos desenvolvedores criar aplicativos distribuídos, automatizar processos, orquestrar microsserviços e criar pipelines de dados e aprendizado de máquina (ML). O Step Functions se integra a mais de 220 serviços da AWS e a qualquer endpoint HTTP acessível ao público. O Step Functions fornece muitos recurso que ajudam os desenvolvedores a construirem aplicações distribuida, como tratamento de erros integrado, histórico de execução de fluxo de trabalho em tempo real e auditável e processamento paralelo em grande escala.

Várias áreas podem ser complexas para os desenvolvedores ao testar fluxos de trabalho do Step Functions. Por exemplo, autenticação com serviços externos, processamento de entrada/saída, permissão do AWS IAM ou funções intrínsecas. Para simplificar e acelerar a resolução desses problemas, a Step Functions lançou um novo recurso no ano passado para testar estados individuais: a API TestState. Esse recurso permite testar estados independentemente da execução do seu fluxo de trabalho. Você pode alterar a entrada e testar diferentes cenários sem a necessidade de implantar seu fluxo de trabalho ou executar toda a máquina de estado. Esse recurso está disponível para todos os estados de tarefa, escolha e aprovação.

Como os desenvolvedores passam um tempo significativo em IDEs e terminais, o TestState também está disponível por meio de uma API. Isso permite que você itere sobre mudanças para um estado individual e refine o processamento de entrada/saída ou a lógica condicional em um estado de escolha sem sair do seu IDE. Neste post, você aprenderá como a API TestState pode acelerar seus testes e desenvolvimento.

Começando com o TestState

Suponha que você esteja desenvolvendo um fluxo de trabalho de processamento de pagamentos que consiste em três estados. Primeiro, um estado de escolha que verifica o tipo de pagamento com base nos dados de entrada. Dependendo do tipo, ele chama uma função do AWS Lambda ou um endpoint externo. O estado da tarefa que invoca a função Lambda inclui algum processamento de entrada/saída.

Getting started with TestState

Para começar a usar a API TestState, você precisa criar uma função do IAM que o serviço possa assumir. O papel deve conter as permissões necessárias do IAM para os recursos que seu estado está acessando. Para obter informações sobre as permissões que um estado pode precisar, consulte Permissões do IAM para testar um estado. O trecho a seguir mostra as permissões mínimas necessárias:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "states:TestState",
        "iam:PassRole"
      ],
      "Resource": "*"
    }
  ]
}
JSON

Em seguida, você deve fornecer a definição do estado que está sendo testado. O estado de escolha é configurado para verificar o tipo de pagamento e se o VoucherID está presente, no caso de um voucher. O trecho a seguir mostra a definição do estado:

{
    "Type": "Choice",
    "Choices": [
        {
            "And": [
                {
                    "Variable": "$.payment.type",
                    "IsPresent": true
                },
                {
                    "Variable": "$.payment.type",
                    "StringEquals": "voucher"
                }
            ],
            "Next": "Process voucher"
        },
        {
            "Variable": "$.payment.type",
            "StringEquals": "credit",
            "Next": "Call payment provider"
        }
    ],
    "Default": "Fail"
}
JSON

Usando a definição de função e estado, agora você pode testá-la se uma entrada resultar no próximo estado esperado:

aws stepfunctions test-state 
--definition file://choice.json 
--role-arn "arn:aws:iam::<account-id>:role/StepFunctions-TestState-Role" 
--input '{"payment":{"type":"voucher"}}'
Bash

A resposta mostra que o teste não encontrou nenhum erro e que o próximo estado seria invocar a função Lambda para processar o voucher conforme o esperado.

{
    "output": "{\"payment\":{\"type\":\"voucher\"}}",
    "nextState": "Process voucher",
    "status": "SUCCEEDED"
}
JSON

Da mesma forma, com um tipo de pagamento de crédito como entrada, o próximo estado é invocar o endpoint de terceiros:

aws stepfunctions test-state
--definition file://choice.json
--role-arn "arn:aws:iam::<account-id>:role/StepFunctions-TestState-Role"
--input '{"payment":{"type":"credit"}}'
Bash

Como a API TestState usa a definição do estado como argumento, você não precisa reimplantar a máquina de estado ao alterar a definição do estado. Em vez disso, você pode iterar e testar suas configurações passando a definição de estado modificada para a API testState.

Usando níveis de inspeção

Para cada estado, você pode especificar a quantidade de detalhes que deseja visualizar nos resultados do teste. Esses detalhes fornecem informações adicionais sobre o estado que você está testando. Por exemplo, se você usou algum filtro de processamento de dados de entrada e saída, como inputPath ou resultPath em um estado, poderá visualizar os resultados intermediários e finais do processamento de dados. O Step Functions fornece os seguintes níveis para especificar os detalhes que você deseja visualizar: INFO, DEBUG e TRACE. Todos esses níveis retornam os campos status e nextState.

Em seguida, o estado do Lambda Invoke é testado. Nesse cenário, o estado inclui o processamento de entrada/saída. A saída da função é transformada renomeando e reestruturando o campo e, em seguida, mesclada com a entrada original. Essa é a parte relevante da definição da tarefa:

"Process voucher": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {...},
      "Retry": [...],
      "Next": "Success",
      "ResultPath": "$.voucherProcessed",
      "ResultSelector": {
        "status.$": "$.Payload.result",
        "workflowId.$": "$.Payload.workflow"
      }
}
JSON

Dessa vez, teste usando o console Step Functions, que pode facilitar a compreensão das etapas de processamento de entrada/saída. Para começar, abra a máquina de estado no Workflow Studio, selecione o estado e escolha Estado do teste. Certifique-se de selecionar DEBUG como o nível de inspeção. Depois de testar o estado, mude para a guia Processamento de entrada/saída para verificar as etapas intermediárias.

Input/output processing tab

Quando você chama a API testState e define o parâmetro inspectionLevel como DEBUG, a resposta da API inclui um objeto chamado inspectionData. Esse objeto contém campos para ajudá-lo a inspecionar como os dados foram filtrados ou manipulados dentro do estado em que foram executados. Esses dados são mostrados na guia Processamento de entrada/saída no console.

Ser capaz de ver todas as etapas de processamento facilmente em um só lugar permite que os desenvolvedores identifiquem problemas e iterem com mais rapidez, economizando tempo.

Testando integrações de endpoints de terceiros

Os aplicativos podem chamar endpoints de terceiros que exigem autenticação. O Step Functions oferece o recurso de endpoint HTTPS para se conectar a destinos HTTP de terceiros fora da nuvem da AWS.

Os endpoints HTTPS usam conexões do Amazon EventBridge para gerenciar as credenciais de autenticação do destino. Isso define o tipo de autorização usado, que pode ser uma autenticação básica com nome de usuário e senha, uma chave de API ou OAuth. As conexões do EventBridge usam o AWS Secrets Manager para armazenar o segredo. Isso mantém os segredos fora da máquina de estado, reduzindo os riscos de expor acidentalmente seus segredos em registros ou na definição da máquina de estado.

Acertar a configuração de autenticação pode envolver várias iterações demoradas. Com o nível de inspeção TRACE, os desenvolvedores podem ver a solicitação e a resposta HTTP “cruas”, o que é útil para verificar cabeçalhos, parâmetros de consulta e outros detalhes específicos da API. Essa opção só está disponível para a tarefa HTTP. Você também pode ver os segredos incluídos na conexão do EventBridge. Para fazer isso, você deve definir o parâmetro revealSecrets como verdadeiro na API testState. Isso pode ajudar a verificar se os parâmetros de autenticação corretos estão sendo usados.

Para começar, certifique-se de que a função de execução usada para testes tenha as permissões necessárias, conforme mostrado aqui:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret"
            ],
            "Resource": "arn:aws:secretsmanager:<your-region>:<account-id>:secret:events!connection/<your-connection-id>"
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RetrieveConnectionCredentials",
            "Effect": "Allow",
            "Action": [
                "events:RetrieveConnectionCredentials"
            ],
            "Resource": [
                "arn:aws:events:<your-region>:<account-id>:connection/<your-connection-id>"
            ]
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "InvokeHTTPEndpoint",
            "Effect": "Allow",
            "Action": [
                "states:InvokeHTTPEndpoint"
            ],
            "Resource": [
                "arn:aws:states:<your-region>:<account-id>:stateMachine:<your-statemachine>"
            ]
        }
    ]
}
JSON

Ao testar a tarefa HTTP, certifique-se de definir o nível de inspeção como TRACE. Em seguida, use a guia de solicitação e resposta HTTP para verificar os detalhes. Esse recurso economiza seu tempo ao depurar problemas complexos de autenticação.

set the inspection level to TRACE

Automatizando os testes

O teste não é apenas uma atividade manual para acertar a configuração. Na maioria das vezes, os testes são executados como parte de um conjunto de testes, que são executados automaticamente para validar o comportamento correto. Também evita regressões ao fazer alterações. A API TestState também pode ser facilmente integrada nesses testes.

O trecho a seguir mostra um teste usando o framework Jest em JavaScript. O teste verifica se o próximo estado correto é produzido de acordo com uma definição e uma entrada. A definição reside em um arquivo diferente, que também pode ser usado para infraestrutura como código (IaC) para criar a máquina de estado.

const { SFNClient, TestStateCommand } = require("@aws-sdk/client-sfn");
// Import the state definition 
const definition = require("./definition.json");

const client = new SFNClient({});

describe("Step Functions", () => {
  test("that next state is correct", async () => {
    const command = new TestStateCommand({
      definition: JSON.stringify(definition),
      roleArn: "arn:aws:iam::<account-id>:role/<role-with-sufficient-permissions>",
      input: "{}" # Adjust as necessary
    });
    const data = await client.send(command);

    expect(data.status).toBe("SUCCEEDED");
    expect(data.nextState).toBe("Success"); # Adjust as necessary
  });
});
JavaScript

Com testes automatizados, você pode alterar com segurança suas definições de fluxo de trabalho sem a necessidade de esforços manuais. Dessa forma, você é imediatamente alertado se uma alteração resultar em uma incompatibilidade.

Com o TestState, você pode aumentar a cobertura do teste com menos esforço, pois pode testar os estados diretamente. Isso é especialmente útil para fluxos de trabalho e estados complexos que exigem um conjunto específico de circunstâncias para alcançá-los. Isso também facilita a validação da exatidão do tratamento de erros. Agora você pode testar as possíveis combinações de seus Retriers e Catchers configurados com muito mais facilidade.

Conclusão

A API TestState ajuda os desenvolvedores a iterar com mais rapidez, resolver problemas com eficiência e fornecer aplicativos de alta qualidade com maior confiança. Ao permitir que os desenvolvedores testem estados individuais de forma independente e integrando os testes em seus fluxos de trabalho de desenvolvimento preferidos, isso simplifica o processo de depuração e reduz as mudanças de contexto. Seja testando processamento de entrada/saída, autenticação com serviços externos ou integrações de endpoints de terceiros, a API TestState pode ser uma ferramenta útil para testes.

Este blog em português é uma tradução do blog original em inglês (link aqui).

Biografia dos Autores

Ben Freiberg é arquiteto sênior de soluções.

Biografia dos Tradutor e Revisor

 

Daniel Abib é arquiteto de soluções senior na AWS, com mais de 25 anos trabalhando com gerenciamento de projetos, arquiteturas de soluções escaláveis, desenvolvimento de sistemas e CI/CD, microsserviços, arquitetura Serverless & Containers e segurança. Ele trabalha apoiando clientes corporativos, ajudando-os em sua jornada para a nuvem.

https://www.linkedin.com/in/danielabib/

Rodrigo Peres é arquiteto de soluções na AWS, com mais de 20 anos de experiência trabalhando com arquitetura de soluções, desenvolvimento de sistemas e modernização de sistemas legados.