Search code examples
pythonrallypyral

How to update steps of Test Cases in Rally by using the Python API (pyral)


Thanks to the great documentation online for Rally API, I know how to create test steps and update a defect/test case.

A similar question has been asked and answered regarding usage with ...

However, I did not succeed updating a test step by using python API (pyral).

I have tried the following code:

TCid = "TC1392"
testcase=rally.get('TestCase', query='FormattedID = %s' % TCid, instance=True)
print "Updating steps for Test Case %s" % testcase.FormattedID
#Test Steps
try:
    for i in range(3):
        input="Step Input for Step: "+str(i)
        expected_result="Expected Result for Step: "+str(i)

        testcasestep_fields = {
            "TestCase"          : testcase.ref,
            "StepIndex"         : i,
            "Input"             : input,
            "ExpectedResult"    : expected_result
        }

        testcasestep = rally.update('TestCaseStep', testcasestep_fields)
    print "Steps of TestCase %s updated\n" % testcase.FormattedID
except RallyRESTAPIError, details:
    sys.stderr.write('ERROR: %s \n\n' % details)

But this returns the following error: An identifying field (Object or FormattedID) must be specified. The error is raised by the line 991 of pyral/restapi.py.

How to make it work?


Solution

  • The solution I found was to take another approach and looping through the steps and therefore being able to retrieve the oid of each step.

    [Update 14 May 2015]: A better approach is to perform 3 steps:

    1. update of existing test steps (if any)
    2. creation of new test steps (if needed)
    3. deletion of extra test steps (if needed)

    The program shall first identify the number of steps for each operation.


    The result looks like this:

    TCid = "TC1394"
    #Generate random number of steps
    def generate_Steps():
        list_Steps=[]
        import random
        n_steps=random.randrange(1,15)
        for i in range(n_steps):
            Step={'StepIndex':i+1}
            Step['Input']="Step Input for step %d" % (i+1)
            Step['ExpectedResult']="Expected Result for step %d" % (i+1)
            list_Steps.append(Step)
        print "Using random list of %d Test Steps" % (n_steps)
        return list_Steps
    
    #Update steps
    def update_TestSteps(TCid, Steps):
        try:
            #Get number of existing steps
            testcase=rally.get('TestCase', query='FormattedID = %s' % TCid, instance=True)
            print "Updating steps for Test Case %s" % testcase.FormattedID
            list_steps=sorted(testcase.Steps, key=lambda step: step.StepIndex)
            #Calculate what to do on the steps (how many to update, create, or delete)
            nb_steps = { 'Rally':len(testcase.Steps), 'HTML':len(Steps) } 
            nb_steps['toUpdate'] = min(nb_steps['Rally'], nb_steps['HTML'])
            nb_steps['toCreate'] = nb_steps['HTML'] - nb_steps['toUpdate']
            nb_steps['toDelete'] = nb_steps['Rally'] - nb_steps['toUpdate']
    
            #Update content of existing steps with steps from test case
            for StepIndex in range(nb_steps['toUpdate']):
                step=list_steps[StepIndex]
                teststep_fields = Steps[StepIndex]
                (teststep_fields['TestCase'], teststep_fields['ObjectID']) = (testcase.ref, step.oid)
                teststep = rally.update('TestCaseStep', teststep_fields)
            #Create new test steps when required
            for StepIndex in range(nb_steps['toCreate']):
                teststep_fields = Steps[StepIndex+nb_steps['toUpdate']]
                teststep_fields['TestCase'] = testcase.ref
                teststep = rally.put('TestCaseStep', teststep_fields)
            #Delete extra test steps
            for StepIndex in range(nb_steps['toDelete']):
                step=list_steps[StepIndex+nb_steps['toUpdate']]
                rally.delete('TestCaseStep', step.oid)
    
            #Print message for end of test step update
            message="Updated test steps for TestCase %s" % testcase.FormattedID
            message+=" (steps created: {toCreate}, updated: {toUpdate}, deleted: {toDelete})".format(**nb_steps)
            print message
    
        except RallyRESTAPIError, details:
            sys.stderr.write('Rally Error during update of Test Step:  %s \n\n' % details)
    
    #Update random list of Steps
    update_TestSteps(TCid, generate_Steps())