diff --git a/Tasks/VsTest/distributedTest.ts b/Tasks/VsTest/distributedTest.ts index 2314dd9a1039..a28ab9096d74 100644 --- a/Tasks/VsTest/distributedTest.ts +++ b/Tasks/VsTest/distributedTest.ts @@ -25,7 +25,7 @@ export class DistributedTest { try { const agentId = await ta.TestAgent.createAgent(this.dtaTestConfig.dtaEnvironment, 3); - this.dtaPid = this.startDtaExecutionHost(agentId); + this.dtaPid = await this.startDtaExecutionHost(agentId); await this.startDtaTestRun(); try { // TODO: ranjanar: fixasap : This dangerous - Note that the PID only uniquely identifies your child process @@ -42,7 +42,7 @@ export class DistributedTest { } } - private startDtaExecutionHost(agentId: any): number { + private async startDtaExecutionHost(agentId: any) { tl.rmRF(this.dtaTestConfig.dtaEnvironment.dtaHostLogFilePath, true); const envVars: { [key: string]: string; } = process.env; utils.Helper.addToProcessEnvVars(envVars, 'DTA.AccessToken', this.dtaTestConfig.dtaEnvironment.patToken); @@ -54,11 +54,15 @@ export class DistributedTest { this.dtaTestConfig.vsTestVersion = '15.0'; } utils.Helper.addToProcessEnvVars(envVars, 'DTA.TestPlatformVersion', this.dtaTestConfig.vsTestVersion); - versionFinder.locateTestWindow(this.dtaTestConfig) - .then (function (exeInfo) { - tl.debug("Adding env var DTA.TestWindow.Path = " + exeInfo.location); - utils.Helper.addToProcessEnvVars(envVars, 'DTA.TestWindow.Path', exeInfo.location); + var exeInfo = await versionFinder.locateTestWindow(this.dtaTestConfig); + if(exeInfo) { + tl.debug("Adding env var DTA.TestWindow.Path = " + exeInfo.location); + utils.Helper.addToProcessEnvVars(envVars, 'DTA.TestWindow.Path', exeInfo.location); + } else { + tl.error(tl.loc('VstestNotFound', this.dtaTestConfig.vsTestVersion)); + } + // We are logging everything to a DTAExecutionHost.exe.log file and reading it at the end and adding to the build task debug logs // So we are not redirecting the IO streams from the DTAExecutionHost.exe process @@ -68,9 +72,6 @@ export class DistributedTest { const proc = ps.spawn(path.join(__dirname, 'Modules/DTAExecutionHost.exe'), [], { env: envVars, stdio: 'ignore' }); tl.debug('DtaExecutionHost is executing with the process : ' + proc.pid); return proc.pid; - }); - tl.error(tl.loc('VstestNotFound')); - return 0; } private async startDtaTestRun() { diff --git a/Tasks/VsTest/models.ts b/Tasks/VsTest/models.ts index 58b84617682c..4c67805d1f7d 100644 --- a/Tasks/VsTest/models.ts +++ b/Tasks/VsTest/models.ts @@ -20,15 +20,15 @@ export interface TestConfigurations { runInParallel: boolean; runTestsInIsolation: boolean; vs15HelperPath: string; + testSelection: string; // "testPlan" as selection string + testplan: number; + testSuites: number[]; + testPlanConfigId: number; } export interface DtaTestConfigurations extends TestConfigurations { onDemandTestRunId: string; testConfigurationMapping: string; // TODO : What is this? - testSelection: string; // "testPlan" as selection string - testplan: number; - testSuites: number[]; - testPlanConfigId: number; customSlicingenabled: boolean; dtaEnvironment: DtaEnvironment; } diff --git a/Tasks/VsTest/runvstest.ts b/Tasks/VsTest/runvstest.ts index c2b34c9e1dbd..afac79adee94 100644 --- a/Tasks/VsTest/runvstest.ts +++ b/Tasks/VsTest/runvstest.ts @@ -16,7 +16,15 @@ try { if (parallelExecution && parallelExecution.toLowerCase() === 'multimachine' || testType.toLowerCase() === 'testplan' || testType.toLowerCase() === 'testrun') { tl.debug('Going to the DTA Flow..'); tl.debug('***********************'); - const dtaTestConfig = taskInputParser.getDistributedTestConfigurations(); + + var dtaTestConfig = null; + if(parallelExecution && parallelExecution.toLowerCase() === 'multimachine') { + dtaTestConfig = taskInputParser.getDistributedTestConfigurations(false); + } + else { + dtaTestConfig = taskInputParser.getDistributedTestConfigurations(true); + } + const test = new distributedTest.DistributedTest(dtaTestConfig); test.runDistributedTest(); } else { @@ -28,3 +36,16 @@ try { tl._writeLine('##vso[task.logissue type=error;code=' + error + ';TaskName=VSTest]'); throw error; } + +function getDtaInstanceId(): number { + const taskInstanceIdString = tl.getVariable('DTA_INSTANCE_ID'); + let taskInstanceId: number = 1; + if (taskInstanceIdString) { + const instanceId: number = Number(taskInstanceIdString); + if (!isNaN(instanceId)) { + taskInstanceId = instanceId + 1; + } + } + tl.setVariable('DTA_INSTANCE_ID', taskInstanceId.toString()); + return taskInstanceId; +} diff --git a/Tasks/VsTest/task.json b/Tasks/VsTest/task.json index c57b1fcde598..b6aa73e9ecbe 100644 --- a/Tasks/VsTest/task.json +++ b/Tasks/VsTest/task.json @@ -180,6 +180,7 @@ "defaultValue": "14.0", "required": false, "helpMarkDown": "The version of Visual Studio test to use.", + "groupName": "executionOptions", "options": { "latest": "Latest", "15.0": "Visual Studio 2017", diff --git a/Tasks/VsTest/task.loc.json b/Tasks/VsTest/task.loc.json index 950d7dcb04e3..d61a892bfdba 100644 --- a/Tasks/VsTest/task.loc.json +++ b/Tasks/VsTest/task.loc.json @@ -180,6 +180,7 @@ "defaultValue": "14.0", "required": false, "helpMarkDown": "ms-resource:loc.input.help.vsTestVersion", + "groupName": "executionOptions", "options": { "latest": "Latest", "15.0": "Visual Studio 2017", diff --git a/Tasks/VsTest/taskinputparser.ts b/Tasks/VsTest/taskinputparser.ts index b88ef9578ad4..5cae3676a2f8 100644 --- a/Tasks/VsTest/taskinputparser.ts +++ b/Tasks/VsTest/taskinputparser.ts @@ -8,7 +8,7 @@ import utils = require('./helpers'); let os = require('os'); let uuid = require('node-uuid'); -export function getDistributedTestConfigurations(): models.DtaTestConfigurations { +export function getDistributedTestConfigurations(isBuild : boolean): models.DtaTestConfigurations { tl.setResourcePath(path.join(__dirname, 'task.json')); const dtaConfiguration = {} as models.DtaTestConfigurations; initTestConfigurations(dtaConfiguration); @@ -20,7 +20,7 @@ export function getDistributedTestConfigurations(): models.DtaTestConfigurations if(dtaConfiguration.runTestsInIsolation) { tl.warning(tl.loc('runTestInIsolationNotSupported')); } - dtaConfiguration.dtaEnvironment = initDtaEnvironment(); + dtaConfiguration.dtaEnvironment = initDtaEnvironment(isBuild); return dtaConfiguration; } @@ -34,7 +34,7 @@ export function getvsTestConfigurations(): models.VsTestConfigurations { return vsTestConfiguration; } -function initDtaEnvironment(): models.DtaEnvironment { +function initDtaEnvironment(isBuild: boolean): models.DtaEnvironment { const dtaEnvironment = {} as models.DtaEnvironment; dtaEnvironment.tfsCollectionUrl = tl.getVariable('System.TeamFoundationCollectionUri'); dtaEnvironment.patToken = tl.getEndpointAuthorization('SystemVssConnection', true).parameters['AccessToken']; @@ -44,8 +44,14 @@ function initDtaEnvironment(): models.DtaEnvironment { const phaseId = tl.getVariable('Release.DeployPhaseId'); const projectName = tl.getVariable('System.TeamProject'); const taskInstanceId = getDtaInstanceId(); + + if(isBuild) { + const buildId = tl.getVariable('Build.BuildId'); + dtaEnvironment.environmentUri = 'dta://env/' + projectName + '/_apis/build/' + buildId + '/' + taskInstanceId; + } else { + dtaEnvironment.environmentUri = 'dta://env/' + projectName + '/_apis/release/' + releaseId + '/' + phaseId + '/' + taskInstanceId; + } - dtaEnvironment.environmentUri = 'dta://env/' + projectName + '/_apis/release/' + releaseId + '/' + phaseId + '/' + taskInstanceId; dtaEnvironment.dtaHostLogFilePath = path.join(tl.getVariable('System.DefaultWorkingDirectory'), 'DTAExecutionHost.exe.log'); return dtaEnvironment; } @@ -77,8 +83,20 @@ function initTestConfigurations(testConfiguration: models.TestConfigurations) testConfiguration.runInParallel = tl.getBoolInput('runTestsInParallel'); testConfiguration.runTestsInIsolation = tl.getBoolInput('runTestsInIsolation'); testConfiguration.tiaConfig = getTiaConfiguration(); - testConfiguration.vsTestVersion = tl.getInput('vsTestVersion'); + testConfiguration.testSelection = tl.getInput('testSelector'); + + if(testConfiguration.testSelection.toLowerCase() === 'testPlan') { + testConfiguration.testplan = parseInt(tl.getInput('testPlan')); + testConfiguration.testPlanConfigId = parseInt(tl.getInput('testConfiguration')); + + var testSuiteStrings = tl.getInput('testSuite').split(','); + testConfiguration.testSuites = new Array(); + testSuiteStrings.forEach(element => { + testConfiguration.testSuites.push(parseInt(element)); + }); + } + testConfiguration.vsTestVersion = tl.getInput('vsTestVersion'); if(utils.Helper.isNullEmptyOrUndefined(testConfiguration.vsTestVersion)) { tl._writeLine('vsTestVersion is null or empty'); throw new Error("vsTestVersion is null or empty"); diff --git a/Tasks/VsTest/versionFinder.ts b/Tasks/VsTest/versionFinder.ts index 6c7d61c1e8f7..67a8cb9abe5c 100644 --- a/Tasks/VsTest/versionFinder.ts +++ b/Tasks/VsTest/versionFinder.ts @@ -64,7 +64,7 @@ function getLatestVSTestConsolePathFromRegistry(): Q.Promise();