Для того, чтобы запустить в пайплайне интеграционные тесты 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(){}
}
Файл 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
Джоб в конфигурации .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
# …
Top comments (0)