TestManagement/TestManagement.ps1
<#
.SYNOPSIS Clones a test plan and, optionally, its test suites and test cases .DESCRIPTION The Copy-TfsTestPlan copies ("clones") a test plan to help duplicate test suites and/or test cases. Cloning is useful if you want to branch your application into two versions: after copying, the tests for the two versions can be changed without affecting each other. .EXAMPLE Copy-TfsTestPlan -TestPlan 'My test plan' -Project 'SourceProject' -Destination 'TargetProject' -NewName 'My new test plan' .INPUTS Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlan .OUTPUTS Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlan .NOTES When you clone a test suite, the following objects are copied from the source test plan to the destination test plan: * Test cases (note: Each new test case retains its shared steps. A link is made between the source and new test cases. The new test cases do not have test runs, bugs, test results, and build information); * Shared steps referenced by cloned test cases; * Test suites (note: The following data is retained - Names and hierarchical structure of the test suites; Order of the test cases; Assigned testers; Configurations) * Action Recordings linked from a cloned test case * Links and Attachments * Test configuration The items below are only copied when using -CloneRequirements: * Requirements-based suites; * Requirements work items (product backlog items or user stories); * Bug work items, when in a project that uses the Scrum process template or any other project in which the Bug work item type is in the Requirements work item category. In other projects, bugs are not cloned. .PARAMETER TestPlan .PARAMETER Project Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any). For more details, see the Get-TfsTeamProject cmdlet. .PARAMETER NewName .PARAMETER DestinationProject .PARAMETER AreaPath .PARAMETER IterationPath .PARAMETER DeepClone .PARAMETER CopyAllSuites .PARAMETER CopyAncestorHierarchy .PARAMETER DestinationWorkItemType .PARAMETER SuiteIds .PARAMETER RelatedLinkComment .PARAMETER Passthru Returns the results of the command. By default, this cmdlet does not generate any output. .PARAMETER Collection Specifies either a URL/name of the Team Project Collection to connect to, or a previously initialized TfsTeamProjectCollection object. When using a URL, it must be fully qualified. The format of this string is as follows: http[s]://<ComputerName>:<Port>/[<TFS-vDir>/]<CollectionName> Valid values for the Transport segment of the URI are HTTP and HTTPS. If you specify a connection URI with a Transport segment, but do not specify a port, the session is created with standards ports: 80 for HTTP and 443 for HTTPS. To connect to a Team Project Collection by using its name, a TfsConfigurationServer object must be supplied either via -Server argument or via a previous call to the Connect-TfsConfigurationServer cmdlet. For more details, see the Get-TfsTeamProjectCollection cmdlet. #> Function Copy-TfsTestPlan { [CmdletBinding()] [OutputType('Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlan')] Param ( [Parameter(ValueFromPipeline=$true)] [Alias("id")] [ValidateNotNull()] [object] $TestPlan, [Parameter()] [object] $Project, [Parameter()] [string] $NewName, [Parameter()] [Alias('Destination')] [object] $DestinationProject, [Parameter()] [string] $AreaPath, [Parameter()] [string] $IterationPath, [Parameter()] [switch] $DeepClone, [Parameter()] [Alias("Recurse")] [switch] $CopyAllSuites, [Parameter()] [switch] $CopyAncestorHierarchy, [Parameter()] [switch] $CloneRequirements, [Parameter()] [string] $DestinationWorkItemType = 'Test Case', [Parameter()] [int[]] $SuiteIds, [Parameter()] [string] $RelatedLinkComment, [Parameter()] [ValidateSet('Original', 'Copy', 'None')] [string] $Passthru = 'None', [Parameter()] [object] $Collection ) Begin { #_ImportRequiredAssembly -AssemblyName 'Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi' #_ImportRequiredAssembly -AssemblyName 'Microsoft.TeamFoundation.TestManagement.WebApi' $ns = 'Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi' } Process { $plan = Get-TfsTestPlan -TestPlan $TestPlan -Project $Project -Collect $Collection if(-not $plan) { throw "Invalid or non-existent test plan $TestPlan" } $destTp = Get-TfsTeamProject -Project $DestinationProject -Collection $Collection if(-not $destTp) { throw "Invalid or non-existent team project $DestinationProject" } if (-not $Project) { $Project = $plan.Project.Name } $tp = Get-TfsTeamProject -Project $Project -Collection $Collection if(-not $tp) { throw "Invalid or non-existent team project $Project" } if (-not $NewName) { if($tp.Name -ne $destTp.Name) { $NewName = $plan.Name } else { $NewName = "$($plan.Name) (cloned $([DateTime]::Now.ToShortDateString()))" } } if (-not $AreaPath) { $AreaPath = $destTp.Name } if (-not $IterationPath) { $IterationPath = $destTp.Name } $tpc = $tp.Store.TeamProjectCollection $client = _GetRestClient "$ns.TestPlanHttpClient" -Collection $tpc $cloneParams = New-Object "$ns.CloneTestPlanParams" -Property @{ sourceTestPlan = New-Object "$ns.SourceTestPlanInfo" -Property @{ Id = $plan.Id }; destinationTestPlan = New-Object "$ns.DestinationTestPlanCloneParams" -Property @{ Project = $destTp.Name; Name = $NewName; AreaPath = $AreaPath; Iteration = $IterationPath }; cloneOptions = New-Object "Microsoft.TeamFoundation.TestManagement.WebApi.CloneOptions" -Property @{ RelatedLinkComment = $RelatedLinkComment; CopyAllSuites = $CopyAllSuites.IsPresent; CopyAncestorHierarchy = $CopyAncestorHierarchy; DestinationWorkItemType = $DestinationWorkItemType; CloneRequirements = $CloneRequirements; OverrideParameters = _NewDictionary @([string],[string]) @{ 'System.AreaPath' = $AreaPath; 'System.IterationPath' = $IterationPath } } } $task = $client.CloneTestPlanAsync($cloneParams, $tp.Name, $DeepClone.IsPresent) $result = $task.Result; if($task.IsFaulted) { _throw 'Error cloning test plan' $task.Exception.InnerExceptions } $opInfo = $result do { Start-Sleep -Seconds 1 $opInfo = $client.GetCloneInformationAsync($tp.Name, $opInfo.CloneOperationResponse.opId) } while ($opInfo.CloneOperationResponse.CloneOperationState -match 'Queued|InProgress') if ($opInfo.CloneOperationResponse.CloneOperationState -eq 'Failed') { throw "Error cloning test plan '$($plan.Name)': $($opInfo.CloneOperationResponse.Message)" } else { $copy = $opInfo.DestinationTestPlan } if ($Passthru -eq 'Original') { return $plan } if($Passthru -eq 'Copy') { return $copy } } } <# .SYNOPSIS Gets the contents of one or more test plans .DESCRIPTION .EXAMPLE Get-TfsTestPlan 'Release 1 - Sprint*' -Project 'Fabrikam' Returns all test plans from team project 'Fabrikam' whose names start with 'Release 1 - Sprint' .INPUTS Microsoft.TeamFoundation.WorkItemTracking.Client.Project .OUTPUTS Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlan .NOTES #> Function Get-TfsTestPlan { [CmdletBinding()] [OutputType('Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlan')] Param ( # Specifies the test plan name. Wildcards are supported [Parameter(Position=0)] [SupportsWildcards()] [Alias("Id")] [Alias("Name")] [object] $TestPlan = '*', # Specifices the plan's owner name [Parameter()] [string] $Owner, # Get only basic properties of the test plan [Parameter()] [switch] $NoPlanDetails, # Get just the active plans [Parameter()] [switch] $FilterActivePlans, # Specifies the team project [Parameter(ValueFromPipeline=$true)] [object] $Project, # Specifies the collection / organization [Parameter()] [Alias("Organization")] [object] $Collection ) Begin { #_ImportRequiredAssembly -AssemblyName 'Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi' } Process { if ($TestPlan -is [Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlan]) { return $TestPlan } $tp = Get-TfsTeamProject -Project $Project -Collection $Collection $tpc = $tp.Store.TeamProjectCollection $client = _GetRestClient 'Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi.TestPlanHttpClient' -Collection $tpc return $client.GetTestPlansAsync( $tp.Name, $Owner, $null, (-not $NoPlanDetails.IsPresent), $FilterActivePlans.IsPresent).Result | Where-Object Name -like $TestPlan } } Function Remove-TfsTestPlan { [CmdletBinding(ConfirmImpact="High", SupportsShouldProcess=$true)] Param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [Alias("id")] [ValidateNotNull()] [object] $TestPlan, [Parameter()] [object] $Project, [Parameter()] [object] $Collection ) Begin { #_ImportRequiredAssembly -AssemblyName 'Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi' #_ImportRequiredAssembly -AssemblyName 'Microsoft.TeamFoundation.TestManagement.WebApi' $ns = 'Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi' } Process { $plan = Get-TfsTestPlan -TestPlan $TestPlan -Project $Project -Collect $Collection if(-not $plan) { throw "Invalid or non-existent test plan $TestPlan" } if (-not $Project) { $Project = $plan.Project.Name } $tp = Get-TfsTeamProject -Project $Project -Collection $Collection if(-not $tp) { throw "Invalid or non-existent team project $Project" } $tpc = $tp.Store.TeamProjectCollection $client = _GetRestClient "$ns.TestPlanHttpClient" -Collection $tpc if ($PSCmdlet.ShouldProcess("Plan $($plan.Id) ('$($plan.Name)')", "Remove test plan")) { $task = $client.DeleteTestPlanAsync($tp.Name, $plan.Id) $result = $task.Result; if($task.IsFaulted) { _throw 'Error deleting test plan' $task.Exception.InnerExceptions } } } } |