Другое

Полное руководство по тестированию конвейеров CDK

Узнайте, как реализовать комплексные стратегии тестирования для конвейеров AWS CDK с приложениями .NET. Изучите лучшие практики тестирования Docker-ресурсов, подходы к интеграционному тестированию и сканирование безопасности в вашем CI/CD конвейере.

Как запускать тесты с помощью AWS CDK pipelines?

Мы создаем и развертываем несколько систем с использованием AWS CDK Pipeline, в основном с приложениями .NET. В большинстве случаев мы создаем развертываемые приложения с использованием Dockerfile assets, на которые ссылается CDK.

Какой лучший подход для запуска тестов в данном контексте?

  • Следует ли запускать тесты внутри Dockerfile, вместе с кодом?
  • Или следует запускать их как отдельный пользовательский шаг перед созданием самих assets?
  • Существуют ли другие стратегии тестирования, которые следует рассмотреть для CDK pipelines?

Чтобы эффективно запускать тесты с конвейерами AWS CDK для приложений .NET с использованием Docker-ресурсов, обычно следует выполнять тесты как отдельные этапы конвейера перед сборкой ресурсов, а также учитывать стратегии сканирования безопасности и интеграционного тестирования. Оптимальный подход сочетает несколько методов тестирования на разных этапах конвейера для обеспечения всестороннего покрытия.

Содержание

Тестирование внутри Dockerfile vs. Отдельные шаги конвейера

Тестирование внутри Dockerfile

Запуск тестов внутри Dockerfile вместе с кодом — распространенный подход, особенно для модульных тестов. Этот метод включает добавление команд тестирования непосредственно в ваш Dockerfile, обычно в настройке многоэтапной сборки:

dockerfile
# Пример многоэтапного Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet build --no-restore

# Запуск тестов на этапе сборки
RUN dotnet test --no-build --no-restore --verbosity normal

FROM build AS publish
RUN dotnet publish -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "your-app.dll"]

Преимущества:

  • Тесты запускаются в той же среде, что и приложение
  • Обеспечивает корректную работу зависимостей в контейнерной среде
  • Упрощает конвейер, уменьшая количество отдельных шагов

Недостатки:

  • Замедляет процесс сборки Docker
  • Сбой тестов полностью предотвращает создание образа
  • Меньше гибкости в конфигурации тестов и параллельном выполнении

Отдельные шаги тестирования

Для более всестороннего тестирования следует выполнять тесты как отдельные пользовательские шаги перед сборкой ресурсов. Согласно лучшим практикам AWS CDK, можно использовать действия addPre и addPost для правильного позиционирования тестов в этапах конвейера:

typescript
// Пример добавления этапа тестирования перед развертыванием
const testStage = new pipelines.Stage(this, 'TestStage', {
  stageName: 'Test',
  env: testEnv,
});

// Добавление действий тестирования перед развертыванием
testStage.addPre(new pipelines.ShellStep('RunUnitTests', {
  commands: ['dotnet test'],
  env: {
    DOTNET_ENVIRONMENT: 'Testing'
  }
}));

// Добавление интеграционных тестов после развертывания
testStage.addPost(new pipelines.ShellStep('RunIntegrationTests', {
  commands: ['dotnet integration-test'],
  env: {
    SERVICE_ENDPOINT: cdk.Fn.importValue('ServiceEndpoint')
  }
}));

Преимущества:

  • Более быстрая обратная связь за счет параллельного выполнения тестов
  • Точный контроль над средами и конфигурациями тестирования
  • Возможность запускать разные типы тестов на соответствующих этапах
  • Лучшее разделение обязанностей в процессе CI/CD

Рекомендуемая стратегия тестирования для CDK-конвейеров

На основе результатов исследования, комплексная стратегия тестирования для CDK-конвейеров должна следовать подходу тестовой пирамиды:

  1. Модульные тесты (Быстрые, многочисленные) - Запускать как можно раньше в конвейере
  2. Интеграционные тесты (Средняя скорость, меньше) - Запускать после развертывания в тестовые среды
  3. Системные/Сквозные тесты (Медленные, немного) - Запускать перед развертыванием в продакшн

Из документации CDK Pipelines, конвейер автоматически обрабатывает процесс сборки и развертывания, и вы можете вставлять шаги тестирования в соответствующие точки.

Пример структуры конвейера:

ИсточникСборка модульных тестовСборка DockerСканирование безопасностиРазвертывание в стейджингИнтеграционные тестыРазвертывание в продакшн

