Jak pisać i wykonywać testy integracyjne dla aplikacji AWS CDK

18 sierpnia 2023

Jak pisac i wykonywac testy integracyjne dla aplikacji AWS CDK

Zautomatyzowane testy integracyjne sprawdzają poprawność komponentów systemu i zwiększają zaufanie do nowych wersji oprogramowania. Przeprowadzanie testów integracyjnych zasobów wdrożonych w chmurze AWS umożliwia weryfikację zasad AWS Identity and Access Management (IAM), limitów usług, konfiguracji aplikacji i kodu wykonawczego. Dla programistów, którzy obecnie wykorzystują AWS Cloud Development Kit (AWS CDK) jako narzędzie Infrastructure as Code, dostępna jest platforma testowa, która ułatwia wdrażanie testów integracyjnych w danej wersji oprogramowania.

AWS CDK to platforma typu open source do definiowania i udostępniania infrastruktury chmurowej AWS przy użyciu obsługiwanych języków programowania. Framework zawiera konstrukcje do pisania i uruchamiania jednostek oraz testów integracyjnych. Konstrukcji asercji można używać do pisania testów jednostkowych i potwierdzania względem wygenerowanych szablonów CloudFormation. Konstrukt CDK integ-tests może być wykorzysrywany do definiowania przypadków testowych integracji i może być łączony z CDK integ-runner do wykonywania tych testów. Integ-runner obsługuje automatyczne udostępnianie i usuwanie zasobów oraz obsługuje kilka opcji dostosowywania. Testy jednostkowe wykorzystujące funkcje asercji służą do testowania konfiguracji w szablonach CloudFormation przed wdrożeniem tych szablonów, podczas gdy testy integracyjne uruchamiają asercje we wdrożonych zasobach. Poniższy artykuł demonstruje pisanie automatycznych testów integracyjnych dla przykładowej aplikacji przy użyciu AWS CDK.

Jak pisac i wykonywac testy integracyjne dla aplikacji AWS CDK

Przykładowa aplikacja pokazana na rysunku nr 1 to przykładowa bezserwerowa aplikacja do wzbogacania danych. Dane są przetwarzane i wzbogacane w systemie w następujący sposób:

  1. Użytkownicy publikują wiadomości w temacie Amazon Simple Notification Service (Amazon SNS). Wiadomości są szyfrowane w stanie spoczynku przy użyciu klucza zarządzanego przez klienta usługi AWS Key Management Service (AWS KMS).
  2. Kolejka Amazon Simple Queue Service (Amazon SQS) jest subskrybowana do tematu Amazon SNS, do którego dostarczane są publikowane wiadomości.
  3. AWS Lambda pochłania wiadomości z kolejki Amazon SQS, dodając do wiadomości dodatkowe dane. Komunikaty, których nie można pomyślnie przetworzyć, są wysyłane do kolejki utraconych wiadomości.
  4. Pomyślnie wzbogacone wiadomości są przechowywane w tabeli Amazon DynamoDB przez funkcję Lambda.

Jak pisac i wykonywac testy integracyjne dla aplikacji AWS CDK

W tej przykładowej aplikacji twórcy użyją platformy testowania integracji AWS CDK, aby sprawdzić poprawność przetwarzania pojedynczej wiadomości, jak pokazano na rysunku nr 2. Aby uruchomić test, skonfigurują platformę testową, aby wykonać następujące kroki:

  1. Opublikuj wiadomość w temacie Amazon SNS. Poczekaj, aż aplikacja przetworzy wiadomość i zapisz ją w DynamoDB.
  2. Okresowo sprawdzaj tabelę Amazon DynamoDB i sprawdzaj, czy zapisana wiadomość została wzbogacona.

Wymagania wstępne

Poniżej przedstawiono wymagania dotyczące wdrożenia omawianego rozwiązania:

Struktura przykładowego repozytorium aplikacji AWS CDK wygląda następująco:

  • Folder /bin zawiera definicję najwyższego poziomu aplikacji AWS CDK.
  • Folder /lib zawiera definicję stosu testowanej aplikacji, która definiuje aplikację opisaną w powyższej sekcji.
  • /lib/functions zawiera kod wykonawczy funkcji Lambda.
  • /integ-tests zawiera stos testów integracyjnych, w którym definiujesz i konfigurujesz swoje przypadki testowe.

Repozytorium jest typową aplikacją AWS CDK z tą różnicą, że posiada jeden dodatkowy katalog na definicje przypadków testowych. W pozostałej części tego artykułu autorzy skupią się na definicji testu integracyjnego w pliku /integ-tests/integ.sns-sqs-ddb.ts i przeprowadzą Cię przez proces tworzenia i wykonywania testu integracyjnego.

Pisanie testów integracyjnych

Test integracyjny powinien zweryfikować oczekiwane zachowanie Twojej aplikacji AWS CDK. Możesz zdefiniować test integracyjny dla swojej aplikacji w następujący sposób:

1.Utwórz testowany stos z definicji CdkIntegTestsDemoStack i zmapuj go do aplikacji.

// CDK App for Integration Tests
const app = new cdk.App();

