C# 通过REST API向TFS 2018测试用例发布测试结果
目前我们正在使用mstest.exe运行自动测试,然后它将创建一个.trx结果文件。然后,我们使用tcm.exe将这些结果发布到TFS服务器上的一些测试套件/测试用例中 我们希望不再使用tcm,而是使用TFS REST API从.trx结果文件发布结果 我已经读过一些关于这方面的文章,但是没有什么是特定于使用TFS扩展客户机类的(例如C# 通过REST API向TFS 2018测试用例发布测试结果,c#,.net,rest,tfs,automated-tests,C#,.net,Rest,Tfs,Automated Tests,目前我们正在使用mstest.exe运行自动测试,然后它将创建一个.trx结果文件。然后,我们使用tcm.exe将这些结果发布到TFS服务器上的一些测试套件/测试用例中 我们希望不再使用tcm,而是使用TFS REST API从.trx结果文件发布结果 我已经读过一些关于这方面的文章,但是没有什么是特定于使用TFS扩展客户机类的(例如TestManagementHttpClient),它只列举了要使用的实际URL。它也没有给出很多关于它期望的参数的例子 Microsoft.TeamFoundat
TestManagementHttpClient
),它只列举了要使用的实际URL。它也没有给出很多关于它期望的参数的例子
Microsoft.TeamFoundation.TestManagement.WebApi名称空间有一个官方名称空间,这有点帮助,但同样没有任何示例/示例来了解每个函数需要哪些参数
由于我对testpoints/testruns的概念不太熟悉,无法操纵表示它们的类,因此,这个问题还不够详细,我无法理解如何在我的情况下应用它
我猜一个测试运行有多个测试点(每个测试用例运行一个测试点?)?在这种情况下,我应该假设我需要为每个测试结果创建一个测试点。如果是,我怎么知道该给哪个ID?上面的示例硬编码“3”作为其值
如果有人能解释上面的示例,并提供一个与我的用例相关的更好/更完整的示例(从.trx文件开始,并将这些结果发布到与某个测试套件下的链接自动化项相匹配的测试用例),帮助我理解所有内容是如何相互关联的,我将不胜感激
谢谢。因此,根据我在问题中链接的示例/示例回答我自己的问题:
TestManagementHttpClient.GetTestConfigurationsAsync()
TestManagementHttpClient.GetPointsAsync()获取该测试用例/测试配置组合的所有测试点
RunCreateModel
对象来完成的,方法是至少指定您以前获取的测试点ID。您可能还需要填写大量的参数(buildId
,isAutomated
,等等)。然后需要调用TestManagementHttpClient.CreateTestRunAsync()
来实际创建它TestManagementHttpClient.GetTestResultsAsync()
获取它们,并使用TestCaseResult.TestCase.Id
属性修改它们上的Output
属性,以了解哪个测试用例的结果。您可能还需要填写其他属性,例如状态
,等等。同样,您需要使用TestManagementHttpClient.UpdateTestResultsAsync()将这些修改推送到TFS
state=“completed”
创建一个RunUpdateModel
对象,然后调用TestManagementHttpClient.updatestrunasync()
//测试点是测试用例与测试配置的配对
让createTestRun(httpClient:TestManagementHttpClient)(testRunName:string)(teamProjectName:string)(testPlanId:int)(testSuiteId:int)(testCaseIdsAndResults:seq)(buildId:int)(cancellationToken:cancellationToken)=异步{
设testPlanIdString=testPlanId.ToString()
let plan=new ShallowReference(testPlanIdString)
让!testConfigurations=httpClient.GetTestConfigurationsAsync(teamProjectName,cancellationToken=cancellationToken)|>Async.WaitTask
让defaultTestConfiguration=testConfigurations |>Seq.find(fun c->c.IsDefault)//TODO:我们现在只使用默认配置。我们总是想要这样吗?
让rec getTestPoints(testdsandresults:(int*string)列表)(testPoints:TestPoint[])=async{
将测试和结果与
|(testId:):rest->
let!fetchedTestPoints=httpClient.GetPointsAsync(teamProjectName,testPlanId,testSuiteId,testCaseId=testId.ToString(),cancellationToken=cancellationToken)|>Async.WaitTask
让testPoint=fetchedTestPoints |>Seq.find(fun p->p.Configuration.Id=defaultTestConfiguration.Id.ToString())
让newTestPointsList=Array.append测试点[|测试点|]
return!getTestPoints rest newTestPoints列表
| _ ->
返回测试点
}
let!testPoints=getTestPoints(List.ofSeq testCaseIdsAndResults)Array.empty
让testPointIds=testPoints |>Array.map(fun p->p.Id)
让runCreateModel=new runCreateModel(name=testRunName,plan=plan,buildId=buildId,isAutomated=new Nullable(true),pointid=testpointid)
让!testRun=httpClient.CreateTestRunAsync(runCreateModel,teamProjectName,cancellationToken=cancellationToken)|>Async.WaitTask
let!emptyResults=httpClient.GetTestResultsSync(project=teamProjectName,runId=testRun.Id,Outlets=new List(),cancellationToken=cancellationToken)|>Async.Task
let rec createCaseResults(testisAndResults:(int*string)列表)(结果:TestCaseResult[])=async{
将测试和结果与
|(testId,testResult)::rest->
让casesult=emptyResults |>Seq.find(fun r->r.TestCase.Id=testId.ToString())
caseResult.State Async.Task
让runmodel=newrunupdatemodel(state=“Completed”);
let!u=httpClient.UpdateTestRunAsync(runmodel,teamProjectName,testRun.Id,cancellationTo
// A test point is a pairing of a test case with a test configuration
let createTestRun (httpClient:TestManagementHttpClient) (testRunName:string) (teamProjectName:string) (testPlanId:int) (testSuiteId:int) (testCaseIdsAndResults:seq<(int * string)>) (buildId:int) (cancellationToken:CancellationToken) = async {
let testPlanIdString = testPlanId.ToString()
let plan = new ShallowReference(testPlanIdString)
let! testConfigurations = httpClient.GetTestConfigurationsAsync(teamProjectName, cancellationToken = cancellationToken) |> Async.AwaitTask
let defaultTestConfiguration = testConfigurations |> Seq.find (fun c -> c.IsDefault) // TODO: We only use the default configuration for now. Do we always want this?
let rec getTestPoints (testIdsAndResults:(int * string) list) (testPoints:TestPoint[]) = async {
match testIdsAndResults with
| (testId, _)::rest ->
let! fetchedTestPoints = httpClient.GetPointsAsync(teamProjectName, testPlanId, testSuiteId, testCaseId = testId.ToString(), cancellationToken = cancellationToken) |> Async.AwaitTask
let testPoint = fetchedTestPoints |> Seq.find (fun p -> p.Configuration.Id = defaultTestConfiguration.Id.ToString())
let newTestPointsList = Array.append testPoints [|testPoint|]
return! getTestPoints rest newTestPointsList
| _ ->
return testPoints
}
let! testPoints = getTestPoints (List.ofSeq testCaseIdsAndResults) Array.empty
let testPointIds = testPoints |> Array.map (fun p -> p.Id)
let runCreateModel = new RunCreateModel(name = testRunName, plan = plan, buildId = buildId, isAutomated = new Nullable<bool>(true), pointIds = testPointIds)
let! testRun = httpClient.CreateTestRunAsync(runCreateModel, teamProjectName, cancellationToken = cancellationToken) |> Async.AwaitTask
let! emptyResults = httpClient.GetTestResultsAsync(project = teamProjectName, runId = testRun.Id, outcomes = new List<TestOutcome>(), cancellationToken = cancellationToken) |> Async.AwaitTask
let rec createCaseResults (testIdsAndResults:(int * string) list) (results:TestCaseResult[]) = async {
match testIdsAndResults with
| (testId, testResult)::rest ->
let caseResult = emptyResults |> Seq.find (fun r -> r.TestCase.Id = testId.ToString())
caseResult.State <- "Completed"
caseResult.Outcome <- testResult // "passed", "failed", "never run", "not applicable"
let newResultsList = Array.append results [|caseResult|]
return! createCaseResults rest newResultsList
| _ ->
return results
}
let! results = createCaseResults (List.ofSeq testCaseIdsAndResults) Array.empty
let! _ = httpClient.UpdateTestResultsAsync(results, teamProjectName, testRun.Id, cancellationToken = cancellationToken) |> Async.AwaitTask
let runmodel = new RunUpdateModel(state = "Completed");
let! _ = httpClient.UpdateTestRunAsync(runmodel, teamProjectName, testRun.Id, cancellationToken = cancellationToken) |> Async.AwaitTask
()
}