Как отмечено в блоге AWS Developer Tools, вы можете подключать выходные данные стека в ваши тесты для включения интеграционного тестирования против развернутых ресурсов.

Подходы к интеграционному тестированию

Интеграционное тестирование в CDK-конвейерах представляет уникальные проблемы, поскольку тестам нужен доступ к развернутым ресурсам AWS. Вот эффективные подходы:

1. Тестирование на основе стека

Создайте отдельные стеки CDK специально для целей тестирования. Как предложено в ответе на Stack Overflow, вы можете “написать небольшие приложения CDK в качестве интеграционных тестов и сравнить результат cdk synth с файлом ожидания, проверенным в системе контроля версий.”

2. Тестирование конечных точек сервисов

Для сервисов с HTTP-конечными точками вы можете получить URL-адрес конечной точки из выходных данных CloudFormation и использовать его в ваших тестах:

typescript
// В вашем стеке конвейера
const serviceOutput = new cdk.CfnOutput(this, 'ServiceEndpoint', {
  value: serviceService.url,
  exportName: 'ServiceEndpoint'
});

// В вашем шаге тестирования
const testStep = new pipelines.ShellStep('RunIntegrationTests', {
  commands: [
    'echo "Тестируем конечную точку: $SERVICE_ENDPOINT"',
    'curl -f $SERVICE_ENDPOINT/health',
    'dotnet integration-test --endpoint=$SERVICE_ENDPOINT'
  ],
  env: {
    SERVICE_ENDPOINT: cdk.Fn.importValue('ServiceEndpoint')
  }
});

Как упоминается в статье AWS, этот подход позволяет интеграционным тестам получать доступ к реальному развернутому сервису.

3. Шаблон Test Containers

Для приложений .NET рассмотрите использование TestContainers для запуска интеграционных тестов с реальными зависимостями. Как отмечено в статье на Medium, вам нужно тщательно обрабатывать сценарии Docker-in-Docker:

csharp
// Пример использования TestContainers в .NET
[Test]
public async Task TestContainerIntegration()
{
    await using var container = new ContainerBuilder()
        .WithImage("your-app:latest")
        .WithPortBinding(8080, true)
        .Build();
    
    await container.StartAsync();
    
    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync("http://localhost:8080/health");
    response.EnsureSuccessStatusCode();
}

Не забудьте правильно настроить переменные окружения Docker для вложенных сценариев Docker.

Тестирование безопасности и уязвимостей

Тестирование безопасности должно быть неотъемлемой частью вашего CDK-конвейера. Из эталонной архитектуры, вы можете использовать такие инструменты, как Trivy для сканирования ваших Docker-образов и исходного кода:

typescript
// Добавление сканирования безопасности в ваш конвейер
const securityScan = new pipelines.CodeBuildStep('SecurityScan', {
  commands: [
    'trivy image --exit-code 1 --severity CRITICAL,HIGH your-app:latest',
    'trivy config --exit-code 1 Dockerfile',
    'trivy fs --exit-code 1 --severity CRITICAL,HIGH .'
  ],
  env: {
    # Переменные окружения, связанные с Docker, для вложенных сценариев Docker
    DOCKER_HOST: 'unix:///var/run/docker.sock',
    DOCKER_TLS_VERIFY: '',
    DOCKER_CERT_PATH: ''
  }
});

Этот подход сканирует:

  • Уязвимости в зависимостях
  • Проблемы конфигурации Dockerfile
  • Ошибки безопасности в исходном коде

Лучшие практики и примеры реализации

Реализация тестовой пирамиды

Следуя фреймворку тестовой пирамиды, структурируйте этапы вашего конвейера соответственно:

  1. Модульные тесты - Быстрое выполнение, запуск при каждом коммите
  2. Интеграционные тесты - Среднее время выполнения, запуск после успешной сборки
  3. Системные тесты - Медленное выполнение, запуск перед развертыванием

Конфигурация этапов конвейера

Согласно лучшим практикам AWS, вы должны:

typescript
const pipeline = new pipelines.CodePipeline(this, 'Pipeline', {
  synth: new pipelines.ShellStep('Synth', {
    input: pipelines.CodePipelineSource.gitHub('owner/repo', 'main'),
    commands: ['npm install', 'npm run build']
  }),
  cliCommandOptions: {
    requireApproval: pipelines.ApprovalLevel.MANUAL,
    env: {
      CDK_DEFAULT_REGION: 'us-east-1',
      CDK_DEFAULT_ACCOUNT: process.env.CDK_DEFAULT_ACCOUNT
    }
  }
});