// Stack under test
const stackUnderTest = new CdkIntegTestsDemoStack(app, ‘IntegrationTestStack’, {
  setDestroyPolicyToAllResources: true,
  description:
    “This stack includes the application’s resources for integration testing.,
});

2.
Zdefiniuj konstrukcję testu integracyjnego z listą przypadków testowych. Ta konstrukcja oferuje możliwość dostosowania zachowania narzędzia Integration Runner. Na przykład możesz zmusić program integ-runner do zniszczenia zasobów po uruchomieniu testu, aby wymusić czyszczenie.

up.

// Initialize Integ Test construct
const integ = new IntegTest(app, ‘DataFlowTest’, {
  testCases: [stackUnderTest], // Define a list of cases for this test
  cdkCommandOptions: {
    // Customize the integ-runner parameters
    destroy: {
      args: {
        force: true,
      },
    },
  },
  regions: [stackUnderTest.region],
});

3.Dodaj asercję, aby zweryfikować wyniki testu. W tym przykładzie sprawdzasz poprawność pojedynczego przepływu wiadomości z tematu Amazon SNS do tabeli Amazon DynamoDB. Asercja publikuje obiekt wiadomości w temacie Amazon SNS przy użyciu metody AwsApiCall. W tle ta metoda wykorzystuje niestandardowy zasób CloudFormation wspierany przez Lambda do wykonania wywołania API Amazon SNS Publish z AWS SDK dla JavaScript.

/**
 * Assertion:
 * The application should handle single message and write the enriched item to the DynamoDB table.
 */
const id = 'test-id-1';
const message = 'This message should be validated';
/**
 * Publish a message to the SNS topic.
 * Note - SNS topic ARN is a member variable of the
 * application stack for testing purposes.
 */
const assertion = integ.assertions
  .awsApiCall('SNS', 'publish', {
    TopicArn: stackUnderTest.topicArn,
    Message: JSON.stringify({
      id: id,
      message: message,
    }),
  })

4.Użyj następnej metody pomocniczej, aby połączyć wywołania API. W omawianym przykładzie drugie wywołanie API Amazon DynamoDB GetItem pobiera element, którego klucz podstawowy jest równy identyfikatorowi wiadomości. Oczekuje się, że wynik drugiego wywołania interfejsu API będzie zgodny z obiektem komunikatu, w tym z dodatkowym atrybutem dodanym w wyniku wzbogacenia danych.

/**
 * Validate that the DynamoDB table contains the enriched message.
 */
  .next(
    integ.assertions
      .awsApiCall('DynamoDB', 'getItem', {
        TableName: stackUnderTest.tableName,
        Key: { id: { S: id } },
      })
      /**
       * Expect the enriched message to be returned.
       */
      .expect(
        ExpectedResult.objectLike({
          Item: { id: { S: id, },
            message: { S: message, },
            additionalAttr: { S: 'enriched', },
          },
        }),
      )

 

5. Ze względu na to, że przekazanie komunikatu przez aplikację może zająć trochę czasu, autorzy uruchamiają asercję asynchronicznie, wywołując metodę waitForAssertions. Oznacza to, że wywołanie API Amazon DynamoDB GetItem jest wywoływane w odstępach czasowych, aż do osiągnięcia oczekiwanego wyniku lub całkowitego limitu czasu.

/**
 * Timeout and interval check for assertion to be true.
 * Note - Data may take some time to arrive in DynamoDB.
 * Iteratively executes API call at specified interval.
 */
      .waitForAssertions({
        totalTimeout: Duration.seconds(25),
        interval: Duration.seconds(3),
      }),
  );

6. Metoda AwsApiCall automatycznie dodaje poprawne uprawnienia IAM dla obu wywołań API do funkcji AWS Lambda. Biorąc pod uwagę, że temat Amazon SNS przykładowej aplikacji jest zaszyfrowany przy użyciu klucza AWS KMS, do opublikowania wiadomości wymagane są dodatkowe uprawnienia.

// Add the required permissions to the api call
assertion.provider.addToRolePolicy({
  Effect: 'Allow',
  Action: [
    'kms:Encrypt',
    'kms:ReEncrypt*',
    'kms:GenerateDataKey*',
    'kms:Decrypt',
  ],
  Resource: [stackUnderTest.kmsKeyArn],
});

Przeprowadzanie testów integracyjnych

W tej sekcji autorzy pokazują, jak uruchomić test integracyjny dla wprowadzonej przykładowej aplikacji za pomocą integ-runner, aby wykonać przypadek testowy i zgłosić wyniki asercji.

npm install 

npm run build

Zainstaluj i skompiluj projekt.

npm run integ-test

Uruchom następującą komendę, aby zainicjować wykonanie przypadku testowego z listą opcji.

Opcja katalogu określa, w której lokalizacji integ-runner musi rekurencyjnie wyszukiwać pliki definicji testów. Opcja regionów równoległych umożliwia zdefiniowanie listy regionów do uruchamiania testów. Twórcy ustawili to na us-east-1 i upewnili się, że ładowanie AWS CDK zostało wcześniej wykonane w tym regionie. Opcja aktualizacji po niepowodzeniu umożliwia ponowne uruchomienie testów integracyjnych, jeśli migawka się nie powiedzie. Pełną listę dostępnych opcji można znaleźć w repozytorium integ-runner Github.

