{"id":3024,"date":"2015-10-20T01:04:56","date_gmt":"2015-10-20T05:04:56","guid":{"rendered":"http:\/\/qxf2.com\/blog\/?p=3024"},"modified":"2018-03-14T10:33:19","modified_gmt":"2018-03-14T14:33:19","slug":"reporting-to-testrail-using-python","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/reporting-to-testrail-using-python\/","title":{"rendered":"Reporting automation results to TestRail using Python"},"content":{"rendered":"<p>We have been hard at work integrating our <a href=\"https:\/\/qxf2.com\/blog\/page-object-model-selenium-python\/\">Python based GUI automation framework<\/a> (that uses the Page Object pattern) with a test case management tool for reporting purposes. In this post we will show you how to report the results of your automated checks to a visual test case management tool &#8211; <a href=\"http:\/\/www.gurock.com\/testrail\/\">TestRail<\/a>. TestRail offers a <a href=\"https:\/\/secure.gurock.com\/customers\/testrail\/trial\/\">free trial<\/a> &#8211; so you can sign up for free and follow this post.<\/p>\n<hr>\n<h3>Why this post?<\/h3>\n<p>In most automated checks, we are able to judge the outcome as &#8216;pass&#8217; or &#8216;fail&#8217; by comparing the expected result to the actual result. Tracking, reporting and sharing the test results is important. Excel and email rarely scale and need a lot of maintenance. Continuous Integration servers are great for engineers &#8211; but non-technical stakeholders prefer something more visual. At Qxf2, we love TestRail &#8211; a visual test case management software. We got you started with TestRail in an <a href=\"https:\/\/qxf2.com\/blog\/testrail-get-your-tests-organized\/\">earlier post<\/a>. In this post, we are going to show you how automation can update test results directly on to TestRail.<\/p>\n<hr>\n<h3>Report automation results to TestRail using Python<\/h3>\n<p>We&#8217;ll need to perform the following steps to report test results automatically to TestRail<br \/>\n1. Get the TestRail API<br \/>\n2. Connect (authentication) to your TestRail instance<br \/>\n3. Write the logic to update test results to TestRail<br \/>\n4. Identify your test case id on TestRail<br \/>\n5. Modify your test script to report to TestRail<br \/>\n&nbsp;<br \/>\n&nbsp;<br \/>\n<strong>1. Get the TestRail API<\/strong><br \/>\nTestRail provides a useful REST API for automated tests to directly report results on to TestRail. The API provides the functionality to authenticate API requests, provides seamless JSON encoding\/decoding and has generic support for read and write requests. We will write some useful wrappers around TestRail&#8217;s official <a href=\"http:\/\/docs.gurock.com\/testrail-api2\/bindings-python\">API binding<\/a> for Python.<br \/>\nBefore we proceed, please download the <strong>testrail.py<\/strong> from <a href=\"https:\/\/github.com\/gurock\/testrail-api\/archive\/master.zip\">here<\/a>  and follow the installation <a href=\"http:\/\/docs.gurock.com\/testrail-api2\/bindings-python#setup_installation\">instructions<\/a>.<\/p>\n<p><strong>2. Connect to your TestRail instance<\/strong><br \/>\nWe prefer separating any credentials we use into <a href=\"https:\/\/qxf2.com\/blog\/dont-hardcode-usernames-and-passwords-in-your-test-scripts\/\">separate files<\/a>. For this tutorial, we have created <strong>testrail.env<\/strong> that looks something like this:<br \/>\ntestrail.env<\/p>\n<pre lang=''>\r\nTESTRAIL_URL=https:\/\/<your_instance_name>.testrail.com\r\nTESTRAIL_USER=test@abc.xyz\r\nTESTRAIL_PASSWORD=test\r\n<\/pre>\n<p>We then created a file that wraps around TestRail&#8217;s API called <strong>TestRail.py<\/strong>. In this file we implemented a method to connect to the TestRail instance.<\/p>\n<pre lang='python'>\r\n\"\"\"\r\nTestRail integration\r\n\"\"\"\r\nimport dotenv,os,testrail,Conf_Reader\r\n\r\ndef get_testrail_client():\r\n    \"Get the TestRail account credentials from the testrail.env file\"\r\n    testrail_file = os.path.join(os.path.dirname(__file__),'testrail.env')\r\n    #Get the TestRail Url\r\n    testrail_url = Conf_Reader.get_value(testrail_file,'TESTRAIL_URL')\r\n    client = testrail.APIClient(testrail_url)\r\n    #Get and set the TestRail User and Password\r\n    client.user = Conf_Reader.get_value(testrail_file,'TESTRAIL_USER')\r\n    client.password = Conf_Reader.get_value(testrail_file,'TESTRAIL_PASSWORD')\r\n\r\n    return client\r\n<\/pre>\n<p>Now we have an object that can connect to your TestRail instance!<\/p>\n<p><strong>3. Write the logic to update test results to TestRail<\/strong><br \/>\nTestRail needs to know two things to go an update a test case result:<br \/>\na. the test run id<br \/>\nb. the test case id<\/p>\n<p>We need both because we can have multiple test runs for the same set of test cases. So our script should be able to update the test results into TestRail for a particular test run and specific test case. For this we need to know the test case id and the test run id. We implemented the <strong>update_testrail<\/strong> method. This method can be called from the test script with appropriate parameters so that the test results are recorded in TestRail for the specific case id and run id.<\/p>\n<pre lang='python'>\r\ndef update_testrail(case_id,run_id,result_flag,msg=\"\"):\r\n    \"Update TestRail for a given run_id and case_id\"\r\n    update_flag = False\r\n    #Get the TestRail client account details\r\n    client = get_testrail_client()\r\n\r\n    #Update the result in TestRail using send_post function. \r\n    #Parameters for add_result_for_case is the combination of runid and case id. \r\n    #status_id is 1 for Passed, 2 For Blocked, 4 for Retest and 5 for Failed\r\n    status_id = 1 if result_flag is True else 5\r\n\r\n    if run_id is not None:\r\n        try:\r\n            result = client.send_post(\r\n                'add_result_for_case\/%s\/%s'%(run_id,case_id),\r\n                {'status_id': status_id, 'comment': msg })\r\n        except Exception,e:\r\n            print 'Exception in update_testrail() updating TestRail.'\r\n            print 'PYTHON SAYS: '\r\n            print e\r\n        else:\r\n            print 'Updated test result for case: %s in test run: %s with msg:%s'%(case_id,run_id,msg)\r\n        \r\n    return update_flag\r\n<\/pre>\n<p><strong>NOTE:<\/strong> Test case ids stay constant across test runs in TestRail. However each test run is assigned a unique id. To automatically obtain your run id based on your test run name, you can implement something similar to this code snippet:<\/p>\n<pre lang=\"python\">\r\n    def get_project_id(project_name):\r\n        \"Get the project ID using project name\"\r\n        client = get_testrail_client()\r\n        project_id=None\r\n        projects = client.send_get('get_projects')\r\n        for project in projects:\r\n            if project['name'] == project_name: \r\n                project_id = project['id']\r\n                #project_found_flag=True\r\n                break\r\n        return project_id\r\n\r\n    def get_run_id(test_run_name,project_name):\r\n        \"Get the run ID using test name and project name\"\r\n        run_id=None\r\n        client = get_testrail_client()\r\n        project_id = get_project_id(project_name)\r\n        try:\r\n            test_runs = client.send_get('get_runs\/%s'%(project_id))\r\n        except Exception,e:\r\n            print 'Exception in update_testrail() updating TestRail.'\r\n            print 'PYTHON SAYS: '\r\n            print e\r\n            return None\r\n        else:\r\n            for test_run in test_runs:\r\n                 if test_run['name'] == test_run_name:\r\n                     run_id = test_run['id']\r\n                     break\r\n            return run_id\r\n<\/pre>\n<p><strong>4. Identify your test case id on TestRail<\/strong><br \/>\nTo obtain the test case id, simply visit your project on TestRail, navigate to <strong>Test Cases<\/strong>  section and look for the integer in the ID column next to your test case.<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2015\/10\/case_ids1.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2015\/10\/case_ids1-1024x409.png\" alt=\"TestRail case ids\" width=\"1024\" height=\"409\" class=\"aligncenter size-large wp-image-3303\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2015\/10\/case_ids1-1024x409.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2015\/10\/case_ids1-300x120.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2015\/10\/case_ids1.png 1091w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p><strong>5. Modify your test script to report to TestRail<\/strong><br \/>\nNow you can modify your existing test scripts to report to TestRail. Here is a code sample that shows you how to use the method you wrote earlier:<br \/>\nTest Script<\/p>\n<pre lang='python'>\r\n#Code to automate test case goes here\r\n.\r\n.\r\n#Update TestRail\r\n    case_id = 125 #Case id of your test case \r\n    if (result_flag):\r\n        msg = \"Successfully updated the example form\"\r\n    else:\r\n        msg = \"Failed to update the example form\"\r\n    Test_Rail.update_testrail(case_id,test_run_id,result_flag,msg=msg)\r\n<\/pre>\n<hr>\n<p>Hope this post helps you offload the manual task of updating the test results in TestRail! Get all this code for free in our open-sourced <a href=\"https:\/\/github.com\/qxf2\/qxf2-page-object-model\">Python test automation framework<\/a> based on the page object pattern. We strongly recommend you check it out!<\/p>\n<hr>\n<script>(function() {\n\twindow.mc4wp = window.mc4wp || {\n\t\tlisteners: [],\n\t\tforms: {\n\t\t\ton: function(evt, cb) {\n\t\t\t\twindow.mc4wp.listeners.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tevent   : evt,\n\t\t\t\t\t\tcallback: cb\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n})();\n<\/script><!-- Mailchimp for WordPress v4.10.1 - https:\/\/wordpress.org\/plugins\/mailchimp-for-wp\/ --><form id=\"mc4wp-form-1\" class=\"mc4wp-form mc4wp-form-6165 mc4wp-form-theme mc4wp-form-theme-blue\" method=\"post\" data-id=\"6165\" data-name=\"Newsletter\" ><div class=\"mc4wp-form-fields\"><div style=\"border:3px; border-style:dashed;border-color:#56d1e1;padding:1.2em;\">\r\n  <h1 style=\"text-align: center; padding-top: 20px; padding-bottom: 20px; color: #592b1b;\">Subscribe to our weekly Newsletter<\/h1>\r\n  <input style=\"margin: auto;\" type=\"email\" name=\"EMAIL\" placeholder=\"Your email address\" required \/>\r\n  <br>\r\n  <p style=\"text-align: center;\">\r\n    <input style=\"background-color: #890c06 !important; border-color: #890c06;\" type=\"submit\" value=\"Sign up\" \/>\r\n    \r\n  <\/p>\r\n  <p style=\"text-align: center;\">\r\n    <a href=\"http:\/\/mailchi.mp\/c9c7b81ddf13\/the-informed-testers-newsletter-20-oct-2017\"><small>View a sample<\/small><\/a>\r\n  <\/p>\r\n  <br>\r\n<\/div><\/div><label style=\"display: none !important;\">Leave this field empty if you're human: <input type=\"text\" name=\"_mc4wp_honeypot\" value=\"\" tabindex=\"-1\" autocomplete=\"off\" \/><\/label><input type=\"hidden\" name=\"_mc4wp_timestamp\" value=\"1776611736\" \/><input type=\"hidden\" name=\"_mc4wp_form_id\" value=\"6165\" \/><input type=\"hidden\" name=\"_mc4wp_form_element_id\" value=\"mc4wp-form-1\" \/><div class=\"mc4wp-response\"><\/div><\/form><!-- \/ Mailchimp for WordPress Plugin -->\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>We have been hard at work integrating our Python based GUI automation framework (that uses the Page Object pattern) with a test case management tool for reporting purposes. In this post we will show you how to report the results of your automated checks to a visual test case management tool &#8211; TestRail. TestRail offers a free trial &#8211; so [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,91,90],"tags":[],"class_list":["post-3024","post","type-post","status-publish","format-standard","hentry","category-python","category-testcase-management","category-testrail"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/3024","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=3024"}],"version-history":[{"count":22,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/3024\/revisions"}],"predecessor-version":[{"id":8704,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/3024\/revisions\/8704"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=3024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=3024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=3024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}