{"id":11087,"date":"2019-08-13T02:29:24","date_gmt":"2019-08-13T06:29:24","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=11087"},"modified":"2019-08-13T02:29:24","modified_gmt":"2019-08-13T06:29:24","slug":"using-cprofile-to-get-some-useful-statistics-for-python-based-tests","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/using-cprofile-to-get-some-useful-statistics-for-python-based-tests\/","title":{"rendered":"Using cProfile to get some useful statistics for Python based tests"},"content":{"rendered":"<p>In general, when we have some performance problem with our code, profilers can be used to help identify where the problem actually lies. It can be used to check how long the functions defined in your code took to execute, how many times a particular function is being called etc. We were able to use cProfile to find out some useful information about our tests. In case you want to get some additional information about your test with some minor code changes you should find this blog useful.<\/p>\n<hr \/>\n<h3>What is the need for cProfile in testing?<\/h3>\n<p>We always wanted to check how many times some tests function were getting called in our GUI tests. Also in case, we end up having multiple exceptions it made sense to see how many times which exceptions were getting called. <a href=\"https:\/\/docs.python.org\/2\/library\/profile.html\">cProfile<\/a> is one of the popular python based profiling tool. When we used cProfile we got some useful ideas which we could implement on our <a href=\"https:\/\/github.com\/qxf2\/qxf2-page-object-model\">python-based testing framework<\/a>. We decided to pen down the same in this post. You can try using cProfile with your own tests and framework based on your use-case.<\/p>\n<p>Some of the below stats related to what functions are getting called, how many times and how long a function call takes were useful for our case.<\/p>\n<ul>\n<li>ncalls \u2013 how many times the function\/method has been called<\/li>\n<li>tottime \u2013 the total time in seconds excluding the time of other functions\/methods<\/li>\n<li>percall \u2013 average time to execute function (per call)<\/li>\n<li>cumtime \u2013 the total time in seconds includes the times of other functions it calls<\/li>\n<li>percall \u2013 similar to the previous percall, however this one includes network delays,sleep<\/li>\n<\/ul>\n<hr \/>\n<h3>How to use cProfile<\/h3>\n<p>We will use cProfile to get some useful stats for our GUI tests which is built based on <a href=\"https:\/\/github.com\/qxf2\/qxf2-page-object-model\">Python Selenium Page Object Model Framework.<\/a>. cProfile is included in Python&#8217;s standard library.<\/p>\n<hr \/>\n<p><strong>Coding changes in Python Framework for profiling:<\/strong><br \/>\nTo add profiling to your code you just need 5 to 6 lines of additional code. We need to import cProfile first, then create a profile object, enable it, disable it after the function we want to profile has been called and save the stats to a file. You can look at the example below.<\/p>\n<pre lang=\"python\">import cProfile, pstats\r\npr = cProfile.Profile()\r\npr.enable()\r\n\r\ntest_example_form()---your code\r\n\r\npr.disable()\r\nps = pstats.Stats(pr).print_stats()\r\n\r\n<\/pre>\n<hr \/>\n<p><strong> Statistics to know how many time a particular function has been called<\/strong><br \/>\nIn our Qxf2 based framework test, there is a test case named test_successive_form_creation. We are trying to fill in details like name, phone, email, etc and then submit the form multiple times. In case we need to get details on how many times the form was submitted we can get the details using the above code. You may need to filter out the function names. Under statistics we have the last column named as &#8220;filename:lineno(function)&#8221;, we can filter out the required function name by a search.<\/p>\n<figure id=\"attachment_11378\" aria-describedby=\"caption-attachment-11378\" style=\"width: 1543px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_statistics.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\/2019\/08\/cprofile_statistics.png\" alt=\"\" width=\"1543\" height=\"208\" class=\"size-full wp-image-11378\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_statistics.png 1543w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_statistics-300x40.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_statistics-768x104.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_statistics-1024x138.png 1024w\" sizes=\"auto, (max-width: 1543px) 100vw, 1543px\" \/><\/a><figcaption id=\"caption-attachment-11378\" class=\"wp-caption-text\">cprofile statistics<\/figcaption><\/figure>\n<hr \/>\n<p><strong> Looking at the statistics to know how many times Exception has been caught<\/strong><\/p>\n<p>With cProfile statistics, we can track the Exceptions too. However, in Our framework, we have some wrapper(Wrapit.py), containing Exception Handlers so we can&#8217;t exactly see the exception. The Exception handler decorator is used to capture exceptions. This decorator is used, when an error occurs to prevents tests from stopping. If we want to check how many times exception handler in Wrapit.py got called, we can test the test_example_form with some missing info. Since our framework uses a testrail util to submit test results to testrail, we will try to report test results without passing testrail id. Now we can check the cprofile statistics to get this information as shown below:<\/p>\n<p><figure id=\"attachment_11379\" aria-describedby=\"caption-attachment-11379\" style=\"width: 1551px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_exception.png\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_exception.png\" alt=\"\" width=\"1551\" height=\"190\" class=\"size-full wp-image-11379\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_exception.png 1551w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_exception-300x37.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_exception-768x94.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofile_exception-1024x125.png 1024w\" sizes=\"auto, (max-width: 1551px) 100vw, 1551px\" \/><\/a><figcaption id=\"caption-attachment-11379\" class=\"wp-caption-text\">cprofile_exception<\/figcaption><\/figure><br \/>\nAlso in case you want to reuse the statistics from the file, you may want to save it to a readable file and reuse it. For more details of how to save the statistics in a csvfile, you can refer to <a href=\"https:\/\/qxf2.com\/blog\/saving-cprofile-stats-to-a-csv-file\/\">our blog<\/a>.<\/p>\n<hr \/>\n<h3>Using cprofilev as a wrapper on command line:<\/h3>\n<p>We also found some cool tool to visually view the cProfile stats better. <a href=\"https:\/\/github.com\/ymichael\/cprofilev\">cprofilev<\/a> is a simple way of profiling your Python program. When you run python code with cprofilev from the command line, it gives you output on html page running on http:\/\/localhost:4000. When you run your code, it opens up 4000 port for profile statistics. User can view the same on that port. The beauty of cprofilev is you can sort the statics, as well as you can view particular function statistics just by clicking on that particular function.<\/p>\n<p>Installation of cprofilev:<\/p>\n<pre lang=\"python\">\r\npip install cprofilev\r\n<\/pre>\n<p>We can run our code with cprofilev as below:<\/p>\n<pre lang=\"python\">\r\npython -m cprofilev test_example_form.py\r\n<\/pre>\n<figure id=\"attachment_11363\" aria-describedby=\"caption-attachment-11363\" style=\"width: 1732px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofilev_new_example-1.png\" 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\/2019\/08\/cprofilev_new_example-1.png\" alt=\"\" width=\"1732\" height=\"480\" class=\"size-full wp-image-11363\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofilev_new_example-1.png 1732w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofilev_new_example-1-300x83.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofilev_new_example-1-768x213.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/08\/cprofilev_new_example-1-1024x284.png 1024w\" sizes=\"auto, (max-width: 1732px) 100vw, 1732px\" \/><\/a><figcaption id=\"caption-attachment-11363\" class=\"wp-caption-text\">cprofilev statistics<\/figcaption><\/figure>\n<p>Hope you find this article useful!!<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In general, when we have some performance problem with our code, profilers can be used to help identify where the problem actually lies. It can be used to check how long the functions defined in your code took to execute, how many times a particular function is being called etc. We were able to use cProfile to find out some [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[194,18,61],"tags":[],"class_list":["post-11087","post","type-post","status-publish","format-standard","hentry","category-cprofile","category-python","category-testing"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/11087","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\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=11087"}],"version-history":[{"count":45,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/11087\/revisions"}],"predecessor-version":[{"id":11389,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/11087\/revisions\/11389"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=11087"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=11087"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=11087"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}