GitLab CI and MsBuild (with tests)

As an addendum to Jürgen Steinblock answer, I would like to suggest a simplier alternative for the test stage script:

variables:
  SOLUTION_DIR: "MySolution"
  BUILD_DIR: "Release"
  TESTER: "vstest.console.exe" # or "mstest.exe /testcontainer:"

before_script:
  - call "%VS120COMNTOOLS%\vsvars32" # import in path tools like msbuild, mstest, etc using VS script

test:
  stage: test
  script:
  - for /f %%F in ('dir /s /b %SOLUTION_DIR%\%BUILD_DIR%\*Tests.dll') do set dllPath=%%F
  - "%TESTER% %dllPath%"

This will launch testing on all test project binaries found which ends by convention with *Tests.dll in the build directory. This has the advantage of not using an intermediate file.


Since things have changed a bit since this question has been opened (and now MS supports core/linux docker deployments right in VS), I thought I'd share my solution.

# Default image is docker:stable
image: docker:stable

# Define deployment stages
stages:
  - Test
  - Build

# We use docker-in-docker (dind) for building docker images (build stage)
services:
  - docker:dind

# Run unit test on dotnet core sdk image
test:
  stage: Test
  image: mcr.microsoft.com/dotnet/core/sdk:3.1
  script:
    - dotnet restore "${CI_PROJECT_DIR}/Project.Tests/Project.Tests.csproj"
    - dotnet test "${CI_PROJECT_DIR}/Project.Tests/Project.Tests.csproj"
  tags: 
    - docker
  only:
    - master

# Only build when testing passes, build using Dockerfile/dind
build:
  stage: Build
  # Print docker instance details for logging/diagnosing
  before_script:
    - docker info
    - docker login registry.gitlab.com -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD}
  script:
    - docker build -t ${CI_REGISTRY}/${CI_PROJECT_PATH}:latest .
    - docker push ${CI_REGISTRY}/${CI_PROJECT_PATH}:latest
  after_script:
    - docker logout ${CI_REGISTRY}
  tags: 
    - docker
  only:
    - master
  when: on_success

This should run the MS Unit tests on your solution, and if the tests pass, create an image from them (provided you have a Dockerfile next to the gitlab-ci.yml file). Ignore the build stage if you're only looking to perform unit testing automatically on commits.


This is what I used eventually. It runs all the *Tests.Dll in a single run.

  dir /s /b *.Tests.dll | findstr /r bin\\Debug > testcontainers.txt
  for /f %%x in (testcontainers.txt) do set list=!list! %%x
  set list=%list:~1%
  vstest.console.exe %list%

Apparently there is no simple msbuild example but this should get you started:

variables:
  Solution: MySolution.sln

before_script:
  - "echo off"
  - 'call "%VS120COMNTOOLS%\vsvars32.bat"'
  # output environment variables (usefull for debugging, propably not what you want to do if your ci server is public)
  - echo.
  - set
  - echo.

stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
  - echo building...
  - 'msbuild.exe "%Solution%"'
  except:
  - tags

test:
  stage: test
  script:
  - echo testing...
  - 'msbuild.exe "%Solution%"'
  - dir /s /b *.Tests.dll | findstr /r Tests\\*\\bin\\ > testcontainers.txt
  - 'for /f %%f in (testcontainers.txt) do mstest.exe /testcontainer:"%%f"'
  except:
  - tags

deploy:
  stage: deploy
  script:
  - echo deploying...
  - 'msbuild.exe "%Solution%" /t:publish'
  only:
  - production

Figuring out which tests to run is a bit tricky. My convention is that every project has a folder tests in which the test projects are named after the schema MyProject.Core.Tests (for a project called MyProject.Core)

Just as a first feedback towards gitlab-ci

I like the simplicity and the source control integration. But I would like to be able to modify the script before execution (especially while changing the script) but I could imaging to rerun a specific commit and inject variables or change the script (I can do that with teamcity). Or even ignore a failed test and rerun the script again (I do that a lot with teamcity). I know gitlab-ci does not know anything about my tests I just have a command line that returns an error code.