private static async Task AttachReportToBuildTestRunAsync(string collectionUri, string teamProjectName, string releaseUri, string releaseEnvironmentUri, string reportFile, string personalAccessToken) { var connection = GetConnection(collectionUri, personalAccessToken); var testManagementClient = connection.GetClient <TestManagementHttpClient>(); var projectClient = connection.GetClient <ProjectHttpClient>(); Console.WriteLine("Attaching Report"); var queryModel = new QueryModel(query: "SELECT * FROM TestRun WHERE ReleaseUri = '" + releaseUri + "' and ReleaseEnvironmentUri in ('" + releaseEnvironmentUri + "')"); var testRunResult = await testManagementClient.GetTestRunsByQueryAsync(queryModel, teamProjectName); TestRun testRun; if (testRunResult == null || testRunResult.Count == 0) { var runCreateModel = new RunCreateModel("OWASP ZAP Security Tests", isAutomated: true, releaseUri: releaseUri, releaseEnvironmentUri: releaseEnvironmentUri); var project = await projectClient.GetProject(teamProjectName); string projectId = project.Id.ToString(); testRun = await testManagementClient.CreateTestRunAsync(projectId, runCreateModel); } else { testRun = testRunResult.FirstOrDefault(); } string stream = File.ReadAllText(reportFile); var attachmentModel = new TestAttachmentRequestModel(stream: Base64Encode(stream), fileName: "OwaspZapTestResultsReport.html"); var testAttachmentResult = await testManagementClient.CreateTestRunAttachmentAsync(attachmentModel, teamProjectName, testRun.Id); }
public async Task <TestAttachmentReference> CreateTestRunAttachmentAsync( TestAttachmentRequestModel reqModel, string projectName, int testRunId, CancellationToken cancellationToken = default(CancellationToken)) { return(await TestHttpClient.CreateTestRunAttachmentAsync(reqModel, projectName, testRunId, cancellationToken)); }
private async Task UploadTestSubResultsAttachmentAsync(int testRunId, int testResultId, TestCaseSubResultData subResultData, TestSubResult subresult, int level, CancellationToken cancellationToken) { if (level > TestManagementConstants.maxHierarchyLevelForSubresults || subresult == null || subResultData == null || subResultData.AttachmentData == null) { return; } string[] attachments = subResultData.AttachmentData.AttachmentsFilePathList?.ToArray(); // remove duplicate entries HashSet <string> attachedFiles = GetUniqueTestRunFiles(attachments); if (attachedFiles != null && attachedFiles.Any()) { var createAttachmentsTasks = attachedFiles .Select(async attachment => { TestAttachmentRequestModel reqModel = GetAttachmentRequestModel(attachment); if (reqModel != null) { await _testResultsServer.CreateTestSubResultAttachmentAsync(reqModel, _projectName, testRunId, testResultId, subresult.Id, cancellationToken); } }); await Task.WhenAll(createAttachmentsTasks); } // Upload console log as attachment string consoleLog = subResultData.AttachmentData.ConsoleLog; TestAttachmentRequestModel attachmentRequestModel = GetConsoleLogAttachmentRequestModel(consoleLog); if (attachmentRequestModel != null) { await _testResultsServer.CreateTestSubResultAttachmentAsync(attachmentRequestModel, _projectName, testRunId, testResultId, subresult.Id, cancellationToken); } // Upload standard error as attachment string standardError = subResultData.AttachmentData.StandardError; TestAttachmentRequestModel stdErrAttachmentRequestModel = GetStandardErrorAttachmentRequestModel(standardError); if (stdErrAttachmentRequestModel != null) { await _testResultsServer.CreateTestSubResultAttachmentAsync(stdErrAttachmentRequestModel, _projectName, testRunId, testResultId, subresult.Id, cancellationToken); } if (subResultData.SubResultData != null) { for (int i = 0; i < subResultData.SubResultData.Count; ++i) { await UploadTestSubResultsAttachmentAsync(testRunId, testResultId, subResultData.SubResultData[i], subresult.SubResults[i], level + 1, cancellationToken); } } }
private async Task UploadTestResultsAttachmentAsync(int testRunId, TestCaseResultData testCaseResultData, TestCaseResult testCaseResult, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (testCaseResult == null || testCaseResultData == null) { return; } if (testCaseResultData.AttachmentData != null) { // Remove duplicate entries string[] attachments = testCaseResultData.AttachmentData.AttachmentsFilePathList?.ToArray(); HashSet <string> attachedFiles = GetUniqueTestRunFiles(attachments); if (attachedFiles != null && attachedFiles.Any()) { var createAttachmentsTasks = attachedFiles.Select(async attachment => { TestAttachmentRequestModel reqModel = GetAttachmentRequestModel(attachment); if (reqModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(reqModel, _projectName, testRunId, testCaseResult.Id, cancellationToken); } }); await Task.WhenAll(createAttachmentsTasks); } // Upload console log as attachment string consoleLog = testCaseResultData?.AttachmentData.ConsoleLog; TestAttachmentRequestModel attachmentRequestModel = GetConsoleLogAttachmentRequestModel(consoleLog); if (attachmentRequestModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(attachmentRequestModel, _projectName, testRunId, testCaseResult.Id, cancellationToken); } // Upload standard error as attachment string standardError = testCaseResultData.AttachmentData.StandardError; TestAttachmentRequestModel stdErrAttachmentRequestModel = GetStandardErrorAttachmentRequestModel(standardError); if (stdErrAttachmentRequestModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(stdErrAttachmentRequestModel, _projectName, testRunId, testCaseResult.Id, cancellationToken); } } if (testCaseResult.SubResults != null && testCaseResult.SubResults.Any() && testCaseResultData.TestCaseSubResultData != null) { for (int i = 0; i < testCaseResultData.TestCaseSubResultData.Count; i++) { await UploadTestSubResultsAttachmentAsync(testRunId, testCaseResult.Id, testCaseResultData.TestCaseSubResultData[i], testCaseResult.SubResults[i], 1, cancellationToken); } } }
/// <summary> /// Publishes the given results to the test run. /// </summary> /// <param name="testResults">Results to be published.</param> public async Task AddResultsAsync(TestRun testRun, TestCaseResultData[] testResults, CancellationToken cancellationToken) { Trace.Entering(); int noOfResultsToBePublished = BATCH_SIZE; _executionContext.Output(StringUtil.Loc("PublishingTestResults", testRun.Id)); for (int i = 0; i < testResults.Length; i += BATCH_SIZE) { cancellationToken.ThrowIfCancellationRequested(); if (i + BATCH_SIZE >= testResults.Length) { noOfResultsToBePublished = testResults.Length - i; } _executionContext.Output(StringUtil.Loc("TestResultsRemaining", (testResults.Length - i), testRun.Id)); var currentBatch = new TestCaseResultData[noOfResultsToBePublished]; Array.Copy(testResults, i, currentBatch, 0, noOfResultsToBePublished); List <TestCaseResult> testresults = await _testResultsServer.AddTestResultsToTestRunAsync(currentBatch, _projectName, testRun.Id, cancellationToken); for (int j = 0; j < noOfResultsToBePublished; j++) { cancellationToken.ThrowIfCancellationRequested(); // Do not upload duplicate entries string[] attachments = testResults[i + j].Attachments; if (attachments != null) { Hashtable attachedFiles = new Hashtable(StringComparer.CurrentCultureIgnoreCase); var createAttachmentsTasks = attachments.Select(async attachment => { if (!attachedFiles.ContainsKey(attachment)) { TestAttachmentRequestModel reqModel = GetAttachmentRequestModel(attachment); if (reqModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(reqModel, _projectName, testRun.Id, testresults[j].Id, cancellationToken); } attachedFiles.Add(attachment, null); } }); await Task.WhenAll(createAttachmentsTasks); } // Upload console log as attachment string consoleLog = testResults[i + j].ConsoleLog; TestAttachmentRequestModel attachmentRequestModel = GetConsoleLogAttachmentRequestModel(consoleLog); if (attachmentRequestModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(attachmentRequestModel, _projectName, testRun.Id, testresults[j].Id, cancellationToken); } } } Trace.Leaving(); }
private void ResetValues() { _runId = 0; _projectId = ""; _attachmentRequestModel = null; _resultCreateModels = null; _resultsLevelAttachments = new Dictionary <int, List <TestAttachmentRequestModel> >(); _updateProperties = null; _batchSizes = new List <int>(); }
private async Task CreateTestRunAttachmentAsync(int testRunId, string zipFile, CancellationToken cancellationToken) { Trace.Entering(); TestAttachmentRequestModel reqModel = GetAttachmentRequestModel(zipFile); if (reqModel != null) { await _testResultsServer.CreateTestRunAttachmentAsync(reqModel, _projectName, testRunId, cancellationToken); } }
public TestRunPublisherTests() { _attachmentFilePath = "attachment.txt"; File.WriteAllText(_attachmentFilePath, "asdf"); _testRunContext = new TestRunContext("owner", "platform", "config", 1, "builduri", "releaseuri", "releaseenvuri"); _reader = new Mock <IResultReader>(); _reader.Setup(x => x.ReadResults(It.IsAny <IExecutionContext>(), It.IsAny <string>(), It.IsAny <TestRunContext>())) .Callback <IExecutionContext, string, TestRunContext> ((executionContext, filePath, runContext) => { _runContext = runContext; _resultsFilepath = filePath; }) .Returns((IExecutionContext executionContext, string filePath, TestRunContext runContext) => { TestRunData trd = new TestRunData( name: "xyz", buildId: runContext.BuildId, completedDate: "", state: "InProgress", isAutomated: true, dueDate: "", type: "", buildFlavor: runContext.Configuration, buildPlatform: runContext.Platform, releaseUri: runContext.ReleaseUri, releaseEnvironmentUri: runContext.ReleaseEnvironmentUri ); trd.Attachments = new string[] { "attachment.txt" }; return(trd); }); _testResultServer = new Mock <ITestResultsServer>(); _testResultServer.Setup(x => x.InitializeServer(It.IsAny <VssConnection>(), It.IsAny <IExecutionContext>())); _testResultServer.Setup(x => x.AddTestResultsToTestRunAsync(It.IsAny <TestCaseResult[]>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <CancellationToken>())) .Callback <TestCaseResult[], string, int, CancellationToken> ((currentBatch, projectName, testRunId, cancellationToken) => { _batchSizes.Add(currentBatch.Length); _resultCreateModels = currentBatch; }) .Returns(() => { List <TestCaseResult> resultsList = new List <TestCaseResult>(); int i = 0; int j = 1; foreach (TestCaseResult resultCreateModel in _resultCreateModels) { List <TestSubResult> SubResults = null; if (resultCreateModel.SubResults != null) { SubResults = new List <TestSubResult>(); foreach (var subresultdata in resultCreateModel.SubResults) { var subResult = new TestSubResult(); subResult.Id = j++; SubResults.Add(subResult); } } resultsList.Add(new TestCaseResult() { Id = ++i, SubResults = SubResults }); } return(Task.FromResult(resultsList)); }); _testResultServer.Setup(x => x.CreateTestRunAsync(It.IsAny <string>(), It.IsAny <RunCreateModel>(), It.IsAny <CancellationToken>())) .Callback <string, RunCreateModel, CancellationToken> ((projectName, testRunData, cancellationToken) => { _projectId = projectName; _testRun = (TestRunData)testRunData; }) .Returns(Task.FromResult(new TestRun() { Name = "TestRun", Id = 1 })); _testResultServer.Setup(x => x.UpdateTestRunAsync(It.IsAny <string>(), It.IsAny <int>(), It.IsAny <RunUpdateModel>(), It.IsAny <CancellationToken>())) .Callback <string, int, RunUpdateModel, CancellationToken> ((projectName, testRunId, updateModel, cancellationToken) => { _runId = testRunId; _projectId = projectName; _updateProperties = updateModel; }) .Returns(Task.FromResult(new TestRun() { Name = "TestRun", Id = 1 })); _testResultServer.Setup(x => x.CreateTestRunAttachmentAsync( It.IsAny <TestAttachmentRequestModel>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <CancellationToken>())) .Callback <TestAttachmentRequestModel, string, int, CancellationToken> ((reqModel, projectName, testRunId, cancellationToken) => { _attachmentRequestModel = reqModel; _projectId = projectName; _runId = testRunId; }) .Returns(Task.FromResult(new TestAttachmentReference())); _testResultServer.Setup(x => x.CreateTestResultAttachmentAsync(It.IsAny <TestAttachmentRequestModel>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <CancellationToken>())) .Callback <TestAttachmentRequestModel, string, int, int, CancellationToken> ((reqModel, projectName, testRunId, testCaseResultId, cancellationToken) => { if (_resultsLevelAttachments.ContainsKey(testCaseResultId)) { _resultsLevelAttachments[testCaseResultId].Add(reqModel); } else { _resultsLevelAttachments.Add(testCaseResultId, new List <TestAttachmentRequestModel>() { reqModel }); } }) .Returns(Task.FromResult(new TestAttachmentReference())); _testResultServer.Setup(x => x.CreateTestSubResultAttachmentAsync(It.IsAny <TestAttachmentRequestModel>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <CancellationToken>())) .Callback <TestAttachmentRequestModel, string, int, int, int, CancellationToken> ((reqModel, projectName, testRunId, testCaseResultId, testSubResultId, cancellationToken) => { if (_subResultsLevelAttachments.ContainsKey(testCaseResultId)) { if (_subResultsLevelAttachments[testCaseResultId].ContainsKey(testSubResultId)) { _subResultsLevelAttachments[testCaseResultId][testSubResultId].Add(reqModel); } else { _subResultsLevelAttachments[testCaseResultId].Add(testSubResultId, new List <TestAttachmentRequestModel>() { reqModel }); } } else { Dictionary <int, List <TestAttachmentRequestModel> > subResulAtt = new Dictionary <int, List <TestAttachmentRequestModel> >(); subResulAtt.Add(testSubResultId, new List <TestAttachmentRequestModel>() { reqModel }); _subResultsLevelAttachments.Add(testCaseResultId, subResulAtt); } }) .Returns(Task.FromResult(new TestAttachmentReference())); }
private void ResetValues() { _runId = 0; _projectId = ""; _attachmentRequestModel = null; _resultCreateModels = null; _resultsLevelAttachments = new Dictionary<int, List<TestAttachmentRequestModel>>(); _updateProperties = null; _batchSizes = new List<int>(); }
public TestRunPublisherTests() { _attachmentFilePath = "attachment.txt"; File.WriteAllText(_attachmentFilePath, "asdf"); _testRunContext = new TestRunContext("owner", "platform", "config", 1, "builduri", "releaseuri", "releaseenvuri"); _reader = new Mock<IResultReader>(); _reader.Setup(x => x.ReadResults(It.IsAny<IExecutionContext>(), It.IsAny<string>(), It.IsAny<TestRunContext>())) .Callback<IExecutionContext, string, TestRunContext> ((executionContext, filePath, runContext) => { _runContext = runContext; _resultsFilepath = filePath; }) .Returns((IExecutionContext executionContext, string filePath, TestRunContext runContext) => { TestRunData trd = new TestRunData( name: "xyz", buildId: runContext.BuildId, completedDate: "", state: "InProgress", isAutomated: true, dueDate: "", type: "", buildFlavor: runContext.Configuration, buildPlatform: runContext.Platform, releaseUri: runContext.ReleaseUri, releaseEnvironmentUri: runContext.ReleaseEnvironmentUri ); trd.Attachments = new string[] { "attachment.txt" }; return trd; }); _testResultServer = new Mock<ITestResultsServer>(); _testResultServer.Setup(x => x.InitializeServer(It.IsAny<Client.VssConnection>())); _testResultServer.Setup(x => x.AddTestResultsToTestRunAsync(It.IsAny<TestResultCreateModel[]>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<CancellationToken>())) .Callback<TestResultCreateModel[], string, int, CancellationToken> ((currentBatch, projectName, testRunId, cancellationToken) => { _batchSizes.Add(currentBatch.Length); _resultCreateModels = currentBatch; }) .Returns(() => { List<TestCaseResult> resultsList = new List<TestCaseResult>(); int i = 0; foreach (TestResultCreateModel resultCreateModel in _resultCreateModels) { resultsList.Add(new TestCaseResult() { Id = ++i }); } return Task.FromResult(resultsList); }); _testResultServer.Setup(x => x.CreateTestRunAsync(It.IsAny<string>(), It.IsAny<RunCreateModel>(), It.IsAny<CancellationToken>())) .Callback<string, RunCreateModel, CancellationToken> ((projectName, testRunData, cancellationToken) => { _projectId = projectName; _testRun = (TestRunData)testRunData; }) .Returns(Task.FromResult(new TestRun() { Name = "TestRun", Id = 1 })); _testResultServer.Setup(x => x.UpdateTestRunAsync(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<RunUpdateModel>(), It.IsAny<CancellationToken>())) .Callback<string, int, RunUpdateModel, CancellationToken> ((projectName, testRunId, updateModel, cancellationToken) => { _runId = testRunId; _projectId = projectName; _updateProperties = updateModel; }) .Returns(Task.FromResult(new TestRun() { Name = "TestRun", Id = 1 })); _testResultServer.Setup(x => x.CreateTestRunAttachmentAsync( It.IsAny<TestAttachmentRequestModel>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<CancellationToken>())) .Callback<TestAttachmentRequestModel, string, int, CancellationToken> ((reqModel, projectName, testRunId, cancellationToken) => { _attachmentRequestModel = reqModel; _projectId = projectName; _runId = testRunId; }) .Returns(Task.FromResult(new TestAttachmentReference())); _testResultServer.Setup(x => x.CreateTestResultAttachmentAsync(It.IsAny<TestAttachmentRequestModel>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>())) .Callback<TestAttachmentRequestModel, string, int, int, CancellationToken> ((reqModel, projectName, testRunId, testCaseResultId, cancellationToken) => { if (_resultsLevelAttachments.ContainsKey(testCaseResultId)) { _resultsLevelAttachments[testCaseResultId].Add(reqModel); } else { _resultsLevelAttachments.Add(testCaseResultId, new List<TestAttachmentRequestModel>() { reqModel }); } }) .Returns(Task.FromResult(new TestAttachmentReference())); }
/// <summary> /// Publishes the given results to the test run. /// </summary> /// <param name="testResults">Results to be published.</param> public async Task AddResultsAsync(TestRun testRun, TestCaseResultData[] testResults, CancellationToken cancellationToken) { Trace.Entering(); int noOfResultsToBePublished = BATCH_SIZE; _executionContext.Output(StringUtil.Loc("PublishingTestResults", testRun.Id)); for (int i = 0; i < testResults.Length; i += BATCH_SIZE) { cancellationToken.ThrowIfCancellationRequested(); if (i + BATCH_SIZE >= testResults.Length) { noOfResultsToBePublished = testResults.Length - i; } _executionContext.Output(StringUtil.Loc("TestResultsRemaining", (testResults.Length - i), testRun.Id)); var currentBatch = new TestCaseResultData[noOfResultsToBePublished]; var testResultsBatch = new TestCaseResult[noOfResultsToBePublished]; Array.Copy(testResults, i, currentBatch, 0, noOfResultsToBePublished); for (int testResultsIndex = 0; testResultsIndex < noOfResultsToBePublished; testResultsIndex++) { testResultsBatch[testResultsIndex] = new TestCaseResult(); TestCaseResultDataConverter.Convert(currentBatch[testResultsIndex], testResultsBatch[testResultsIndex]); } List <TestCaseResult> testresults = await _testResultsServer.AddTestResultsToTestRunAsync(testResultsBatch, _projectName, testRun.Id, cancellationToken); for (int j = 0; j < noOfResultsToBePublished; j++) { cancellationToken.ThrowIfCancellationRequested(); // Remove duplicate entries string[] attachments = testResults[i + j]?.AttachmentData?.AttachmentsFilePathList?.ToArray(); HashSet <string> attachedFiles = GetUniqueTestRunFiles(attachments); if (attachedFiles != null) { var createAttachmentsTasks = attachedFiles.Select(async attachment => { TestAttachmentRequestModel reqModel = GetAttachmentRequestModel(attachment); if (reqModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(reqModel, _projectName, testRun.Id, testresults[j].Id, cancellationToken); } }); await Task.WhenAll(createAttachmentsTasks); } // Upload console log as attachment string consoleLog = testResults[i + j]?.AttachmentData?.ConsoleLog; TestAttachmentRequestModel attachmentRequestModel = GetConsoleLogAttachmentRequestModel(consoleLog); if (attachmentRequestModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(attachmentRequestModel, _projectName, testRun.Id, testresults[j].Id, cancellationToken); } // Upload standard error as attachment string standardError = testResults[i + j]?.AttachmentData?.StandardError; TestAttachmentRequestModel stdErrAttachmentRequestModel = GetStandardErrorAttachmentRequestModel(standardError); if (stdErrAttachmentRequestModel != null) { await _testResultsServer.CreateTestResultAttachmentAsync(stdErrAttachmentRequestModel, _projectName, testRun.Id, testresults[j].Id, cancellationToken); } } } Trace.Leaving(); }
static void Main(string[] args) { string collectionUri; //set to Uri of the TFS collection //if this code is running in Build/Release workflow, we will fetch collection Uri from environment variable //See https://www.visualstudio.com/en-us/docs/build/define/variables for full list of agent environment variables if (Environment.GetEnvironmentVariable("TF_BUILD") == "True") { collectionUri = Environment.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"); Console.WriteLine("Fetched Collection (or VSTS account) from environment variable SYSTEM_TEAMFOUNDATIONCOLLECTIONURI: {0}", collectionUri); } else // set it to TFS instance of your choice { collectionUri = "http://buildmachine1:8080/tfs/DefaultCollection"; Console.WriteLine("Using Collection (or VSTS account): {0}", collectionUri); } //authentication.. VssConnection connection = new VssConnection(new Uri(collectionUri), new VssCredentials()); //set the team project name in which the test results must be published... // get team project name from the agent environment variables if the script is running in Build/Release workflow.. string teamProject; if (Environment.GetEnvironmentVariable("TF_BUILD") == "True") { teamProject = Environment.GetEnvironmentVariable("SYSTEM_TEAMPROJECT"); Console.WriteLine("Fetched team project from environment variable SYSTEM_TEAMPROJECT: {0}", teamProject); } else //else set it the team project of your choice... { teamProject = "FabrikamFiber"; Console.WriteLine("Using team project: {0}", teamProject); } // get the build number to publish results against... string buildNumber = null, buildUri = null, releaseUri = null, releaseEnvironmentUri = null; int buildId; // if this code is running in build/release workflow, we will use agent environment variables for fetch build/release Uris to associate information if (Environment.GetEnvironmentVariable("TF_BUILD") == "True") { //If RELEASE_RELEASEURI variable is set, then this code is running in the Release workflow, so we fetch release details if (Environment.GetEnvironmentVariable("RELEASE_RELEASEURI") != "") { releaseUri = Environment.GetEnvironmentVariable("RELEASE_RELEASEURI"); Console.WriteLine("Fetched release uri from environment variable RELEASE_RELEASEURI: {0}", releaseUri); releaseEnvironmentUri = Environment.GetEnvironmentVariable("RELEASE_ENVIRONMENTURI"); Console.WriteLine("Fetched release environemnt uri from environment variable RELEASE_ENVIRONMENTURI: {0}", releaseEnvironmentUri); } //note that the build used to deploy and test a Release is an Aritfact. //If you have multiple builds or are using external artifacts like Jenkins, make sure you use Aritfact variables to find the build information //See https://www.visualstudio.com/en-us/docs/release/author-release-definition/understanding-tasks#predefvariables for pre-defined variables available in release //See https://www.visualstudio.com/en-us/docs/release/author-release-definition/understanding-artifacts#variables for artifact variables documentation //For example, you'll have to use RELEASE_ARTIFACTS_<aftifactname>_BUILDID to find the build number. //Here we are assuming a simple setup, where we are working with Team Build and using Build variables instead... //build number is human readable format of the build name, you can confiure it's format in build options.. buildNumber = Environment.GetEnvironmentVariable("BUILD_BUILDNUMBER"); Console.WriteLine("Fetched build number from environment variable BUILD_BUILDNUMBER: {0}", buildNumber); //build id is the id associated with the build number, which we will use to associate the test run with... buildId = Convert.ToInt32(Environment.GetEnvironmentVariable("BUILD_BUILDID")); Console.WriteLine("Fetched build id from environment variable BUILD_BUILDID: {0}", buildId); //build uri is a more elaborate form of build id, in the vstfs:///Build/Build/<id> format... //We will use this for querying test runs against this build... buildUri = Environment.GetEnvironmentVariable("BUILD_BUILDURI"); Console.WriteLine("Fetched build uri from environment variable BUILD_BUILDURI: {0}", buildUri); } else //if the code is running in standalone mode, you'll have to use Build and Release APIs to fetch the build and release information... //see https://www.visualstudio.com/en-us/docs/integrate/api/build/overview for build APIs... //and https://www.visualstudio.com/en-us/docs/release/overview for release APIs... { buildNumber = "20161124.2"; buildId = 3; buildUri = "vstfs:///Build/Build/40"; releaseUri = "vstfs:///ReleaseManagement/Release/2"; releaseEnvironmentUri = "vstfs:///ReleaseManagement/Environment/2"; Console.WriteLine("Using build number: {0}; build id: {1}; build uri: {2}; release uri: {3}; release environment uri: {4}", buildNumber, buildId, buildUri, releaseUri, releaseEnvironmentUri); } //Client to use test run and test result APIs... TestManagementHttpClient client = connection.GetClient <TestManagementHttpClient>(); //Test run model to initialize test run parameters.. //For automated test runs, isAutomated must be set.. Else manual test run will be created.. //<<Q: do we want to mark run in progress here?>> RunCreateModel TestRunModel = new RunCreateModel(name: "Sample test run from CSV file against buildNumber: " + buildNumber, isAutomated: true, startedDate: DateTime.Now.ToString(), buildId: buildId, releaseUri: releaseUri, releaseEnvironmentUri: releaseEnvironmentUri); //Since we are doing a Asycn call, .Result will wait for the call to complete... TestRun testRun = client.CreateTestRunAsync(teamProject, TestRunModel).Result; Console.WriteLine("Step 1: test run created -> {0}: {1}; Run url: {2} ", testRun.Id, testRun.Name, testRun.WebAccessUrl); string resultsFilePath; if (args.Length == 0) { resultsFilePath = "Results.csv"; } else { resultsFilePath = args[0]; } TestAttachmentRequestModel fileAttachment = GetAttachmentRequestModel(resultsFilePath); TestAttachmentReference testAttachment = client.CreateTestRunAttachmentAsync(fileAttachment, teamProject, testRun.Id).Result; Console.WriteLine("Created test run attachment -> Id: {0}, Url: {2}", testAttachment.Id, testAttachment.Url); //List to hold results from parsed from CSV file... List <TestResultCreateModel> testResultsFromCsv = new List <TestResultCreateModel>(); //TestMethodName, Outcome, ErrorMessage, StackTrace, StartedDate, CompletedDate string traceFilePath; List <string> resultLogFiles = new List <string>(); var reader = new StreamReader(File.OpenRead(resultsFilePath)); while (!reader.EndOfStream) { var line = reader.ReadLine(); var values = line.Split(','); Console.WriteLine("Publishing test {0}", values[0]); //Assign values from each line in CSV to result model... TestResultCreateModel testResultModel = new TestResultCreateModel(); testResultModel.TestCaseTitle = testResultModel.AutomatedTestName = values[0]; testResultModel.Outcome = values[1]; //Setting state to completed since we are only publishing results. //In advanced scenarios, you can choose to create a test result, // move it into in progress state while test test acutally runs and finally update the outcome with state as completed testResultModel.State = "Completed"; testResultModel.ErrorMessage = values[2]; testResultModel.StackTrace = values[3]; testResultModel.StartedDate = values[4]; testResultModel.CompletedDate = values[5]; //store the path of the attachment in a list. We will publish attachments to results after we publish results and obtain result ids. traceFilePath = values[6]; resultLogFiles.Add(traceFilePath); //Add the result ot the results list... testResultsFromCsv.Add(testResultModel); } //Publish the results... List <TestCaseResult> publishedResults = client.AddTestResultsToTestRunAsync(testResultsFromCsv.ToArray(), teamProject, testRun.Id).Result; Console.WriteLine("Step 2: test results published..."); //results are published in the order they were submitted. H //We will now loop through the results file and publish the attachments for each test result. //Path of the attachment for each result (sample trace log) is in last column of the result csv file... int i = 0; foreach (TestCaseResult r in publishedResults) { Console.WriteLine("Adding attachment for Test Result -> Id: {0}", r.Id); fileAttachment = GetAttachmentRequestModel(resultLogFiles.ElementAt(i++)); testAttachment = client.CreateTestResultAttachmentAsync(fileAttachment, teamProject, testRun.Id, r.Id).Result; Console.WriteLine("Created test result attachment -> Id: {0}, Url: {1}", testAttachment.Id, testAttachment.Url); } //Mark the run complete... RunUpdateModel testRunUpdate = new RunUpdateModel(completedDate: DateTime.Now.ToString(), state: "Completed"); TestRun RunUpdateResult = client.UpdateTestRunAsync(teamProject, testRun.Id, testRunUpdate).Result; Console.WriteLine("Step 3: Test run completed: {0}", RunUpdateResult.WebAccessUrl); }