Python:
Here is a script that performs this task - it will copy all Test Cases from a Source Test Folder identified by FormattedID, to a Target Test Folder, also identified by FormattedID. It will copy all Test Steps and Attachments as well. The Target Test Folder must exist, i.e. the script will not create a Test Folder for you if the Target is not found.
The script does not associate the new Test Case to original Test Case's Work Product (i.e. Defect, User Story), or copy Discussion items, Test Case Results, or Last Build, Verdict, etc. as it is assumed the new Test Case is desired to be in a "blank" state.
For those needing to install and configure the Rally Python REST Library:
Rally Developer Portal: Pyral Download and Installation
Pyral Documentation
#!/usr/bin/env python
#################################################################################################
#
# copy_test_folder.py -- Copy all Test Cases in Source Test Folder to Target. Includes Test Steps
# and attachments. Target Test Folder must exist (i.e. the script will not
# create a new targeet Test Folder for you)
#
USAGE = """
Usage: copy_test_folder.py
"""
#################################################################################################
# import needed python libs
import sys, os
import re
import string
import base64
from pprint import pprint
# import needed pyral libs
from pyral import Rally, rallySettings, RallyRESTAPIError
errout = sys.stderr.write
my_server = "rally1.rallydev.com"
my_user = "user@company.com"
my_password = "topsecret"
my_workspace = "My Workspace"
my_project = "My Project"
source_test_folder_formatted_id = "TF1"
target_test_folder_formatted_id = "TF4"
rally = Rally(my_server, my_user, my_password, workspace=my_workspace, project=my_project)
# rally = Rally(my_server, my_user, my_password, workspace=my_workspace, project=my_project, debug=True)
rally.enableLogging('copy_test_folder.log')
# Query for source and target test folders
source_test_folder_response = rally.get('TestFolder', fetch=True, query='FormattedID = %s' % source_test_folder_formatted_id)
target_test_folder_response = rally.get('TestFolder', fetch=True, query='FormattedID = %s' % target_test_folder_formatted_id)
# Check to make sure folders exist
if source_test_folder_response.resultCount == 0:
errout('No Source Test Folder Found matching Formatted ID: %s\n' % (source_test_folder_formatted_id))
sys.exit(4)
if target_test_folder_response.resultCount == 0:
errout('No Target Test Folder Found matching Formatted ID: %s\n. Target Test Folder must be created before copying.' % (target_test_folder_formatted_id))
sys.exit(4)
# Get references to source Test Folder and Test Cases, etc.
source_test_folder = source_test_folder_response.next()
source_test_cases = source_test_folder.TestCases
# Get reference to target Test Folder
target_test_folder = target_test_folder_response.next()
for source_test_case in source_test_cases:
# Create update fields for target Test Case
# Does NOT associate new Test Case to original Test Case's work product (i.e. Defect, User Story)
# Does NOT copy Discussion items - as the old Discussions are likely not desired on new Test Case
# Does NOT copy Last Build, Last Run, Last Update Date, Last Verdict as new Test Case will effectively
# be "blank" and not have any results associated to it
if source_test_case.Owner != None:
target_owner = source_test_case.Owner.ref
else:
target_owner = None
target_test_case_fields = {
"Package": source_test_case.Package,
"Description": source_test_case.Description,
"Method": source_test_case.Method,
"Name": source_test_case.Name,
"Objective": source_test_case.Objective,
"Owner": target_owner,
"PostConditions": source_test_case.PostConditions,
"PreConditions": source_test_case.PreConditions,
"Priority": source_test_case.Priority,
"Project": source_test_case.Project.ref,
"Risk": source_test_case.Risk,
"ValidationInput": source_test_case.ValidationInput,
"ValidationExpectedResult": source_test_case.ValidationExpectedResult,
"TestFolder": target_test_folder.ref,
}
# Create the target test case
try:
target_test_case = rally.create("TestCase", target_test_case_fields)
message = "Copied Source Test Case: " + source_test_case.FormattedID + \
" To: " + target_test_folder.FormattedID + ": " + target_test_folder.Name + \
": " + target_test_case.FormattedID
print message
except RallyRESTAPIError, details:
sys.stderr.write('ERROR: %s \n' % details)
sys.exit(2)
# Copy Test Steps
# Add Test Case Steps
source_test_case_steps = source_test_case.Steps
for source_step in source_test_case_steps:
target_step_fields = {
"TestCase" : target_test_case.ref,
"StepIndex" : source_step.StepIndex,
"Input" : source_step.Input,
"ExpectedResult" : source_step.ExpectedResult
}
target_test_case_step = rally.put('TestCaseStep', target_step_fields)
print "===> Copied TestCaseStep: %s OID: %s" % (target_test_case_step.StepIndex, target_test_case_step.oid)
# Copy Attachments
source_attachments = rally.getAttachments(source_test_case)
for source_attachment in source_attachments:
# First copy the content
source_attachment_content = source_attachment.Content
target_attachment_content_fields = {
"Content": base64.encodestring(source_attachment_content)
}
try:
target_attachment_content = rally.put('AttachmentContent', target_attachment_content_fields)
print "===> Copied AttachmentContent: %s" % target_attachment_content.ref
except RallyRESTAPIError, details:
sys.stderr.write('ERROR: %s \n' % details)
sys.exit(2)
# Next copy the attachment object
target_attachment_fields = {
"Name": source_attachment.Name,
"Description": source_attachment.Description,
"Content": target_attachment_content.ref,
"ContentType": source_attachment.ContentType,
"Size": source_attachment.Size,
"Artifact": target_test_case.ref,
"User": source_attachment.User.ref
}
try:
target_attachment = rally.put('Attachment', target_attachment_fields)
print "===> Copied Attachment: %s" % target_attachment.ref
except RallyRESTAPIError, details:
sys.stderr.write('ERROR: %s \n' % details)
sys.exit(2)
# Copy Tags
source_tags = source_test_case.Tags;
target_tags = list()
for source_tag in source_tags:
target_tags.append({"_ref":source_tag.ref})
target_test_case_fields = {
"FormattedID": target_test_case.FormattedID,
"Tags": target_tags
}
try:
update_response = rally.update('TestCase', target_test_case_fields)
except RallyRESTAPIError, details:
sys.stderr.write('ERROR: %s \n' % details)
sys.exit(2)