如何在 VS Code 中调试 dotnet 测试?

Mat*_*t W 12 unit-testing vscode-settings dotnet-test vscode-debugger

本文介绍如何设置 VS Code 设置以将调试目标指向单元测试项目的构建输出。因此,我将我的设置如下:

{
    "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
}
Run Code Online (Sandbox Code Playgroud)

但是,我不确定如何设置launch.json以启动dotnet test它以便它可以附加调试器。

这是我目前所拥有的:

{
    "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"
        },
    ]
}
Run Code Online (Sandbox Code Playgroud)

是否可以选择告诉 VS Code 它需要执行dotnet test而不是执行dotnet run

我希望这个页面会指出如何做到这一点,但事实并非如此。

zaj*_*jer 31

所有功劳均归功于@Lance U. Matthews,他将本文作为对以下问题答案的评论发表:如何在 VSCode 中调试 MSTest?。我将其重新发布为正确答案,因为他已经一年没有这样做了。

以下答案已在 VSCode v1.62.3 和 dotnet 工具 v5.0.403 上进行了测试。

假设您有一个结构如下的 .NET 解决方案:

mysolution.sln
tests\
  |---> tests.csproj
  |---> UnitTest1.cs
.vscode\
  |---> launch.json
  |---> tasks.json
Run Code Online (Sandbox Code Playgroud)

将以下内容复制到tasks.json文件中:

mysolution.sln
tests\
  |---> tests.csproj
  |---> UnitTest1.cs
.vscode\
  |---> launch.json
  |---> tasks.json
Run Code Online (Sandbox Code Playgroud)

并将其写入launch.json文件中:

{
    // 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": [] 
        },
    ]
}
Run Code Online (Sandbox Code Playgroud)

现在在文件中的任意位置设置断点UnitTest1.cs并运行.NET Core Test with debugger任务(终端->运行任务...)。测试执行命令行工具应该启动,并且终端底部应该类似于: 在此输入图像描述Process Id肯定会有所不同,但这是预期的行为。

现在您需要切换到“运行和调试”选项卡(ctrl+shift+d)并选择“.NET Core Attach”(它应该位于 VSCode 的左上角)。提供之前在终端中出现的进程 ID: 在此输入图像描述 现在单击 F5 一次,您应该到达一个断点。

  • 进程名称将是“testhost.exe”,而不是屏幕截图中第一个突出显示的进程。对于像我这样的人来说可能并不明显 x)。此外,我还必须按“恢复执行”调试按钮才能继续加载调试符号。 (2认同)

0x4*_*B1D 6

这可能无法解决您完全传递参数的问题,但可以解决将 runsettings 参数传递给正在调试的代码的问题。使用这种方法,我可以在运行调试器时将 runsettings 的内容传递给我的代码(即当我单击方法上方的“调试测试”时):

测试方法示例

我最终做的是这样的:

首先,TestContext如果密钥在设置文件中不可用,我编写了一些代码,这些代码将从设置文件(通过)或从用户环境中读取,即:


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

Run Code Online (Sandbox Code Playgroud)

下面是实现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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我编写了一个 Powershell,它将读取我的设置文件来解析参数并将它们设置为用户环境变量,如下所示:

<# 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")
}
Run Code Online (Sandbox Code Playgroud)

因此,现在我既可以使用特定的 runsettings 文件从命令行运行代码,也可以通过运行脚本来设置环境变量进行调试。