Wskazówka: jeśli chcesz zachować stosy testowe podczas programowania w celu debugowania, możesz określić opcję no-clean, aby zachować stos testowy po uruchomieniu testu.

Narzędzie integ-runner początkowo sprawdza migawki testu integracji, aby określić, czy od ostatniego wykonania zaszły jakieś zmiany. Ponieważ nie ma poprzednich migawek dla pierwszego uruchomienia, weryfikacja migawki kończy się niepowodzeniem. W rezultacie integ-runner rozpoczyna wykonywanie testów integracyjnych przy użyciu efemerycznego stosu testów i wyświetla wynik.

 

Verifying integration test snapshots...

  NEW        integ.sns-sqs-ddb 2.863s

Snapshot Results: 

Tests:    1 failed, 1 total

Running integration tests for failed tests...

Running in parallel across regions: us-east-1
Running test <your-path>/cdk-integ-tests-demo/integ-tests/integ.sns-sqs-ddb.js in us-east-1
  SUCCESS    integ.sns-sqs-ddb-DemoTest/DefaultTest 587.295s
       AssertionResultsAwsApiCallDynamoDBgetItem - success

Test Results: 

Tests:    1 passed, 1 total


Jak pisac i wykonywac testy integracyjne dla aplikacji AWS CDK

Integ-runner generuje dwa stosy AWS CloudFormation, jak pokazano na rysunku nr 3. Stos IntegrationTestStack zawiera zasoby z naszej przykładowej aplikacji, która służy jako izolowana aplikacja reprezentująca testowany stos. Stos DataFlowDefaultTestDeployAssert zawiera zasoby wymagane do wykonania testów integracji, jak pokazano na rysunku nr 4.

Jak pisac i wykonywac testy integracyjne dla aplikacji AWS CDK 4

Porządkowanie

Na podstawie określonej RemovalPolicy zasoby są automatycznie niszczone po usunięciu stosu. Niektóre zasoby, takie jak tabele Amazon DynamoDB, mają domyślną opcję RemovalPolicy ustawioną na Retain w AWS CDK. Aby ustawić zasady usuwania na Destroy dla zasobów testów integracyjnych, autorzy wykorzystują aspekty.

/**
 * Aspect for setting all removal policies to DESTROY
 */
class ApplyDestroyPolicyAspect implements cdk.IAspect {
  public visit(node: IConstruct): void {
    if (node instanceof CfnResource) {
      node.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
    }
  }
}

Jeśli ustawisz argument no-clean jako część opcji CLI integ-runner, musisz ręcznie zniszczyć stosy. Można to zrobić z konsoli AWS, za pośrednictwem AWS CloudFormation, jak pokazano na rysunku nr 5 lub za pomocą następującego polecenia.

BASH

cdk destroy --all

Aby wyczyścić pliki kompilacji repozytorium kodu, możesz uruchomić następujący skrypt.

BASH

npm run clean

Wnioski

Konstrukcja AWS CDK integ-tests jest cennym narzędziem do definiowania i przeprowadzania automatycznych testów integracyjnych dla aplikacji AWS CDK. W tym artykule autorzy przedstawili praktyczny przykład kodu pokazujący, w jaki sposób można wykorzystać testy integracji AWS CDK do sprawdzenia oczekiwanego zachowania aplikacji po wdrożeniu w chmurze. Możesz wykorzystać techniki opisane w tym przewodniku, aby napisać własne testy integracyjne AWS CDK i poprawić jakość i niezawodność wydań aplikacji.

Aby uzyskać informacje na temat rozpoczynania pracy z tymi konstrukcjami, zapoznaj się z poniższą dokumentacją.

Wezwanie do działania

Konstrukcje Integ-runner i Integ-tests są eksperymentalne i mogą ulec zmianie. Informacje o wersji dla modułów stabilnych i eksperymentalnych są dostępne w informacjach o wersji AWS CDK Github. Jak zawsze, twórcy czekają na zgłoszenia błędów, prośby o nowe funkcje i żądania ściągnięcia w repozytorium GitHub aws-cdk, aby dalej kształtować te konstrukcje alfa w oparciu o Wasze opinie.

 

Źródło: AWS

Case Studies
Referencje

Firma Hostersi pozwoliła nam osadzić ogólne zagadnienia programu Well Architected Framework w kontekście naszej firmy. Oszczędziło nam to wiele czasu i pozwoliło znaleźć lepiej dopasowane rozwiązania do specyfiki naszego biznesu. WAF był świetnym katalizatorem do wprowadzenie szeregu zmian w obszarze niezawodności, szybkości i bezpieczeństwa edrone. 

Piotr Stachowicz
CTO
W skrócie o nas
Specjalizujemy się w dostarczaniu rozwiązań IT w obszarach projektowania infrastruktury serwerowej, wdrażania chmury obliczeniowej, opieki administracyjnej i bezpieczeństwa danych.