{"id":38731439,"url":"https://github.com/alexandrepasc/locust-load-starter","last_synced_at":"2026-01-17T11:26:37.579Z","repository":{"id":188746021,"uuid":"675636771","full_name":"alexandrepasc/locust-load-starter","owner":"alexandrepasc","description":"A starter project to help creating a new Locust load test project, using this as base instead of creating it from zero. It gives the ability to map all the service endpoints using the open api v3 yaml file.","archived":false,"fork":false,"pushed_at":"2024-03-17T20:07:35.000Z","size":63,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-03-17T21:28:38.539Z","etag":null,"topics":["load-testing","locust","locustio","python","python3","qa","qa-automation","test-automation","testing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexandrepasc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-08-07T11:30:56.000Z","updated_at":"2024-03-17T21:28:40.807Z","dependencies_parsed_at":"2023-08-16T19:16:01.591Z","dependency_job_id":"a67cea65-d1aa-4b03-b3c1-6e66599cefdf","html_url":"https://github.com/alexandrepasc/locust-load-starter","commit_stats":null,"previous_names":["alexandrepasc/locust-load-starter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/alexandrepasc/locust-load-starter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrepasc%2Flocust-load-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrepasc%2Flocust-load-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrepasc%2Flocust-load-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrepasc%2Flocust-load-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexandrepasc","download_url":"https://codeload.github.com/alexandrepasc/locust-load-starter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandrepasc%2Flocust-load-starter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28507401,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T10:25:30.148Z","status":"ssl_error","status_checked_at":"2026-01-17T10:25:29.718Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["load-testing","locust","locustio","python","python3","qa","qa-automation","test-automation","testing"],"created_at":"2026-01-17T11:26:37.464Z","updated_at":"2026-01-17T11:26:37.536Z","avatar_url":"https://github.com/alexandrepasc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# locust-load-starter\n\u003c!-- TOC --\u003e\n* [locust-load-starter](#locust-load-starter)\n  * [Introduction](#introduction)\n  * [Getting Started](#getting-started)\n  * [Build and Test](#build-and-test)\n    * [Import Endpoints](#import-endpoints)\n    * [Import Flow](#import-flow)\n    * [Execute Locust Tests](#execute-locust-tests)\n  * [Contribute](#contribute)\n  * [Appendix](#appendix)\n    * [Open API v3 yaml example](#open-api-v3-yaml-example)\n    * [Helping commands](#helping-commands)\n\u003c!-- TOC --\u003e\n## Introduction\nThis repository aims to ease the creation of a load testing project by mapping the api automatically from the OpenAPI v3 \n`yaml` or `json` file.\n\nDepending on the tests that will be done, the mapping of multiple requests can be cumbersome, reading the API documentation \nand mapping the required endpoints and parameters to the test project. The main idea here was to reduce that step and be \nable o ramp up the test creation.\n\nThis project is developed to use the [Locust](https://locust.io/) load testing framework, and all that will be generated \nby the script will use that framework. This can be used as the base for a new performance testing project by just copying the \ncontent of this repository to the new repository base folder since this is not done with a product in mind.\n\nAnother functionality that this has is to generate a *Locust task* file and function using a `har` file. This is useful when \nthe performance test is targeting a service that has a web interface. So we can use a web browser and create the flow that \nwe need to use in the test, export the *dev tools network* as a `har` file, and use that file to generate the task. This \nwill use the `har` file requests and the endpoints files generated by the other script.\n\n## Getting Started\nTo use this project install [Python](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installation/). \nAfter that install the requirements using `pip` and the `requirements.txt` file (`pip install -r requirements.txt`).\n\nAfter this we are set to go.\n\n## Build and Test\n### Import Endpoints\nTo use this as a base for a new load testing project get the *spec* file (`.yml`, `.yaml` or `json`) from the API documentation, \nif using the Swagger template the `schema` url and/or a button to access the `schema` should be available.\n\nThen execute the Python script `scripts/generate_endpoints.py` with the `-f` argument with the full path to the downloaded \nfile. The script will create in the root of the project the `endpoints` folder and in it build the sub-folder with the files \nmapping the information retrieved in the *spec* file.\n- `python scripts/generate_endpoints.py -h`\n- `python scripts/generate_endpoints.py -f /full/path/doc.yml`\n\nThe sub-folders created will use the same structure as the API path, this was the easy way to organize the files and not \nkeep all of them in the same folder.\n\nFor each endpoint it will create a sub-folder, in it a file with the name given in the *spec*, in the file a variable \nwith the endpoint and a `class`. The `class` will have functions with all the API methods, in them the locust \nimplementation and the returning response.\n\n```python\nENDPOINT = \"/pets\"\n\n\n#  This class contains a list of the functions for this endpoint with all the\n#  requests that were exported from the swagger spec file. To use this you\n#  need to instantiate the class and pass the locust into it and after that we\n#  are able to start to build the tests.\nclass Pets:\n    #  Initialize the class with the locust instance.\n    def __init__(self, loc: locust.user.users):\n        self.loc = loc\n\n    def get_listPets(self,\n              params: dict[str, any] = None,\n              headers: dict[str, any] = None,\n              cookies: CookieJar = None,\n              auth: tuple[str, str] = None,\n              json: any = None,\n              data: dict[str, any] = None,\n              files: dict[str, any] = None,\n              redirect: bool = False,\n              verify: bool = True):\n\n        response = self.loc.client.get(\n            ENDPOINT,\n            params=params,\n            headers=headers,\n            cookies=cookies,\n            auth=auth,\n            json=json,\n            data=data,\n            files=files,\n            name=\"get_listPets\",\n            allow_redirects=redirect,\n            verify=verify\n        )\n\n        return response\n```\n\nIn case the endpoint method has parameter the `params` argument to the python method will be added as a file listing the \nparameters for that endpoint method.\n\n```python\n#  List of all the parameters exposed in the swagger file, with a comment\n#  referring the type, that can be used when creating the test requests. The\n#  name of this file is linked with a request function in the class of\n#  this folder.\nlimit = \"limit\"  # integer\n```\n\nWith this set we can create the locust `tasks` in a separated file and folder, instantiating the needed class and using \nthe methods, with all the necessary arguments, to do the calls and build the load test(s).\n\nDepending on the test(s) that will be used we could create a folder in the project (like `tasks`), in it the tasks using \nthe generated methods and in the root project folder the test file calling the tasks created.\n\n- `/tasks/example_task_1.py`\n```python\nfrom locust import TaskSet, task\n\nfrom endpoints.pets.pets import Pets\n\n\nclass GetPetsList(TaskSet):\n    @task\n    def get_pets_list(self):\n        pets: Pets = Pets(self)\n\n        pets.get_listPets()\n```\n\n- `/tasks/example_task_2.py`\n```python\nfrom locust import TaskSet, task\n\nfrom endpoints.pets.pets import Pets\n\n\nclass GetPetDetail(TaskSet):\n    @task\n    def get_pets_list(self):\n        pets: Pets = Pets(self)\n\n        pets.get_showPetById_id(id=\"pet_id\")\n```\n\n- `/example_test.py`\n```python\nfrom locust import HttpUser\n\nfrom tasks.example_task_1 import GetPetsList\nfrom tasks.example_task_2 import GetPetDetail\n\n\nclass LoadTest(HttpUser):\n\n    tasks = {\n        GetPetsList: 1,\n        GetPetDetail: 2\n    }\n```\n\n### Import Flow\nTo create a `task` with a sequence of *api* calls, open the *dev tools* of a web browser, do the user actions in the web \npage that you want to replicate in the test. Then open the *network* tab of the *dev tools* and export it in the *HTTP \nArchive format* (aka `har`).\n\nAfter importing the endpoints with the previous script execute the `scripts/generate_flow.py` with the flag `-f` and the \nfull path to the `.har` file, and the `-e` with the full path of the `endpoints` folder created by the `generate_endpoints.py` \nscript. Both the flags are required.\n\n- `python scripts/generate_flow.py -h`\n- `python scripts/generate_flow.py -f /path/to/the/file.har -e /path/to/the/endpoints/folder`\n\nThe script will create a folder called `tasks`, in case it doesn't exist, in the parent folder of the script folder (`../tasks`). \nIn that folder it will create a python file with named `flow_` and a sequence number, this enables the user to import multiple \nflows without the need of re-naming the files. The created file will have a *class* with the *Locust TaskSet* and a function \nwith the *Locust* tag `task`.\n\nIn the `task` function for each *api* call in the `.har` file the correct endpoint function invocation will be set. In case \nthe call has a *request body* it will be added, as in the case of *parameters*. All the necessary imports will be created \nto this file.\n\nThe generated file has the same structure of the example tasks in that the project has and that are described in the previous \nsection of this document.\n\n**PS:**\n- At the moment the requests `headers` are not added to the flow as any `cookies`, since both could cary any authorization \ntoken that should expire setting the test un-usable.\n- There might be some issues creating the flow caused by wrongly implementation from the web interface and/or the *OpenAPI* \nfile being outdated, so bear in mind open the created file to be sure that it is ok.\n- In case the flow has any authentication, the logic to get the authorization tokens and the use of them in the *api* calls \nneed to be created manually, there is no automation regarding this.\n\n### Execute Locust Tests\nThere is another script in this repository called `run_tests.py`, this was created to be able to execute unattended tests \nand be able to have the reports with some important information to help creating a manual report after. In cases that \nthere is a necessity to execute multiple tests in a row and after the execution a manual report needs to be created with \nthe summary of all the tests, the timestamp, the users, time,... and all the locust reports are important. With this script \nall of this information will be in the `html` and `csv` files name automatically, without any need to set that when starting \nthe test. This script will create the `reports` folder in the location where the script is stored.\n\n- `python run_tests.py -h`\n- `python run_tests.py -u 50 -r 5 -t 5m -H https://asd.com -f /path/example_test.py`\n\nThis script has a limited number of flags and in some case more configurations need to be passed to the *Locus* execution. \nTo give the ability to add more configurations to the test execution the tester can use the flag `-e`/`--extra` where the \nuser is able to pass any of the un-supported flags directly to *Locust*. The value(s) passed to these flags needs to be \nenclosed in quotes.\n\n- `python run_tests.py -e \"--loglevel ERROR --logfile ./test.log\"`\n\n## Contribute\nThis was done taking in consideration some of the obstacles that were felt during the creation and execution of load tests \nin a given environment, it will not be a tool to rule them all. So new contributions will be gladly accepted from the \ncommunity.\n\nTo contribute, report a bug, or propose an improvement use an `Issue` to expose it and generate a discussion. Describe \nthe best the idea, link relevant information, and in case there is already a branch with the change link it in the `Issue`.\n\nHope this helps!!!\n\n## Appendix\n### Open API v3 yaml example\n```yaml\nopenapi: \"3.0.0\"\ninfo:\n  version: 1.0.0\n  title: Swagger Petstore\n  license:\n    name: MIT\nservers:\n  - url: http://petstore.swagger.io/v1\npaths:\n  /pets:\n    get:\n      summary: List all pets\n      operationId: listPets\n      tags:\n        - pets\n      parameters:\n        - name: limit\n          in: query\n          description: How many items to return at one time (max 100)\n          required: false\n          schema:\n            type: integer\n            maximum: 100\n            format: int32\n      responses:\n        '200':\n          description: A paged array of pets\n          headers:\n            x-next:\n              description: A link to the next page of responses\n              schema:\n                type: string\n          content:\n            application/json:    \n              schema:\n                $ref: \"#/components/schemas/Pets\"\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Error\"\n    post:\n      summary: Create a pet\n      operationId: createPets\n      tags:\n        - pets\n      responses:\n        '201':\n          description: Null response\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Error\"\n  /pets/{petId}:\n    get:\n      summary: Info for a specific pet\n      operationId: showPetById\n      tags:\n        - pets\n      parameters:\n        - name: petId\n          in: path\n          required: true\n          description: The id of the pet to retrieve\n          schema:\n            type: string\n      responses:\n        '200':\n          description: Expected response to a valid request\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Pet\"\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Error\"\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      required:\n        - id\n        - name\n      properties:\n        id:\n          type: integer\n          format: int64\n        name:\n          type: string\n        tag:\n          type: string\n    Pets:\n      type: array\n      maxItems: 100\n      items:\n        $ref: \"#/components/schemas/Pet\"\n    Error:\n      type: object\n      required:\n        - code\n        - message\n      properties:\n        code:\n          type: integer\n          format: int32\n        message:\n          type: string\n```\n\n### Helping commands\n**Python linter**\n- `pycodestyle scripts/`\n\n**Execute endpoints generator**\n- `python scripts/generate_endpoints.py -f \"/home/path/Downloads/petstore.yaml\"`\n\n**Execute flow generator**\n- `python scripts/generate_flow.py -f /home/path/Downloads/petstore.har -e /home/path/locust-load-starter/endpoints`\n\n**Execute runner**\n- `python run_tests.py -u 5 -r 5 -t 5m -f example_test.py -H https://domain.com`\n\n**Locust execution**\n- `locust -t 1s -u 1 -f example_test.py --headless -H https://domain.com --loglevel DEBUG --logfile asd`","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandrepasc%2Flocust-load-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexandrepasc%2Flocust-load-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandrepasc%2Flocust-load-starter/lists"}