This repository has been archived by the owner on Aug 22, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Includes a task exercising the Programs API's program list endpoint. Also cleans up some aspects of this repo. ECOM-2627.
- Loading branch information
Renzo Lucioni
committed
Oct 27, 2015
1 parent
a930a57
commit 9a840e9
Showing
13 changed files
with
220 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,5 +2,6 @@ | |
*~ | ||
*.DS_Store | ||
*.log | ||
*.egg-info | ||
results/ | ||
data/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,55 @@ | ||
This project is the single source for public load tests for edX software component. New tests should be developed here unless there is a very good reason why that cannot be the case. Old tests should be scrubbed and moved here over time. | ||
edX Load Tests |Travis|_ | ||
========================= | ||
.. |Travis| image:: https://travis-ci.org/edx/edx-load-tests.svg?branch=master | ||
.. _Travis: https://travis-ci.org/edx/edx-load-tests | ||
|
||
This repository is home to public load tests for edX software components. New tests should be developed here. Old tests should be scrubbed and moved here over time. | ||
|
||
Installation | ||
------------ | ||
Getting Started | ||
--------------- | ||
|
||
mkvirtualenv edx-load-tests | ||
pip install -r locust/requirements.txt | ||
cd locust/$TEST_DIR | ||
locust --host="http://localhost" -f $csm | ||
If you have not already done so, create and activate a `virtualenv <https://virtualenvwrapper.readthedocs.org/en/latest/>`_. Unless otherwise stated, assume all commands below are executed within said virtualenv. | ||
|
||
Layout | ||
------ | ||
Next, install load testing requirements. | ||
|
||
Each set of tasks should be captured as a top-level locustfile named | ||
for the particular set of endpoints being tested. This toplevel file | ||
can be a flat python file (lms.py) or a directory (csm/). In the case | ||
of a directory, the __init__.py file should have (or import) the Locust | ||
subclass that defines the test. | ||
.. code-block:: bash | ||
$ pip install -r requirements.txt | ||
Start Locust by providing the Locust CLI with a target host and pointing it to the location of your desired locustfile. For example, | ||
|
||
.. code-block:: bash | ||
$ locust --host=http://localhost:8009 -f programs | ||
Repository Structure | ||
-------------------- | ||
|
||
Tests are organized into top-level packages. For examples, see ``csm`` and ``programs``. A module called ``locustfile.py`` is included inside each test package, within which a subclass of the `Locust class <http://docs.locust.io/en/latest/writing-a-locustfile.html#the-locust-class>`_ is defined. This subclass is imported into the test package's ``__init__.py`` to facilitate discovery at runtime. | ||
|
||
License | ||
------- | ||
|
||
The code in this repository is licensed under version 3 of the AGPL | ||
unless otherwise noted. Please see the `LICENSE`_ file for details. | ||
The code in this repository is licensed under the AGPLv3 unless otherwise noted. Please see `LICENSE.txt <https://github.com/edx/edx-load-tests/blob/master/LICENSE.txt>`_ for details. | ||
|
||
How To Contribute | ||
----------------- | ||
|
||
Contributions are very welcome. | ||
|
||
Please read `How To Contribute <https://github.com/edx/edx-platform/blob/master/CONTRIBUTING.rst>`_ for details. | ||
|
||
Even though they were written with ``edx-platform`` in mind, the guidelines | ||
should be followed for Open edX code in general. | ||
|
||
Reporting Security Issues | ||
------------------------- | ||
|
||
Please do not report security issues in public. Please email security@edx.org. | ||
|
||
Mailing List and IRC Channel | ||
---------------------------- | ||
|
||
.. _LICENSE: https://github.com/edx/edx-load-tests/blob/master/LICENSE | ||
You can discuss this code in the `edx-code Google Group`__ or in the ``#edx-code`` IRC channel on Freenode. | ||
|
||
__ https://groups.google.com/forum/#!forum/edx-code |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
"""Pair Locust and Slumber to allow easier load testing of REST APIs. | ||
See: http://www.renzolucioni.com/pairing-locust-and-slumber/. | ||
""" | ||
from edx_rest_api_client import exceptions | ||
from edx_rest_api_client.client import EdxRestApiClient | ||
import requests | ||
import slumber | ||
|
||
|
||
class LocustResource(slumber.Resource): | ||
"""Custom Slumber Resource which takes advantage of Locust's extended HttpSession.""" | ||
def _request(self, method, data=None, files=None, params=None): | ||
serializer = self._store['serializer'] | ||
url = self.url() | ||
|
||
headers = {'accept': serializer.get_content_type()} | ||
|
||
if not files: | ||
headers['content-type'] = serializer.get_content_type() | ||
if data is not None: | ||
data = serializer.dumps(data) | ||
|
||
# An optional argument that can be used to specify a label to use in Locust's statistics | ||
# instead of the actual URL. Can be used to group requests to the same API endpoint that vary | ||
# only by resource ID included in the URL into a single entry in Locust's statistics. For example, | ||
# requests to | ||
# 'http://localhost:8002/api/v1/resource/1/' | ||
# and | ||
# 'http://localhost:8002/api/v1/resource/2/' | ||
# might be grouped under the name: | ||
# '/api/v1/resource/:id/' | ||
# See: http://docs.locust.io/en/latest/api.html#httpsession-class/. | ||
name = params.pop('name', None) | ||
|
||
resp = self._store['session'].request( | ||
method, | ||
url, | ||
data=data, | ||
params=params, | ||
files=files, | ||
headers=headers, | ||
name=name | ||
) | ||
|
||
if 400 <= resp.status_code <= 499: | ||
exception_class = exceptions.HttpNotFoundError if resp.status_code == 404 else exceptions.HttpClientError | ||
raise exception_class('Client Error %s: %s' % (resp.status_code, url), response=resp, content=resp.content) | ||
elif 500 <= resp.status_code <= 599: | ||
raise exceptions.HttpServerError('Server Error %s: %s' % (resp.status_code, url), response=resp, content=resp.content) | ||
|
||
self._ = resp | ||
|
||
return resp | ||
|
||
|
||
class LocustEdxRestApiClient(EdxRestApiClient): | ||
resource_class = LocustResource |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
Programs Load Testing | ||
===================== | ||
|
||
This directory contains Locust tasks designed to exercise the `edX Programs Service <https://github.com/edx/programs>`_. | ||
|
||
Getting Started | ||
--------------- | ||
|
||
At this point, these load tests only require a running instance of the Programs service. | ||
|
||
Configuration | ||
------------- | ||
|
||
The load tests rely on configuration which can be specified using environment variables. | ||
|
||
==================== ========= ================================= | ||
Variable Required? Description | ||
==================== ========= ================================= | ||
PROGRAMS_SERVICE_URL No URL root for the Programs service | ||
PROGRAMS_API_URL No URL root for the Programs API | ||
JWT_AUD No JWT audience claim (aud) | ||
JWT_ISS No JWT issuer claim (iss) | ||
JWT_SECRET_KEY Yes Secret key used to sign JWTs | ||
==================== ========= ================================= | ||
|
||
If you want to use the defaults provided for these variables, make sure that these defaults are configured for your instance of the Programs service. | ||
|
||
Running | ||
------- | ||
|
||
You can run the Programs load tests from the top level ``edx-load-tests`` directory by executing something like the following: | ||
|
||
.. code-block:: bash | ||
$ JWT_SECRET_KEY=replace-me locust --host=http://localhost:8009/ -f programs | ||
There appears to be a bug in Locust preventing tests from accessing hosts using SSL. To get around this, use ``http`` as the protocol in the host URL, not ``https``. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from programs.locustfile import ProgramsUser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
"""Configuration for Programs load testing.""" | ||
import os | ||
|
||
|
||
# URL CONFIGURATION | ||
PROGRAMS_SERVICE_URL = os.environ.get( | ||
'PROGRAMS_SERVICE_URL', | ||
'http://localhost:8009' | ||
).strip('/') | ||
|
||
PROGRAMS_API_URL = os.environ.get( | ||
'PROGRAMS_API_URL', | ||
'{}/api/v1/'.format(PROGRAMS_SERVICE_URL) | ||
) | ||
# END URL CONFIGURATION | ||
|
||
|
||
# JWT CONFIGURATION | ||
JWT_AUD = os.environ.get('JWT_AUD', 'replace-me') | ||
JWT_ISS = os.environ.get('JWT_ISS', 'http://127.0.0.1:8000/oauth2') | ||
JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') | ||
|
||
if not JWT_SECRET_KEY: | ||
raise RuntimeError('A JWT secret key is required to run Programs load tests.') | ||
# END JWT CONFIGURATION |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from datetime import datetime | ||
import uuid | ||
|
||
import jwt | ||
from locust import TaskSet, task, HttpLocust | ||
|
||
from helpers.api import LocustEdxRestApiClient | ||
from programs.config import PROGRAMS_API_URL, JWT_AUD, JWT_ISS, JWT_SECRET_KEY | ||
|
||
|
||
class ProgramsTaskSet(TaskSet): | ||
"""Tasks exercising Programs functionality.""" | ||
USERNAME_PREFIX = 'load-test-' | ||
|
||
@task | ||
def list_programs(self): | ||
api = LocustEdxRestApiClient(PROGRAMS_API_URL, session=self.client, jwt=self._get_token()) | ||
api.programs.get() | ||
|
||
def _get_token(self): | ||
payload = { | ||
'preferred_username': self.USERNAME_PREFIX + str(uuid.uuid4()), | ||
'iss': JWT_ISS, | ||
'aud': JWT_AUD, | ||
'exp': datetime.utcnow(), | ||
} | ||
|
||
return jwt.encode(payload, JWT_SECRET_KEY) | ||
|
||
|
||
class ProgramsUser(HttpLocust): | ||
"""Representation of an HTTP "user" to be hatched. | ||
Hatched users will be used to attack the system being load tested. This class | ||
defines how long a simulated user should wait between executing tasks, as | ||
well as which TaskSet class should define the user's behavior. | ||
""" | ||
task_set = ProgramsTaskSet | ||
min_wait = 3 * 1000 | ||
max_wait = 5 * 1000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1 @@ | ||
# Packages needed to run any loadtest in this repo | ||
|
||
-e git+https://github.com/edx/locust.git@edx#egg=locustio[scipy] | ||
-e . | ||
jupyter | ||
runipy | ||
seaborn | ||
-r requirements/dev.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Packages required to run load tests | ||
-e git+https://github.com/edx/locust.git@edx#egg=locustio[scipy] | ||
-e . | ||
edx-rest-api-client==1.2.1 | ||
jupyter | ||
runipy | ||
seaborn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Packages required to develop load tests | ||
-r base.txt | ||
|
||
pep8==1.6.2 |