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

Top comments (0)