How to debug dotnet test in VS Code?
Asked Answered
H

4

26

This article describes setting the VS Code settings to point the debugging target at the build output of the unit test project. I have therefore set mine like this:

{
    "explorer.confirmDragAndDrop": false,
    "git.allowForcePush": true,
    "git.autofetch": true,
    "window.zoomLevel": 0,
    "csharp.unitTestDebuggingOptions": {
        "sourceFileMap": {
           "C:\\git\\MsTester\\bin\\Debug\\netcoreapp2.1": "C:\\git\\MsTester\\bin\\Debug\\netcoreapp2.1"
        }
    },
    "files.autoSave": "afterDelay",
    "files.exclude": {
        "**/bin": true,
        "**/node_modules": true,
        "**/obj": true
    },
    "csharpfixformat.style.spaces.insideEmptyBraces": false,
    "csharpfixformat.style.braces.allowInlines": false,
    "csharpfixformat.style.spaces.beforeParenthesis": false,
    "csharpfixformat.style.spaces.afterParenthesis": false,
    "csharp.format.enable": false,
    "extensions.ignoreRecommendations": true
}

However, I am not sure how to setup the launch.json to kick off the dotnet test so that it can attach the debugger.

This is what I've got currently:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "MsTester",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${workspaceFolder}/MsTester/bin/Debug/netcoreapp2.1/MsTester.dll",
            "windows": {
                "args": [
                    "--filter",
                    "TestCategory=lbshell",
                    "--logger",
                    "trx",
                    "--results-directory",
                    ".\\TestResults",
                    "--settings",
                    ".\\Features\\runsettings.xml"
                ],
            },
            "cwd": "${workspaceFolder}/MsTester",
            "console": "internalConsole",
            "stopAtEntry": false,
            "internalConsoleOptions": "openOnSessionStart"
        },
    ]
}

Is there an option to tell VS Code that it needs to execute dotnet test instead of dotnet run?

I was hoping this page would indicate how to do that, but it does not.

Hankypanky answered 24/5, 2019 at 9:53 Comment(1)
I've fixed my issues rolling back to 1.26.0, from 2.x; on macbook pro 2019 i9, Ventura 13.5.2 (22G91)Jakoba
T
33

All credit is due to @Lance U. Matthews as he posted this as a comment to an answer to the question: How does one debug an MSTest in VSCode? . I am reposting this as a proper answer because he hasn't done so in a year.

The following answer has been tested on VSCode v1.62.3 and dotnet tools v5.0.403.

Assuming you have a .NET solution with a structure like this:

mysolution.sln
tests\
  |---> tests.csproj
  |---> UnitTest1.cs
.vscode\
  |---> launch.json
  |---> tasks.json

Copy the following into the tasks.json file:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        { 
            "label": ".NET Core Test with debugger", 
            "type": "process", 
            "isBackground": true, 
            "command": "dotnet", 
            "args": [ "test" ], 
            "options": 
                { 
                    "cwd": "${workspaceFolder}/tests", 
                    "env": 
                    { 
                        "VSTEST_HOST_DEBUG": "1" 
                    }, 
                }, 
            "group": "test", "presentation": 
                { 
                    "echo": true,
                    "reveal": "always",
                    "focus": false,
                    "panel": "shared"
                },
            "problemMatcher": [] 
        },
    ]
}

And this into the launch.json file:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach"
        }
    ]
}

Now set a breakpoint anywhere in your UnitTest1.cs file and run .NET Core Test with debugger task (Terminal->Run task...). The Test Execution Command Line Tool should launch and at the bottom of your terminal should be something like: enter image description here Your Process Id will certainly be different but that is expected behavior.

Now you need to switch to "Run and Debug" tab (ctrl+shift+d) and select ".NET Core Attach" (it should be in the upper left part of the VSCode). Provide the process id that appeared previously in the terminal: enter image description here Now click F5 once and you should reach one of your breakpoints.

Tradescantia answered 9/12, 2021 at 1:45 Comment(3)
Great Answer! it should be documented :)Spurgeon
The process name would be testhost.exe, and not the first highlighted process in the screenshot. Might not be obvious for some like myself x). Also I had to press the "Resume Execution" debug button to continue getting the debug symbols to load.Surefooted
With prelaunchTask and "processName":"testhost.exe" in launch.json, you do not need to run task manually.Kannada
H
11

This may not answer solve your problem of passing the arguments entirely, but may solve the problem of passing runsettings parameters to the code being debugged. Using this method, I was able to pass the contents of runsettings to my code when running the debugger (i.e. when I click "Debug Test" above the method):

