Search code examples
pythontestrail

Problems matching values from nested dictionary


In TestRail, I have created several testruns. When I execute:

test_runs = client.send_get('get_runs/1')
pprint(test_runs)

The following results are returned:

{'_links': {'next': None, 'prev': None},
 'limit': 250,
 'offset': 0,
 'runs': [{'assignedto_id': None,
           'blocked_count': 0,
           'completed_on': None,
           'config': None,
           'config_ids': [],
           'created_by': 1,
           'created_on': 1651790693,
           'custom_status1_count': 0,
           'custom_status2_count': 0,
           'custom_status3_count': 0,
           'custom_status4_count': 0,
           'custom_status5_count': 0,
           'custom_status6_count': 0,
           'custom_status7_count': 0,
           'description': None,
           'failed_count': 1,
           'id': 13,
           'include_all': False,
           'is_completed': False,
           'milestone_id': None,
           'name': '2022-05-05-testrun',
           'passed_count': 2,
           'plan_id': None,
           'project_id': 1,
           'refs': None,
           'retest_count': 0,
           'suite_id': 1,
           'untested_count': 0,
           'updated_on': 1651790693,
           'url': 'https://xxxxxxxxxx.testrail.io/index.php?/runs/view/13'},
          {'assignedto_id': None,
           'blocked_count': 0,
           'completed_on': 1650989972,
           'config': None,
           'config_ids': [],
           'created_by': 5,
           'created_on': 1650966329,
           'custom_status1_count': 0,
           'custom_status2_count': 0,
           'custom_status3_count': 0,
           'custom_status4_count': 0,
           'custom_status5_count': 0,
           'custom_status6_count': 0,
           'custom_status7_count': 0,
           'description': None,
           'failed_count': 0,
           'id': 9,
           'include_all': False,
           'is_completed': True,
           'milestone_id': None,
           'name': 'This is a new test run',
           'passed_count': 0,
           'plan_id': None,
           'project_id': 1,
           'refs': None,
           'retest_count': 0,
           'suite_id': 1,
           'untested_count': 3,
           'updated_on': 1650966329,
           'url': 'https://xxxxxxxxxx.testrail.io/index.php?/runs/view/9'}],
 'size': 2}

In my code, I am trying to scan through all of the resulting testruns, locate the testrun I'm interested in by matching the testrun name, and then have the ID for the testrun returned.

from pprint import pprint
from testrail import *


class connecting():
    def connectPostRun(self):
        client = APIClient('https://xxxxxxxxxx.testrail.io')
        client.user = '[email protected]'
        client.password = 'abc123'

        test_run_name = '2022-05-05-testrun'

        test_runs = client.send_get('get_runs/1')
        pprint(test_runs)

        for test_run in test_runs:
            if test_run['name'] == test_run_name:
                run_id = test_run['id']
                break

        return run_id
        pprint(run_id)

c=connecting()
c.connectPostRun()

Executing the code as is now results in the following error:

    if test_run['name'] == test_run_name:
TypeError: string indices must be integers

Solution

  • You're looping over the wrong part of the datastructure that the function returned. The loop for test_run in test_runs: only iterates over the keys of the top-level dictionary ("_links", "limit", etc.).

    You want to be looping over test_runs['runs'], which will give you dictionaries with the "name" keys you're matching against. Try making your loop look like this:

        for test_run in test_runs['runs']:
            if test_run['name'] == test_run_name:
                run_id = test_run['id']
                break
    

    I'd note that there's a potential problem in this code, that if you never find a matching run, the run_id variable will never be assigned to, so the return statement at the end of the function will raise an exception. If you think that could ever happen, you should probably either set a default value, or perhaps raise your own exception (with a more clear message) if you get into that situation.