xUnit tests not found when running in docker container - docker

I am making a Dockerfile for a dotnet core project with some xUnit tests. I want to run the unit tests when the images are being built. However when I docker build I get the following message at the test step:
No test is available in /ciad/tests/bin/Debug/netcoreapp2.1/Tests.dll. Make sure that test discoverer & executors are registered and platform & framework version settings are appropriate and try again.
Here is the Dockerfile:
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /ciad
# restore
COPY API/API.csproj ./api/
RUN dotnet restore api/API.csproj
COPY Tests/Tests.csproj ./tests/
RUN dotnet restore tests/Tests.csproj
# copy src
COPY . .
# test
RUN dotnet test tests/Tests.csproj
I'm aware that this is an incomplete dockerfile. I'm just stuck with the tests at the moment. Could anyone see what I'm missing?
Good to mention that tests run fine in VS and "dotnet test" command works too. I can also see that the Tests projects' files are copied to the container.
I run:
docker build -t testing .

I don't know what was wrong but eventually thanks to tips from omajid I changed the tests project's name and folder to tests with small t and all other capital T in Dockerfile to small t and it worked!
I hope this might help someone.
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /ciad
# restore
COPY API/API.csproj ./api/
RUN dotnet restore api/API.csproj
COPY tests/tests.csproj ./tests/
RUN dotnet restore tests/tests.csproj
# copy src
COPY . .
# test
RUN dotnet test tests/Tests.csproj

Related

Can't produce coverage in Docker container

I'm having trouble getting coverlet to run in my docker container. My problems seems similar to this issue, although the problem persists, and there are some differences.
Setup
.NET 6 tests project.
References have Microsoft.NET.Test.Sdk v17.2.0 (latest), and coverlet.collector v3.1.2 (latest)
I'm running the tests in a Dockerfile, like so:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
COPY ["src/MyAPI/", "src/MyAPI/"]
COPY ["tests/MyAPI.Handlers.Tests/", "tests/MyAPI.Handlers.Tests/"]
WORKDIR "/tests/MyAPI.Handlers.Tests"
RUN dotnet restore "MyAPI.Handlers.Tests.csproj" --configfile NuGet.config
FROM build AS publish
WORKDIR /tests/MyAPI.Handlers.Tests
RUN dotnet publish "MyAPI.Handlers.Tests.csproj" -c Release -o /tests/publish --no-restore
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS final
WORKDIR /tests
COPY --from=publish /tests/publish .
ENTRYPOINT ["dotnet", "test", "MyAPI.Handlers.Tests.dll", "--collect:\"XPlat Code Coverage\""]
So i am doing a dotnet publish, and running the tests from there. That should mean that everything is there, that needs to run the tests / coverage.
When i run, i get this error:
Data collection : Unable to find a datacollector with friendly name '"XPlat Code Coverage"'.
What i've confirmed:
Command works outside docker fine (e.g if i do a dotnet publish, then dotnet test with coverage)
I've listed the files in the directory in the container, and confirmed the coverlet DLL's are there
Any suggestions would be great! Thanks in advance :)
I tried by removing \" from argument and it worked.
ENTRYPOINT ["dotnet", "test", "MyAPI.Handlers.Tests.dll", "--collect:XPlat Code Coverage"]

How to start multiple microservices after docker build finished for .net projects?

