Skip to content

Commit

Permalink
Add tests regarding issue #3
Browse files Browse the repository at this point in the history
  • Loading branch information
ronlut committed Jan 16, 2021
1 parent a1ab976 commit c871041
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 2 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Build

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.4, 3.5, 3.6, 3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.setup.version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Lint with flake8
run: |
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=13 --max-line-length=127 --statistics
- name: Install dependencies
run: |
pip install -r requirements.txt -r requirements.test.txt
- name: Test with pytest
run: |
pytest tests/
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ celerybeat.pid

# Environments
.env
.venv
.venv*
env/
venv/
venv*/
ENV/
env.bak/
venv.bak/
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
include MANIFEST.in
include requirements.txt
include requirements.test.txt
include tests *
include README.md
include LICENSE
3 changes: 3 additions & 0 deletions requirements.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
requests
pytest
pytest-benchmark
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def parse_requirements(filename):
lineiter = (line.strip() for line in open(filename))
return [line for line in lineiter if line and not line.startswith("#")]


setup(
name='Flask-Inflate',
version='0.3',
Expand All @@ -26,6 +27,8 @@ def parse_requirements(filename):
include_package_data=True,
platforms='any',
install_requires=parse_requirements('requirements.txt'),
test_suite="tests",
tests_require=parse_requirements('requirements.test.txt'),
classifiers=[
'Framework :: Flask',
'Environment :: Web Environment',
Expand Down
Empty file added tests/__init__.py
Empty file.
79 changes: 79 additions & 0 deletions tests/test_performance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import gzip
import json
import random

import pytest
from flask import Flask, request, jsonify
from flask_inflate import inflate

app = Flask(__name__)


@app.route('/naive', methods=["POST"])
def without_inflate():
json_payload = gzip.decompress(request.get_data()) if request.content_encoding == "gzip" else request.get_data()
json.loads(json_payload)
return jsonify("OK")


@app.route('/inflate', methods=["POST"])
@inflate
def with_inflate():
# I could've used .get_json() or .json here but just to be explicit about the fact it's doing the same
# as the naive route
json.loads(request.get_data())
return jsonify("OK")


@pytest.fixture
def client():
with app.test_client() as client:
yield client


def generate_compressed_payload(n_keys):
random_json = {
"random_text{}".format(i): ' '.join(random.choice(["some", "repeating", "words"]) for _ in range(150))
for i in range(n_keys)
}

raw_json = json.dumps(random_json).encode("utf-8")
return gzip.compress(raw_json)


@pytest.fixture
def gzipped_payload():
yield generate_compressed_payload(1000)


def test_inflate(gzipped_payload, client, benchmark):
send_request(client, gzipped_payload, False, True) # warmup
result = benchmark.pedantic(send_request, args=(client, gzipped_payload), kwargs={"naive": False, "compressed": True}, rounds=1000)
assert result == "OK"


def test_naive(gzipped_payload, client, benchmark):
send_request(client, gzipped_payload, True, True)
result = benchmark.pedantic(send_request, args=(client, gzipped_payload), kwargs={"naive": True, "compressed": True}, rounds=1000)
assert result == "OK"


def send_request(_client, payload, naive=False, compressed=True):
headers = {"Content-Type": "application/json"}
if compressed:
headers["Content-Encoding"] = "gzip"

path = 'naive' if naive else 'inflate'
return _client.post('http://localhost:5000/{}'.format(path), data=payload, headers=headers).json


if __name__ == '__main__':
import cProfile

with app.test_client() as client:
payload = generate_compressed_payload(1000)

send_request(client, payload, True, True) # warmup
send_request(client, payload, False, True) # warmup
cProfile.run('send_request(client, payload, True, True)', sort='cumtime')
cProfile.run('send_request(client, payload, False, True)', sort='cumtime')

0 comments on commit c871041

Please sign in to comment.