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

3
我在一个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和不同的.NET框架版本来保存关联,但都没有解决问题。我也尝试以管理员身份运行Visual Studio,但也没有起作用。有其他人遇到过这个问题或者知道任何解决方法吗?


看起来是 Visual Studio 的问题。你尝试过修复安装吗? - Daniel Mann
很遗憾,修复安装并没有解决这个问题。我将尝试运行旧版本的VS2017企业版,15.6.7。我已经向微软提交了一个案例,在那里至少有一个人能够在15.7.6上重现这个问题,并且能够通过降级到15.7.5来解决它。 - srbrills
自从更新到VS 2017 15.8.0之后,错误消息不再显示。相反,在测试资源管理器中右键单击一个测试时,“关联测试用例”将被禁用。 - srbrills
我还在MS社区上有一个正在进行的帖子,链接如下: https://developercommunity.visualstudio.com/content/problem/309413/cannot-associate-test-case-in-visual-studio.html?childToView=311392#comment-311392 - srbrills
刚刚确认在版本15.8.0和15.8.1之间的行为是相同的。 - srbrills
这个问题在VS2017版本15.8.2中仍然存在。 - srbrills
2个回答

0

我在我的电脑上使用了两个VS2017版本进行测试,它们都能正常工作。

例如,在VSTS中的一个测试计划中手动添加了一个简单的测试用例,然后我在我的电脑上使用VS2017 15.7.6创建了一个带有.net 4.7.2的简单单元测试项目,我可以将其与我的测试用例关联起来。

如果可能的话,您可以按照以下步骤在您的电脑上进行测试:

(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

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


自从安装了15.8.0更新后,所有测试的“关联到测试用例”按钮都变灰了。目前测试项目已安装v1.3.2的测试包。我尝试在其他机器上进行测试,使用旧版和新版VS2017均无法解决问题。进行清理>重建也无效。在兼容模式下运行工作项浏览器也无效。 - srbrills
当我移除了MSTest NuGet包并添加了对QualityTools.UnitTestFramework程序集的直接本地引用后,“关联到测试用例”选项不再是灰色的,但我仍然收到了原始帖子中的错误消息。建议的四个步骤都没有解决这个问题。 - srbrills
@srsedate,最新版本确实存在这个问题,“关联到测试用例”对于所有测试都是灰色的,我已经从您在开发者社区网站上的反馈中向产品团队报告了此问题。但是,如果我删除包并引用QualityTools.UnitTestFramework程序集,则在我的端上它可以正常工作。您是否在VS机器上安装了MTM?或者您可以将新的测试用例添加到新的测试计划中,然后再次查看结果。其他成员提供了其他解决方法,例如使用Rest API:https://stackoverflow.com/questions/44581836/how-do-i-associate-test-methods-to-test-cases - Jack Zhai
测试项目是使用.NET Framework的普通单元测试项目模板创建的。我们的VSTS身份验证是使用AAD进行管理的。无论测试用例是否为空,以及测试计划中有多少个测试用例,都会出现相同的行为。我们在6台以上的机器上观察到相同的行为。 - srbrills
1
@srsedate,最新消息:由于该功能尚未完全准备好,MsTestV2测试用例关联已在15.8.x中被禁用。它将在15.9预览2中启用。 - Jack Zhai
显示剩余3条评论

0
我提供了一个解决方法,现在我专门使用它来代替手动关联。方法是在测试方法名称中提供测试用例ID,并通过添加以下PowerShell脚本自动更新TFS中的用例来使用rest API在TFS中成功构建运行。
每个测试的GUID都是使用测试方法的完整命名空间生成的,并需要添加到“/fields/Microsoft.VSTS.TCM.AutomatedTestId”。
这需要根据您自己的TFS身份验证方法和可能的TFS版本(我正在使用2017.2)以及您需要读取的测试类型进行调整。这支持Coded UI和xUnit。如果您根本不使用Coded UI,则可以删除顶部的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."
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接