I have a .net solution which has 2 projects, and each project is a microservice (a server). I have a dockerfile which first installs all the dependencies which are used by both projects. Then I publish the solution:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.sln .
COPY Server/*.csproj ./Server/
COPY JobRunner/*.csproj ./JobRunner/
RUN dotnet restore ./MySolution.sln
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "Server.dll"]
When the solution is published, 2 executables are available: Server.dll and JobRunner.dll. However, I can only start only one of them in Dockerfile.
This seems to be wasteful because restoring the solution is a common step for both Server and JobRunner project. In addition this line RUN dotnet publish -c Release -o out produces both an executable for Server and JobRunner. I could write a separate Dockerfile for each project but this seems redundant as 99% of the build steps for each project is identical.
Is there a way to somehow start 2 executables from a single file without using a script (I don't want that both services will be started in a single container)? The closest I've found is the --target option in docker build but it probably won't work because I'd need multiple entrypoints.
In your Dockerfile, change ENTRYPOINT to CMD in the very last line.
Once you do this, you can override the command by just providing an alternate command after the image name in the docker run command:
docker run ... my-image \
dotnet JobRunner.dll
(In principle you can do this without changing the Dockerfile, but the docker run construction is awkward, and there's no particular benefit to using ENTRYPOINT here. If you're using Docker Compose, you can override either entrypoint: or command: on a container-by-container basis.)

Is there a way to export files during a docker build?

I do a multistage build right now. The first stage compiles with credentials for my internal repos and I just keep the binaries as per this example: https://github.com/dotnet/dotnet-docker/blob/master/documentation/scenarios/nuget-credentials.md
But I want to run in CI server and need to provider the CI server with test and coverage reports. It would be most elegant to do this in the build layer but how do I get files out of a docker image during build?
For example:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj .
COPY ./nuget.config .
RUN dotnet restore
# Copy and publish app and libraries
COPY . .
############ Get this files out #####################
# Generate test report. copy this to external directory
RUN dotnet test --logger trx
# Generate coverage report. copy this to external directory
RUN dotCover.sh dotnet --output=myRep.html --reportType=HTML -- test
#######################################################
RUN dotnet publish -c Release -o out --no-restore
FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS runtime
WORKDIR /app/
COPY --from=build /app/out ./
ENTRYPOINT ["dotnet", "dotnetapp.dll"]
So I want to be able to run docker build and have it dump a test and coverage report to the current directory where docker build command was run. Is this possible? It would make this seamless for CI because all server must do is run docker build and it get reports
docker build supports an --output flag. I think it requires BuildKit (DOCKER_BUILDKIT=1). Here's one example usage.
https://docs.docker.com/engine/reference/commandline/build/ - then find --output on the page
https://docs.docker.com/engine/reference/commandline/build/#output

Unit Test Results from 'dotnet test' call in Docker

I am starting to investigate Azure Devops and its pipelines feature for setting up a continuous integration workflow. I have a pipeline that builds a Docker image of my application using the following dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build-env
WORKDIR /cicd
# restore (put more volatile, changing projects later in process)
COPY src/WebApp/WebApp.csproj ./src/WebApp/
RUN dotnet restore src/WebApp/WebApp.csproj -s http://mycontainerrepo.acme.com/repository/nuget/
COPY tests/WebApp.Test/WebApp.Test.csproj ./tests/WebApp.Test/
RUN dotnet restore tests/WebApp.Test/WebApp.Test.csproj -s http://mycontainerrepo.acme.com/repository/nuget/
# copy source
COPY . .
# test (if tests fail, no final image, yay)
RUN dotnet test tests/WebApp.Test/WebApp.Test.csproj
# publish
RUN dotnet publish src/WebApp/WebApp.csproj -o /publish
# runtime stage
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS release
COPY --from=build-env /publish /publish
WORKDIR /publish
ENTRYPOINT ["dotnet", "WebApp.dll"]
The call to run dotnet test executes just fine and outputs results to the console, but I don't know of any way to make use of this result in the pipeline. In TeamCity, you could set an environment variable to sort of trick it into outputting the test results (xUnit only, I think...). But not sure if there's a similar trick here...
I saw this post on Github about making a separate test image just for testing but was hoping to avoid that route unless its my only option.
Any other CI/CD Azure Devops gurus out there?

Run dotnet test inside docker container

I want to run the dotnet test command inside a docker container but I just cannot figure out where to put the command. The project is a .NET Core 2.1 test project. The reason for this is that I want to run end-to-end integration tests which require all my containers to be running.
DockerFile:
FROM microsoft/dotnet:2.1-runtime AS base
WORKDIR /app
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY *.sln ./
COPY Sombra.IntegrationTests/Sombra.IntegrationTests.csproj Sombra.IntegrationTests/
COPY . .
WORKDIR /src/Sombra.IntegrationTests
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "test", "Sombra.IntegrationTests.csproj"]
docker-compose.yml
version: '3'
services:
sombra.integrationtests:
image: sombra.integrationtests
build:
context: .
dockerfile: Sombra.IntegrationTests/Dockerfile
depends_on:
- rabbitmq
You're using a runtime image to invoke the sdk command test. Your final is from base and base is from runtime.
I've successfully used unit tests as intermediate step while building the container but never integration tests with docker-compose. The key difference is I used a RUN command instead of the entrypoint/cmd so the tests are already executing while building the container. The main advantage is that there is no final image when the tests fail. But then again, this were pure unit tests and no integration tests. Although I can imagine that this will also work.
Here is my full example:
FROM microsoft/dotnet:2.0-sdk AS build-env
WORKDIR /app
# copy csproj and restore as distinct layers
COPY test.sln ./test.sln
COPY program/program.csproj ./program/program.csproj
COPY program.tests/program.tests.csproj ./program.tests/program.tests.csproj
RUN dotnet restore
# copy everything else and build
COPY . ./
RUN dotnet test program.tests -c Release
RUN dotnet publish program -c Release -o /app/out
# build runtime image
FROM microsoft/dotnet:2.0-runtime
WORKDIR /app
COPY --from=build-env /app/out ./
ENTRYPOINT ["dotnet", "program.dll"]
There is a good blog about this. A guide to setting up a .NET Core project using Docker, with integrated unit and component tests
In this blog look for component tests which is equivalent to what you are trying to do.
Below dockerfile is working for me. This can be build as docker image and then can be used for running integration tests.
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY *.sln .
COPY ["Somthing.Business/Somthing.Business.csproj", "Somthing.Business/"]
COPY ["tests/Somthing.Business.IntegrationTests/Somthing.Business.IntegrationTests.csproj", "tests/Somthing.Business.IntegrationTests/"]
COPY "Directory.*.props" . # this is centralized package manager for a project
RUN dotnet restore "tests/Somthing.Business.IntegrationTests/Somthing.Business.IntegrationTests.csproj"
COPY . .
RUN dotnet build "tests/Somthing.Business.IntegrationTests/Somthing.Business.IntegrationTests.csproj"
FROM build AS testrunner
WORKDIR /src/tests/Somthing.Business.IntegrationTests
CMD ["dotnet", "test", "--no-restore"]
You don't provide us with an error log or something, but my guess is that you're trying to run dotnet test Sombra.IntegrationTests.csproj on an image that doesn't have the dotnet sdk installed (only the dotnet runtime).
The dotnet runtime is a version of dotnet core that cannot execute commands (like test and build). It can only execute dll's (hence the name "runtime").

Resources