无法在Visual Studio中关联测试用例

时间:2018-08-10 19:34:06

标签: c# visual-studio unit-testing tfs azure-devops

我在单元测试C#项目文件中有一个标准的MSTest单元测试。该项目正在运行.NET Framework 4.7.2,并安装了MSTest适配器和框架的1.3.2版本。我正在运行Visual Studio 2017 Enterprise 15.7.6,并具有一个VSTS工作区,其中包含一些随机的手动创建的测试用例。

当我在“测试资源管理器”中的单元测试上单击鼠标右键,然后选择“关联到测试用例”时,我可以输入测试用例ID,添加关联,然后单击“保存”。保存后,我在下面收到一条错误消息。

Method not found: 'System. Threading. Tasks. Task'l <Microsoft. Team foundation. Worldte mTraclcing.WebAptModels.Worldtem> Microsoft. Teamfoundation.Workltem Tracking.WebApi.Workltem Tra ckingHttpCiientBase.UpdateWorkltemAsync (Microsoft.VisuaiStudio.SeiVices.WebApi.PatchJson.JsonPatchDocu men!, lnt32, System.Nullable'1 <Boolean>, System.Nullable'1 <Boolean >, System.Nullable'1 <Boolean>, System.Object, System.Threadi ng.Cancellation Token)'.

我尝试使用不同版本的MSTest和项目文件的不同.N​​ET Framework版本来保存关联,但都没有解决该问题。我还尝试以管理员身份运行Visual Studio,但该方法无效。其他人是否遇到过此问题,或知道任何解决方法?

2 个答案:

答案 0 :(得分:0)

我使用两个VS2017版本在我的身边进行了测试,它们都运行良好。

例如,我在VSTS的一个测试计划中手动添加了一个简单的测试用例,然后使用VS2017 15.7.6在我的身边使用.net 4.7.2创建了一个简单的单元测试项目,我可以与Test关联站在我这边。

如果可能,您可以按照以下步骤在自己的身边进行测试:

(1)在其他VS机器上进行测试(相同的VS版本,但如果在同一台机器上则不在同一机器上)。

(2)清理VSTS缓存。在解决方案资源管理器窗口中清理并重建测试项目,然后再次进行测试。

(3)工具->选项->工作项,在此处选择“ Visual Studio(兼容模式)”。

(4)如果仍然没有帮助,请在VS中添加一个新的测试简单单元测试项目,删除nuget包:MSTest.TestAdapter和MSTest.TestFramework,然后向Microsoft.VisualStudio.QualityTools.UnitTestFramework添加本地引用,再次查看结果。

enter image description here

更新

我将VS2017更新到15.8.1版本,我遇到了同样的问题,该选项默认为禁用。这将是一个真实的反馈。

https://developercommunity.visualstudio.com/content/problem/309413/cannot-associate-test-case-in-visual-studio.html?childToView=311392#comment-311392

其他遇到相同问题的成员也可以投票。

答案 1 :(得分:0)

我整理起来的一种解决方法是现在在排他方法中使用而不是手动关联,即在测试方法名称中提供测试用例ID,并通过添加以下PowerShell脚本在其余的API上自动通过TAPI来更新TFS中的用例。在TFS中成功构建。

使用测试方法的完整名称空间生成每个测试的GUID,并且需要将其添加到“ /fields/Microsoft.VSTS.TCM.AutomatedTestId”

这将需要调整到您自己的TFS身份验证方法和可能的TFS版本(我正在使用2017.2)以及您需要读入的测试类型。这支​​持编码的UI和xUnit。如果您根本不使用编码用户界面,则可以删除顶部的LoadFrom。

param (
    [string]$Dll = $(throw "-path to test Dll is required.")    
)
Write-Warning "$Dll will be locked until this powershell session closes"
#Load for CodedUi Support
[Reflection.Assembly]::LoadFrom(("C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.TestTools.UITesting.dll"))
[Reflection.Assembly]::LoadFrom(("C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll"))

try {
    $tests = ([Reflection.Assembly]::LoadFrom(($Dll)).GetTypes().GetMethods() | Where-Object { $_.GetCustomAttributes($false) | Where-Object {$_.TypeId.Name -icontains 'TestMethodAttribute' -or $_.TypeId.Name -icontains 'FactAttribute' -or $_.TypeId.Name -icontains 'SkippableFactAttribute' -or $_.TypeId.Name -icontains 'TheoryAttribute'}} | ForEach-Object { @{ Class = $_.DeclaringType.Name; Name = $_.Name; FullName = $_.DeclaringType.FullName + "."  + $_.Name; }})
}
catch {

    Write-Error "Could not load or read $dll" -ErrorAction Stop
}


foreach ($test in $tests)
{
    $sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider;
    $nameHash = $sha1.ComputeHash([System.Text.Encoding]::Unicode.GetBytes($test.FullName));
    [byte[]]$toGuid = [System.Byte[]]::CreateInstance([System.Byte],16);
    [System.Array]::Copy($nameHash, $toGuid, 16);
    $guid = [guid]::new($toGuid);
    $id = ([Regex]::Match($test.Name, "(\d+)(?!.*\d)").Value)

    try {
        if ($psversiontable.PSVersion.Major -lt 6) {
            $currentGUID = (Invoke-RestMethod "http://{instance}[/{team-project}]/_apis/wit/workitems/$($id)?api-version=3.0-preview" -Method Get -UseBasicParsing -UseDefaultCredentials).Fields.'Microsoft.VSTS.TCM.AutomatedTestId'
        }
        else {
            $currentGUID = (Invoke-RestMethod "http://{instance}[/{team-project}]/_apis/wit/workitems/$($id)?api-version=3.0-preview" -Method Get -UseBasicParsing -UseDefaultCredentials -AllowUnencryptedAuthentication).Fields.'Microsoft.VSTS.TCM.AutomatedTestId'
        }
    }
    catch {
        $currentGUID = $null;
    }

    if($currentGUID -ne $guid)
    {       
        Write-Host "Updating $id."
        [array]$hash = @{
            op = "add";
            path = "/fields/Microsoft.VSTS.TCM.AutomatedTestName";
            from = $null;
            value = $test.FullName;        
        },@{
            op = "add";
            path = "/fields/Microsoft.VSTS.TCM.AutomatedTestStorage";
            from = $null;
            value = (Split-Path $DLL -leaf);
        },@{
            op = "add";
            path = "/fields/Microsoft.VSTS.TCM.AutomatedTestId";
            from = $null;
            value = $guid;
        },@{
            op = "add";
            path = "/fields/Microsoft.VSTS.TCM.AutomationStatus";
            from = $null;
            value = "Automated";
        },@{
            op = "add";
            path = "/fields/System.Reason";
            from = $null;
            value = "Completed";
        },@{
            op = "add";
            path = "/fields/System.State";
            from = $null;
            value = "Ready";
        }

        $patch = Convertto-json $hash -Compress

        write-host $test.Name
        write-host "http://{instance}[/{team-project}]/_apis/wit/workitems/$($id)?api-version=3.0-preview"
        if ($psversiontable.PSVersion.Major -lt 6) {
            $result = Invoke-RestMethod "http://{instance}[/{team-project}]/_apis/wit/workitems/$($id)?api-version=3.0-preview" -Method Patch -UseBasicParsing -UseDefaultCredentials -Body $patch -ContentType "application/json-patch+json"
        }
        else {
            $result = Invoke-RestMethod "http://{instance}[/{team-project}]/_apis/wit/workitems/$($id)?api-version=3.0-preview" -Method Patch -UseBasicParsing -UseDefaultCredentials -Body $patch -ContentType "application/json-patch+json" -AllowUnencryptedAuthentication
        }
    }
    else {
        Write-Host "No changes to $id."
    }
}