DEV Community

Danil Poletavkin
Danil Poletavkin

Posted on

Выполнение интеграционных тестов ASP.NET Core в пайплайне GitLab

Для того, чтобы запустить в пайплайне интеграционные тесты ASP.NET Core, нужно

  • Создать отдельный файл docker-compose-test.yml с конфигурацией развёртывания базы данных. Этот файл не будет использоваться при основном развёртывании, а только при выполнении тестов.
  • Запустить контейнер dotnet/sdk, связать директорию в контейнере с директорией приложения (вероятно это текущая директория), назначить в качестве рабочей директории докера workdir директорию с файлами тестов и выполнить команду dotnet test. При этом переопределить строку подключения к базе данных, так как по умолчанию используется строка подключения из файла appsettings.json
  • Выполнить команду docker-compose down

На что нужно обратить внимание:

  • В интеграционных тестах класс с методами тестов обычно наследуется от WebApplicationFactory или WebApplicationFactory, и при создании класса с тестами выполняются методы класса Startup (Program). Если классов с тестами несколько, то методы класса Startup будут выполняться каждый раз, и если в нём определены операции миграции базы данных, будет возникать ошибка. Причина ошибки в том, что каждый класс с тестами запускается как бы отдельно и «приложение не знает», какие миграции уже были применены к базе данных до этого. Получается, что все миграции применяются каждый раз. Чтобы этого избежать, можно поместить все тесты в один класс, так, чтобы создавался только один класс WebApplicationFactory и соответственно методы класса Startup выполнялись только один раз

Примеры кода

Интеграционный тест

using Microsoft.AspNetCore.Mvc.Testing;

public class IntegrationTests:IClassFixture<WebApplicationFactory<Startup>>{
    private readonly WebApplicationFactory<Startup> _fixture;
    public IntegrationTests(WebApplicationFactory<Startup> fixture)
    {
        _fixture = fixture;
    }
    [Fact]
    public void Test1(){}
    [Fact]
    public void Test2(){}
    [Fact]
    public void Test3(){}
    [Fact]
    public void Test4(){}
}
Enter fullscreen mode Exit fullscreen mode

Файл docker-compose-test.yml с образом postgres

version: '3.4'
networks: 
  network_name:
    driver: bridge
services:
  db:
   image: postgres:14
   ports:
    - "5432:5432"
   environment:
    PGUSER: postgres
    POSTGRES_PASSWORD: postgres
    POSTGRES_DB: postgres
   networks:
    - network_name
   restart: always
   healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 20s
      timeout: 10s
      retries: 3
      start_period: 10s  
Enter fullscreen mode Exit fullscreen mode

Джоб в конфигурации .gitlab-ci.yml

stages:
  - test
  - build
  - deploy

docker-test:
  image: docker:latest
  stage: test
  when: on_success
  services:
    - docker:dind
  script:
# развернуть контейнер с базой данных 
# -d - отменить вывод журнала в консоль для того, чтобы остальные команды могли выполниться
    - docker-compose --file docker-compose-test.yml up -d --build
# --name - задать имя контейнеру (необязательно)
# --network - задать имя сети, с которой будет соединяться контейнер. При развёртывании контейнера с базой данных в предыдущем шаге создаётся сеть с именем network_name. При развёртывании контейнера с базой данных к этому имени добавится имя текущей директории, из которой была выполнена команда docker-compose, так что окончательное имя сети будет не таким, как указано в файле docker-compose-test, а с префиксом из имени текущей директории и нижним подчёркиванием: [имя текущей директории]_network_name. Нужно иметь это ввиду при запуске команды.
# --rm - удалить образ, который используется при развёртывании контейнера а также удалить связанные volume
# -w - задать рабочую директорию для контейнера, то есть ту директорию, в которой будут выполняться дальнейшие команды. Это то же самое, что команда WORKDIR в файлах Dockerfile. Здесь мы в качестве рабочей директории задаём директорию Tests, так как именно в ней нужно будет выполнить команду dotnet test
# dotnet test - команда запуска тестов
# -e задать переменную текущей среды выполнения. Здесь мы задаём строку соединения с базой данных.
# в строке соединения к базе данных:
# __ - двойное подчёркивание используется вместо двоеточия :, так как двоеточие не всегда срабатывает
# Server=db - здесь db - это имя службы из участка кода
# services:
# db:
# image: postgres:14          
    - docker run --name app_name --network [имя текущей директории]_network_name --rm -v $(pwd):/app -w /app/Tests mcr.microsoft.com/dotnet/sdk:7.0 dotnet test -e "ConnectionStrings__DefaultConnection=Server=db;Port=5432;Database=postgres;Username=postgres;Password=postgres"
    - docker-compose --file docker-compose-test.yml down -v

docker-build:
  stage: build
# …
docker-deploy:
  stage: deploy
# …
Enter fullscreen mode Exit fullscreen mode

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay