0

I've worked with the script outlined in the following answer:

Rally APIs: How to copy Test Folder and member Test Cases

and it's handy, but what I really want to do is to move an entire Test Folder into a different project. This is next to impossible through the Rally User Interface. According to Rally Support, the only way to do this in the UI is:

  • Un-assign the Test Cases from their current Test Folder
  • Setup a Custom Grid app on your dashboard
  • Use the Custom Grid bulk edit to update the Project of the Test Cases
  • Lastly use the Custom Grid bulk edit to update the Test Folder - now that you're in the target Project, of the Test Cases

Even though the above process is clunky, it is easier now than it used to be before the advent of the bulk edit within the Custom Grids. Before you had to go through and edit each Test Case one-by-one which was very manual and slow.

However, we have several thousand Test Cases we need to move, and the Custom Grid has a fatal flaw for us. It will only show the first 200 records in a query. So we would have to manually change our grid query in a step wise manner to accomplish the move we need. This is barely better than editing Test Cases one-by-one. Is there a way to move a Test Folder with Test Cases from one Project to another, using a script? Please tell me there is.

Community
  • 1
  • 1
user1373451
  • 53
  • 1
  • 10

1 Answers1

0

The following script will perform this task - it will move all Test Cases from a Source Test Folder identified by FormattedID, to a Target Test Folder, also identified by FormattedID. The Source Test Folder and Target Test Folder can be in different Projects (although they must be within the same Workspace). Like the Copy script referenced in the question, the Target Test Folder must exist, i.e. the script will not create a Test Folder for you if the Target is not found.

For those needing to install and configure the Ruby REST Toolkit, links are here:

Developer Portal: Rally REST API for Ruby

Github

# Copyright 2002-2012 Rally Software Development Corp. All Rights Reserved.

require 'rally_api'

$my_base_url       = "https://rally1.rallydev.com/slm"
$my_username       = "user@company.com"
$my_password       = "password"
$my_workspace      = "My Workspace"
$my_project        = "My Project"
$wsapi_version     = "1.39"

# Test Folders
$source_test_folder_formatted_id = "TF8"
$target_test_folder_formatted_id = "TF11"

#==================== Make a connection to Rally ====================
config                  = {:base_url => $my_base_url}
config[:username]       = $my_username
config[:password]       = $my_password
config[:workspace]      = $my_workspace
config[:project]        = $my_project
config[:version]        = $wsapi_version

@rally = RallyAPI::RallyRestJson.new(config)

begin

  # Lookup source Test Folder
  source_test_folder_query = RallyAPI::RallyQuery.new()
  source_test_folder_query.type = :testfolder
  source_test_folder_query.fetch = true
  source_test_folder_query.query_string = "(FormattedID = \"" + $source_test_folder_formatted_id + "\")"

  source_test_folder_result = @rally.find(source_test_folder_query)

  # Lookup Target Test Folder
  target_test_folder_query = RallyAPI::RallyQuery.new()
  target_test_folder_query.type = :testfolder
  target_test_folder_query.fetch = true
  target_test_folder_query.query_string = "(FormattedID = \"" + $target_test_folder_formatted_id + "\")"

  target_test_folder_result = @rally.find(target_test_folder_query)

  if source_test_folder_result.total_result_count == 0
    puts "Source Test Folder: " + $source_test_folder_formatted_id + "not found. Exiting."
    exit
  end

  if target_test_folder_result.total_result_count == 0
    puts "Target Test Folder: " + $target_test_folder_formatted_id + "not found. Target must exist before moving."
    exit
  end

  source_test_folder = source_test_folder_result.first()
  target_test_folder = target_test_folder_result.first()

  # Populate full object for both Source and Target Test Folders
  full_source_test_folder = source_test_folder.read
  full_target_test_folder = target_test_folder.read

  # Grab collection of Source Test Cases
  source_test_cases = source_test_folder["TestCases"]

  # Loop through Source Test Cases and Move to Target
  source_test_cases.each do |source_test_case|
    begin

      test_case_to_update = source_test_case.read
      source_test_case_formatted_id = test_case_to_update["FormattedID"]

      target_project = full_target_test_folder["Project"]
      target_project_full_object = target_project.read
      target_project_name = target_project_full_object["Name"]

      source_project = full_source_test_folder["Project"]
      source_project_full_object = source_project.read
      source_project_name = source_project_full_object["Name"]

      puts "Source Project Name: #{source_project_name}"
      puts "Target Project Name: #{target_project_name}"

      # Test if the source project and target project are the same
      source_target_proj_match = source_project_name.eql?(target_project_name)

      # If the target Test Folder is in a different Project, we have to do some homework first:
      # "un-Test Folder" the project
      # Assign the Test Case to the Target Project
      # Assign the Test Case to the Target Test Folder
      if !source_target_proj_match then
        fields = {}
        fields["TestFolder"] = ""
        test_case_updated = @rally.update(:testcase, test_case_to_update.ObjectID, fields) #by ObjectID
        puts "Test Case #{source_test_case_formatted_id} successfully dissociated from: #{$source_test_folder_formatted_id}"

        # Get full object on Target Project and assign Test Case to Target Project
        fields = {}
        fields["Project"] = target_project_full_object
        test_case_updated = @rally.update(:testcase, test_case_to_update.ObjectID, fields) #by ObjectID
        puts "Test Case #{source_test_case_formatted_id} successfully assigned to Project: #{target_project_name}"
      end

      # Change the Test Folder attribute on the Test Case
      fields = {}
      fields["TestFolder"] = target_test_folder
      test_case_updated = @rally.update(:testcase, test_case_to_update.ObjectID, fields) #by ObjectID
      puts "Test Case #{source_test_case_formatted_id} successfully moved to #{$target_test_folder_formatted_id}"
    rescue => ex
      puts "Test Case #{source_test_case_formatted_id} not updated due to error"
      puts ex
    end
  end
end