Test Method Example

What I ended up doing is this:

First, I wrote a bit of code that will read from the settings file (via TestContext) OR from the user environment if the key was not available in the settings file, i.e.:


[ClassInitialize]
public static void TestClassInitialize(TestContext context)
{
    v = Settings.GetSettingValueFromContextOrEnvironment("v", context);
}

Here is the implementation of GetSettingValueFromContextOrEnvironment:

/// <summary>
/// Attempts to read a setting value from the context (populated through runsettings). If the
/// key is not present in the context, the value will be read from the user environment variable
/// instead.
/// 
/// This allows running the unit test code in VSCode debugger that currently doesn't seem to allow
/// passing runsettings file to the DLL.
/// </summary>
/// <param name="name"></param>
/// <param name="context"></param>
/// <returns></returns>
public static String GetSettingValueFromContextOrEnvironment(string name, TestContext context){
    if (context.Properties.ContainsKey(name)){
        return context.Properties[name].ToString();
    } else {
        String envVar = Environment.GetEnvironmentVariable(name, System.EnvironmentVariableTarget.User);

        if (envVar == null){
            throw new Exception(String.Format("Environment variable '{0}' was not available neither in the context file nor in the environment.", name));
        } else {
            return envVar;
        }
    }
}

I then wrote a Powershell that will read my settings file to parse parameters and set them as user environment variables, like this:

<# This script updates user environment variables with parameters stored in *.runsettings file that is provided to it as the only argument on the command line.

Example usage:
    .\set_settings_env.ps1 local.runsettings
#>

param (
    [Parameter(Mandatory=$true)][string]$settings_file
)


[xml]$xml = Get-Content $settings_file
foreach( $parameter in $xml.RunSettings.TestRunParameters.Parameter) 
{
    write-host("Setting environment variable: " + $parameter.name)
    [Environment]::SetEnvironmentVariable($parameter.name, $parameter.value, "User")
}

So now I am able to both run the code from command line with a specific runsettings file and debug by running the script to set my environment variables.

Herrmann answered 9/7, 2019 at 14:7 Comment(4)
Are you launching your program with F5 in Visual Studio Code?Hankypanky
No, I use "Run Test" option that appears above my unit test name (see the screenshot in my answer)Herrmann
So, not VS Code?Hankypanky
@MattW, it is in VS code. That's an option I see in VS Code in mstest project, here is a better screenshot: imgur.com/a/rg8xx9eHerrmann
W
1

Perhaps this is more what you are looking for: How does one debug an MSTest in VSCode?

(also check the comment). So by using "VSTEST_HOST_DEBUG": "1" you should be able to attach a debug process, similar to how one can do it in Java.

Weigle answered 20/8, 2020 at 8:26 Comment(0)
U
1

An update I was able to get working on VSCode 1.87.2 (WIndows 11) that extends this answer.

TL;DR

Update the tasks.json file entry to:

{
    "label": "dotnet-test-with-debugger", 
    "type": "process", 
    "isBackground": true, 
    "command": "dotnet", 
    "args": [ "test" ], 
    "options": { 
        "cwd": "${workspaceFolder}/tests", 
        "env": 
        { 
            "VSTEST_HOST_DEBUG": "1" 
        }, 
    }, 
    "group": "test", 
    "presentation": { 
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "shared"
    },
    "problemMatcher": {
        "owner": "custom",
        "pattern": {
            "regexp": "__________________"
        },
        "background": {
            "activeOnStart": true,
            "beginsPattern": ".*",
            "endsPattern": "Process Id:.*, Name: testhost"
        }
    }
},

Update the launch.json file entry to:

{
    "name": ".NET Core Attach",
    "type": "coreclr",
    "request": "attach",
    "preLaunchTask": "dotnet-test-with-debugger",
    "processName": "testhost.exe"
}

Changelog

  1. Changed the task label to dotnet-test-with-debugger. The spaces in the previous version were causing issues.
  2. Change the task problemMatcher to use background process pattern matching. With the previous value of [] I would get the error below. Further research, especially VSCode issue 6209, suggests there has been and will be a lot of movement in this space. Task cannot be tracked error
  3. Update the launch config entry to include a preLaunchTask matching the label of the task and set the processName to testhost.exe

Expected Results

If it's all working properly, you should be able to launch the .NET Core Attach configuration and attach to testhost.exe with a single click/command.

Utopia answered 4/4 at 16:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.