{"id":1435,"date":"2014-09-17T03:00:03","date_gmt":"2014-09-17T07:00:03","guid":{"rendered":"http:\/\/qxf2.com\/blog\/?p=1435"},"modified":"2017-06-14T01:58:49","modified_gmt":"2017-06-14T05:58:49","slug":"jenkins-python","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/jenkins-python\/","title":{"rendered":"Python unit test integration with Jenkins"},"content":{"rendered":"<p><strong>Problem:<\/strong> Jenkins is still somewhat of a black box to testers. <\/p>\n<p>This post is for the hands on tester looking to integrate their Python unit tests with Jenkins.<\/p>\n<hr>\n<h3>Why this post?<\/h3>\n<p><a href=\"http:\/\/jenkins-ci.org\/\">Jenkins<\/a> is an extremely popular <a href=\"http:\/\/en.wikipedia.org\/wiki\/Continuous_integration\">continuous integration<\/a> tool. Jenkins is often setup and maintained by the development team or I.T. team in many companies. Testers know about Jenkins but rarely get a chance to explore Jenkins. At <a href=\"http:\/\/www.qxf2.com\/?utm_source=jenkins_python&#038;utm_medium=click&#038;utm_campaign=From%20blog\">Qxf2<\/a>, we believe in learning and exploring the tools we work with everyday. In a previous post, we showed you how to get <a href=\"https:\/\/qxf2.com\/blog\/get-started-with-jenkins\/\">started with Jenkins<\/a>. In this post, we will show you how to install and configure plugins and run some Python unit tests.<\/p>\n<hr>\n<h3>Overview<\/h3>\n<p>This post will walk you through the following steps:<br \/>\n1. Download and install Jenkins<br \/>\n2. Install and configure the required Jenkins plugins<br \/>\n3. Install Python mock and Python nose<br \/>\n4. Add Python unit test cases<br \/>\n5. Set up the project in Jenkins<br \/>\n6. Start the build<br \/>\n7. Verify the result<\/p>\n<p>We are going to be using a fairly popular Python plugin call <a href=\"https:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/ShiningPanda+Plugin\">ShiningPanda<\/a>. <\/p>\n<p><em>NOTE:<\/em> If you are new to Python unit tests, please refer to our previous blog on <a href=\"https:\/\/qxf2.com\/blog\/python-unit-checks\/\">Python unit checks<\/a> where we downloaded the <a href=\"http:\/\/www.pygame.org\/project-Python+Chess-1099-.html\">Python Chess <\/a> application and wrote a Python unit test for it.<\/p>\n<hr>\n<h3>A step by step guide<\/h3>\n<p><strong>STEP 1: <a href=\"http:\/\/jenkins-ci.org\/\">Download and install Jenkins<\/a><\/strong><br \/>\nJenkins provides installers for different operating systems. In companies, it is more common to see Jenkins hosted on a *nix system. Our best guess is that most testers use Windows. Our goal is to help you, the tester, learn about Jenkins. So we are choosing to use Windows in this example. You can download the Windows native package as a zip file. Extract the file and install Jenkins. Since we are installing Jenkins using the Windows installer, we don&#8217;t need to do anything else as the Windows installer automatically runs Jenkins as a Windows service.<\/p>\n<p>You can verify Jenkins is running as a service by launching the Services app from the Windows Start Menu and looking for a running service called &#8220;Jenkins&#8221; among the list of all windows services running on the machine.<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/services_jenkins.gif\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-774\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/services_jenkins-300x123.gif\" alt=\"Windows Service\" width=\"300\" height=\"123\" \/><\/a><\/p>\n<p>By default, Jenkins runs at http:\/\/localhost:8080\/. You can change it by editing jenkins.xml, which is located in your installation directory.<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/Jenkins.jpg\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-741\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/Jenkins-300x176.jpg\" alt=\"Jenkins\" width=\"300\" height=\"176\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/Jenkins-300x176.jpg 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/Jenkins-1024x603.jpg 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/07\/Jenkins.jpg 1177w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><strong>STEP 2: Install and configure required Jenkins Plugins to run Python Unit Test<\/strong><br \/>\nThere are various Python Plugins available to build python files in Jenkins. We will use <a href=\"https:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/ShiningPanda+Plugin\">ShiningPanda<\/a> Plugin which provides Python support to Jenkins with some useful builders.<\/p>\n<p>To install the plugin click on the <em>Manage Jenkins<\/em> link on the left-hand side of the page. On the next page click on <em>Manage Plugins<\/em> link. Finally on Plugin Manager page click on the Available tab and search for <em>ShiningPanda<\/em>. Check the checkbox for the plugin and install it.Jenkins will install the selected plugins and then take a moment to restart<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Plugin.jpg\" data-rel=\"lightbox-image-2\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Plugin-1024x487.jpg\" alt=\"Jenkins Plugin\" width=\"474\" height=\"225\" class=\"aligncenter size-large wp-image-1443\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Plugin-1024x487.jpg 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Plugin-300x142.jpg 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Plugin.jpg 1365w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p>To configure Python installations, navigate to Manage Jenkins > Configure System. Search for the Python. Select Python Installations and configure it. The <em>Name<\/em> is the name of the Python installation and<em> Home or executable<\/em> is the path to the root folder of the Python installation<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python.jpg\" data-rel=\"lightbox-image-3\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python-1024x248.jpg\" alt=\"Configure Python installation\" width=\"474\" height=\"114\" class=\"aligncenter size-large wp-image-1450\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python-1024x248.jpg 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python-300x72.jpg 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python.jpg 1070w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p><strong>STEP 3: Install Python mock and Python nose<\/strong><br \/>\nWe will use the Python mock module in our test case to mock some classes. The <a href=\"https:\/\/pypi.python.org\/pypi\/mock\">mock<\/a> module has one of my favorite features \u2013 <a href=\"http:\/\/www.toptal.com\/python\/an-introduction-to-mocking-in-python\">patch decorators<\/a>, that make it easy to mock classes. We are doing this on Python 2.7. For Python 3.x you could skip this step. To install mock, open a command prompt and run:<\/p>\n<pre lang=\"python\">pip install -U mock<\/pre>\n<p>Python <a href=\"https:\/\/nose.readthedocs.org\/en\/latest\/\">nose<\/a> extends unittest to make testing easier. By default, nose will run tests in files or directories under the current working directory whose names include &#8220;test&#8221; or &#8220;Test&#8221;. To install nose, open a command prompt and run:<\/p>\n<pre lang=\"python\">pip install nose<\/pre>\n<p><strong>STEP 4: Add Python unit test cases<\/strong><br \/>\nIn real life, you run a suite of tests. To make this example realistic, we are going to be writing three test cases. If you are already comfortable with Python nose, you can choose to run exactly one test. <\/p>\n<p><u>Test 1:<\/u> Please refer to our previous blog on <a href=\"https:\/\/qxf2.com\/blog\/python-unit-checks\/\">python unit check<\/a>  where we have written a python unit test for a <a href=\"http:\/\/www.pygame.org\/project-Python+Chess-1099-.html\">python chess app<\/a>. The test case to check whether the <em>GetListOfValidMoves<\/em> method is getting called with the arguments that we expect it to be called with. <\/p>\n<p><u>Test 2:<\/u> Check if the mocked method was called at least once with some arguments<\/p>\n<pre lang=\"python\">\r\n\"\"\"\r\nExample written for Qxf2 Services' blog post on Python Unit Checking\r\nCheck if IsCheckmate method in ChessRules class calls GetListOfValidMoves  \r\nAssert that it called at least once with some expected argument\r\n\"\"\"\r\nimport unittest, mock\r\nimport ChessRules \r\nfrom ChessBoard import ChessBoard\r\n\r\nclass CheckIsCheckmate(unittest.TestCase):\r\n    \"Class to unit check the IsCheckmate method of ChessRules.py module\"\r\n    # creating a mock for GetListOfValidMoves\r\n    @mock.patch('ChessRules.ChessRules.GetListOfValidMoves')        \r\n    def test_called_with_args(self, mockGetListOfValidMoves):\r\n        \"Unit test for ChessRules method: IsCheckmate\"\r\n\r\n        # Creating objects of Chessboard and ChessRules class and calling IsCheckmate function with each piece for initial position and \"black\" color\r\n        cb = ChessBoard(0) #Create a chess board object with the initial position\r\n        chess_rules_obj = ChessRules.ChessRules()\r\n        chess_rules_obj.IsCheckmate(cb.GetState(),\"black\")\r\n        \r\n        # Create expected_arg_calls list which is supposed to be called with GetListOfValidMoves for initial position\r\n        # IsCheckmate calls GetListOfValidMoves with arguments: board, color (who is to play?) and co-ordinates of a square with a piece on it\r\n        expected_arg_calls = []\r\n        for row in range(0,2):\r\n            for col in range(0,8):\r\n                expected_arg_calls.append(mock.call(cb.GetState(), 'black', (row, col)))\r\n                \r\n        \r\n        # assert that method was called at least once with some argument        \r\n        mockGetListOfValidMoves.assert_any_call(cb.GetState(),\"black\",(1,6))\r\n\r\n        \r\nif __name__==\"__main__\":\r\n    unittest.main()\r\n<\/pre>\n<p><u>Test 3:<\/u> Check if the mocked method was called exactly 16 times<\/p>\n<pre lang=\"python\">\r\n\"\"\"\r\nExample written for Qxf2 Services' blog post on Python Unit Checking\r\nCheck if IsCheckmate method in ChessRules class calls GetListOfValidMoves  \r\nAssert that the mocked method is called 16 times\r\n\"\"\"\r\nimport unittest, mock\r\nimport ChessRules \r\nfrom ChessBoard import ChessBoard\r\n\r\nclass CheckIsCheckmate(unittest.TestCase):\r\n    \"Class to unit check the IsCheckmate method of ChessRules.py module\"\r\n    # creating a mock for GetListOfValidMoves\r\n    @mock.patch('ChessRules.ChessRules.GetListOfValidMoves')        \r\n    def test_call_count(self, mockGetListOfValidMoves):\r\n        \"Unit test for ChessRules method: IsCheckmate\"\r\n                        \r\n        # Creating objects of Chessboard and ChessRules class and calling IsCheckmate function with each piece for initial position and \"black\" color\r\n        cb = ChessBoard(0) #Create a chess board object with the initial position\r\n        chess_rules_obj = ChessRules.ChessRules()\r\n        chess_rules_obj.IsCheckmate(cb.GetState(),\"black\")\r\n        \r\n        # Create expected_arg_calls list which is supposed to be called with GetListOfValidMoves for initial position\r\n        # IsCheckmate calls GetListOfValidMoves with arguments: board, color (who is to play?) and co-ordinates of a square with a piece on it\r\n        expected_arg_calls = []\r\n        for row in range(0,2):\r\n            for col in range(0,8):\r\n                expected_arg_calls.append(mock.call(cb.GetState(), 'black', (row, col)))\r\n                \r\n        \r\n        # check the number of times your mocked method was called\r\n        self.assertEqual(mockGetListOfValidMoves.call_count,16)\r\n        \r\n            \r\nif __name__==\"__main__\":\r\n    unittest.main()\r\n<\/pre>\n<p><strong>STEP 5: Set up the project in Jenkins<\/strong> <\/p>\n<ul>\n<li>Go to Jenkins, select &#8220;New Item&#8221;, enter a name for your build and then choose &#8220;Build a free-style software project\u00a0and click &#8220;OK&#8221;.<\/li>\n<li>We will run the project directly from our local machine. Configure the project as &#8220;None&#8221; under &#8220;Source Code Management&#8221;.<\/li>\n<li>Click on &#8220;Add Build step&#8221; and select Python Builder.<\/li>\n<li>Select the Nature as Shell and in command field enter &#8220;nosetests $Path of testcase &#8221; <\/li>\n<\/ul>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python1.jpg\" data-rel=\"lightbox-image-4\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python1-1024x610.jpg\" alt=\"Configure Python Setting for Build\" width=\"474\" height=\"282\" class=\"aligncenter size-large wp-image-1462\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python1-1024x610.jpg 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python1-300x178.jpg 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Configure-Python1.jpg 1065w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p><strong>STEP 6: Start the build<\/strong><br \/>\nGo back to your build page in Jenkins and click on &#8220;Build Now&#8221;. The Build will start and you can view the status. <\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Build.png\" data-rel=\"lightbox-image-5\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Build.png\" alt=\"Start the Jenkins Build\" width=\"474\" height=\"142\" class=\"aligncenter size-large wp-image-1457\" \/><\/a><\/p>\n<p><strong>STEP 7: Verify the result <\/strong><br \/>\nClick on Console Output to view the Result. All the 3 test cases ran and the status shows as &#8220;SUCCESS&#8221;<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Result.png\" data-rel=\"lightbox-image-6\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Result-1024x308.png\" alt=\"View result in Jenkins\" width=\"474\" height=\"142\" class=\"aligncenter size-large wp-image-1461\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Result-1024x308.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Result-300x90.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/Jenkins_Result.png 1250w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<hr>\n<p>And that brings us to the end of this tutorial on integrating your Python unit tests with Jenkins. As always, we are happy to answer any questions you may have. <\/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=\"1776207281\" \/><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>Problem: Jenkins is still somewhat of a black box to testers. This post is for the hands on tester looking to integrate their Python unit tests with Jenkins. Why this post? Jenkins is an extremely popular continuous integration tool. Jenkins is often setup and maintained by the development team or I.T. team in many companies. Testers know about Jenkins but [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38,52,51,18,66],"tags":[],"class_list":["post-1435","post","type-post","status-publish","format-standard","hentry","category-automation","category-continuous-integration","category-jenkins","category-python","category-unit-testing"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/1435","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\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=1435"}],"version-history":[{"count":41,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/1435\/revisions"}],"predecessor-version":[{"id":6277,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/1435\/revisions\/6277"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=1435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=1435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=1435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}