Responsive Ad Slot

Latest

latest

Load Testing using Jmeter and Python with pytest

Wednesday, 22 June 2022

/ by Sajjad Sarwar

 

Load Testing using Jmeter and Python with pytest



The job of APIs has evolved much in the course of recent years. No long ago, web APIs were predominantly utilized as direct combination focuses between inside frameworks. That is no longer true now a days. These days, APIs often are the core systems of an organization, one on top of which several client – web and mobile – applications are built.

When APIs were only used for back-office tasks such as extracting reports, their performance was never a key factor. However, APIs have slowly moved towards the critical path between an end-user and the service a company offers. This surge in criticality involves a direct significance: performance of APIs really matters now.

It doesn’t matter how tremendously built your front-end applications are if the API data foundations take several seconds to respond. Or even worse, if their performance is untrustworthy. Performance matters a great deal, and more so in a world of Microservice that means the source of what a client application shows is perhaps being combined from multiple APIs behind the scenes.

Pytest is our all in one functional testing solution, but after integrating the Pytest with Jmeter we will be able to perform the load and stress testing on the same capabilities with no hustle.

Software Development Engineers can leverage this solution for the UI and DB load/stress testing with minor tweaks as per nature of testing.

In this blog I will focus on describing how to successfully run a load test on your API using Jmeter and pytest. As part of this blog we will only focus on the API load testing.

We’ll start step by step till complete execution. Let’s go then!


Tool: Apache JMeter, Pycharm Community Version

Prerequisites: Java 8 or Java 9 for Apache JMeter 5.0

First we need to setup the Jmeter, to achieve that you can just execute the setup_jmeter.bat file which will automatically setup the jmeter along with all the required plugins for the load testing.

Once you are done with running batch file you will see the following information in the directory.


cd jmeter
python JMeterInstaller.py


It will install the Jmeter into the jmeter/apache-jmeter-5.2.1 (version can be updated)

Now you are done with setting up Jmeter and ready to use.

We used the pytest-bdd to achieve this and created following BDD scenario.


@api @priority_high @load
Scenario: User take the performance of the RestFul API
  
When user hit the following endpoint and calls jmeter for the performance
    
endpoint                    |
    
calendar_performance |
  Then user zip output results directory generated by Jmeter
  
And detailed report sent to "info@testopsworld.com
"

In first step we are calling an endpoint from .yml service description file.
  • Zip the Jmeter execution results
  • Send Jmeter execution results report to the respective email address
Step definition and other usage is pretty straight forward.

@when(obj_hook_utils.data_table('user hit the following endpoint and calls jmeter for the performance', pstr_fixture='data'))
def api_request_call(data):
    for items in data:
        str_endpoint = items['endpoint']
        assert obj_jmeter_performance.fetch_pre_requisite_for_jmeter(str_endpoint)

Getting the service endpoints detail from the service description file as showing below.

service_description = self.obj_config_utils.get_servicedescription("jmeter_performance" + os.sep + "jmeter_performance.yml", pstr_endpoint)
str_environment = self.obj_config_utils.fetch_base_url()
str_query_params = service_description ["queryparams"]
str_request_url = service_description ["endpoint"]
dict_payload = service_description ["payload"]
str_method = service_description ["method"]
str_token = self.str_authtoken
self.str_report_path = self.obj_jmeter_methods.call_jmeter(pstr_environment=str_environment, pstr_payload=dict_payload, pstr_endpoint=str_request_url, pstr_method=str_method, pstr_token=str_token, pstr_query_params=str_query_params)
if self.str_report_path is not "":
    return True


Calling call_jmeter method with appropriate parameters to performance the load testing. Now let’s have a look how call_jmeter method works.

In this method first section is to generate the dynamic file names for .jtl (results file), .jmx (scripts file) and Also output directories in the format (output/abc_timestamp).


str_ref_time = str(time.time()).split('.')[0]
str_jtl_path = self.str_path + r'jmeter\output\abc_' + str_ref_time + '.jtl'
str_report_path = self.str_path + r"jmeter\output\abc_" + str_ref_time
str_jmx_post_path = self.str_path + 'jmeter\jmeter_' + pstr_method.lower() + '_' + str_ref_time + '.jmx'
subprocess.call("mkdir " + str_report_path, shell=True)

Since we need .jmx file to perform the load testing, we are creating it based on the provided data.

self.update_jmx_file(pstr_method, pstr_payload, str_jmx_post_path)

Once .jmx file is updated and ready, calling the jmeter for the performance and waiting till it’s completion.

str_command = self.str_jmeter_path + r' -j "' + self.str_path + 'jmeter.log" -p "' + self.str_path + r'jmeter.properties" -t ' + str_jmx_post_path + ' -Jendpoint="' + pstr_endpoint + pstr_query_params + '" -Jmethod="' + pstr_method + '" -Jtoken="' + pstr_token + '" -Jenvironment="' + pstr_environment.split('//')[1] + '" -n -l "' + str_jtl_path + r'"'

Once execution is completed, returning the HTML output path.

# Command to generate an HTML report
self.get_html_from_jtl(str_jtl_path, str_report_path)

Next step creating the zip package of the html report.

@then(parsers.cfparse('user zip output results directory generated by Jmeter'))
def get_report_on_completion_zip():
    assert obj_jmeter_performance.zip_output_file()

In the above step definition calling zip_output_file method.

def zip_output_file(self):
    self.str_zip_outout = self.obj_jmeter_methods.zip_output_file(pstr_report_path=self.str_report_path)
    if self.str_zip_outout is not "":

Once the zip package is created next step is to send an email to the respective user with the Jmeter load testing report.


@then(parsers.cfparse('detailed report sent to "{str_email}"'))
def get_report_on_completion(str_email):
    assert obj_jmeter_performance.send_email(str_email)

Using the smtp code you can send the email using the appropriate parameters.


def send_email(self, pstr_email):
    str_attachment_link = self.write_json_file()
    arr_attached = [str_attachment_link, self.str_zip_outout]
    self.obj_email_reporting.email_report(to_email=pstr_email, arr_filepath=arr_attached)
    return True


Once all the execution is completed user will receive an email with all the details.

Once you unpack the .zip package and you will have a detailed load testing report.



Conclusion:

Jmeter is an open source solution for the load testing. Using this solution we will be able to take the load testing of the APIs in the CI/CD any time. Also can be used to take the performance for the database and UI page loading.

No comments

Post a Comment

Don't Miss
© all rights reserved
made with by sajjad