// Добавление этапов тестирования
const devStage = pipeline.addStage(new DevStage(this, 'Dev'));
const testStage = pipeline.addStage(new TestStage(this, 'Test'));
const prodStage = pipeline.addStage(new ProdStage(this, 'Prod'));

// Добавление ручного утверждения между этапами
prodStage.addPre(new pipelines.ManualApprovalStep('ProductionApproval'));

Стратегия тестирования Docker-ресурсов

Для приложений .NET с Docker-ресурсами рекомендуемый подход сочетает оба метода:

dockerfile
# Dockerfile с оптимизированным тестированием
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS base
WORKDIR /app

FROM base AS test
COPY . .
RUN dotnet restore
RUN dotnet build --no-restore
# Запуск только критических тестов быстро
RUN dotnet test --no-build --no-restore --filter "Category=Quick" --verbosity normal

FROM base AS publish
COPY . .
RUN dotnet publish -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "your-app.dll"]

Затем в вашем CDK-конвейере:

typescript
// Конвейер с комплексным тестированием
pipeline.addStage(new pipelines.Stage(this, 'TestStage', {
  stageName: 'Test',
  env: testEnv,
  post: [
    // Запуск полного набора тестов после развертывания
    new pipelines.ShellStep('RunFullTestSuite', {
      commands: ['dotnet test'],
      env: {
        # Переменные окружения для интеграционного тестирования
        ASPNETCORE_ENVIRONMENT: 'Testing',
        # Строки подключения к базе данных для интеграционных тестов
        # Строки подключения извлекаются из AWS Secrets Manager или SSM
      }
    })
  ]
}));

Заключение и рекомендации

На основе результатов исследования, вот ключевые рекомендации по запуску тестов с AWS CDK-конвейерами:

  1. Используйте комбинацию подходов к тестированию: Запускайте модульные тесты внутри Dockerfile для быстрой обратной связи, но реализуйте отдельные этапы конвейера для комплексного тестирования, включая интеграционные тесты и сканирование безопасности.

  2. Структурируйте ваш конвейер с учетом тестовой пирамиды: Начинайте с быстрых модульных тестов, переходите к интеграционным тестам средней скорости и завершайте медленными системными тестами перед развертыванием в продакшн.

  3. Используйте возможности CDK-конвейера: Используйте действия addPre и addPost для правильного позиционирования тестов и используйте выходные данные CloudFormation для включения интеграционного тестирования против развернутых ресурсов.

  4. Реализуйте сканирование безопасности: Включите инструменты, такие как Trivy, для сканирования Docker-образов и исходного кода на наличие уязвимостей в вашем конвейере.

  5. Учитывайте особенности .NET: Для приложений .NET рассмотрите использование TestContainers для интеграционного тестирования и обеспечьте правильную конфигурацию Docker-окружения для вложенных сценариев Docker.

  6. Следуйте лучшим практикам AWS: Как рекомендуется в документации AWS CDK, поддерживайте отдельные стратегии тестирования для разделяемых конструкций и убедитесь, что ваш конвейер поддерживает полный жизненный цикл разработки.

Оптимальный подход балансирует скорость, надежность и комплексное покрытие, обеспечивая тщательное тестирование ваших приложений .NET, развертываемых через CDK-конвейеры, на каждом этапе процесса развертывания.

Источники

  1. Best practices for developing and deploying cloud infrastructure with the AWS CDK - AWS Cloud Development Kit (AWS CDK) v2
  2. Continuous integration and delivery (CI/CD) using CDK Pipelines - AWS Cloud Development Kit (AWS CDK) v2
  3. How to run tests with CDK pipelines - Stack Overflow
  4. How do you add a testing stage to a CodePipeline in AWS CDK? - Stack Overflow
  5. Create a CI/CD pipeline for .NET Lambda functions with AWS CDK Pipelines | AWS DevOps & Developer Productivity Blog
  6. CDK Pipelines: Continuous delivery for AWS CDK applications | AWS Developer Tools Blog
  7. AWS CDK Pipelines - Deployment Pipeline Reference Architecture
  8. AWS CDK Pipelines: Real-World Tips and Tricks — Part 1 | Medium
  9. Testing in Your CI/CD Pipeline | Testkube
  10. AWS CI/CD Pipeline: Tutorial & Best Practices
Авторы
Проверено модерацией
Модерация