Azure DevOps, and TFS/VSTS before it, has always had an interesting problem with Team Projects.  The recommended architecture by most in the field and Microsoft itself is a single Team Project for all of your work.  However, in my experience many users are given an Azure DevOps organization and told to start developing and the first thing they do is make a project for each business unit, solution, and any other subdivision of their organization they can think of.  At some point they may start looking at best practices or bringing in someone to help with their process, but to some extent the damage has already been done.  Thankfully, moving items between projects is easier than ever before.  Work items can be easily moved to new projects and teams using the GUI.

The Problem

However, there is a glaring exception to this for those of us who use Test Plans in Azure DevOps.  You cannot move any Work Items that support test management(test cases, suites or plans).  If you like many organizations started in many different projects, or even had a dedicated QA project, and want to consolidate this becomes a problem.  Depending on how many items in questions you have a few options at this point.  You can create a copy of each test case and change its project.  This is a relatively simple process if you have a few cases, but what if you have hundreds?

Next option would be to create a query-based Test Suite in the new project.  With “Query across projects” selected, you can target Test Cases in a specific team project or across your organization.  You can of course refine down from there as needed, and then add them to a suite in your new project.  This method allows you to automatically pick up items from other projects but doesn’t allow for the same control as if they were all part of the same project.

Solution

The last and cleanest option is to clone the test plans entirely.  While not supported using the GUI, the always useful Azure DevOps API gives us the tools we need to clone a test plan.  Using this you can clone a specific test plan ID to another project.  This is not the whole picture if you are using many different plans in the same project.  As usual, we’ll need to chain a few requests together.  My weapon of choice for these sorts of tasks is Powershell.  Below is first how you would get all the test plans from the initial project

$Url = "$projectUrl/_apis/test/plans?api-version=5.0"
$response = Invoke-RestMethod -Uri $Url -Headers $headers -Method Get -ContentType application/json;

The list request will get you much more information then you need.  All we really care about is the ID, and possibly the plan names if you want to keep them the same.  So we can loop through these easy enough and post them to the new project

$response.value | ForEach-Object {
$ID = $_.id
$Url = "$projectUrl/_apis/test/Plans/$ID/cloneoperation?api-version=5.0-preview.2"
Invoke-RestMethod -Uri $Url -Headers $headers -Body $body -Method Post -ContentType application/json;
}

Now we have cloned all of our test plans and the associated suites and cases into our new project.  This can obviously be refined further depending on how you want the cases organized in the new structure, but it demonstrates that Test Plans can be moved between projects even if all the support hasn’t made it to the GUI yet.

Conclusion

I often get asked if Azure DevOps can be used for a specific tasks or to support a specific process.  While there are always features that are missing from the platform out of the box, what I find to be incredibly useful is how versatile the customization is.  Using the API you have access to an enormous amount of information and functionality for the platform, so I’ve yet to come across a request that could not possibly be done.  The real trick lies in why are we doing such a unique task, is the time investment going to give returns, and is there any way we can improve this process?  If you ever need help answering these questions or figuring out the right script for the job your friendly friends at Nebbia Technology can help with that.