Skip to content

Instantly share code, notes, and snippets.

@arvindsree
Created January 9, 2024 22:13
Show Gist options
  • Save arvindsree/c89da7d319843bf7e82973968bd5c1a7 to your computer and use it in GitHub Desktop.
Save arvindsree/c89da7d319843bf7e82973968bd5c1a7 to your computer and use it in GitHub Desktop.
Pytest service
#!/usr/bin/python3
import sys
import re
import logging
import importlib
import pytest
import flask
from cheroot.wsgi import Server as CherryPyWSGIServer
from flask import Flask
LOG = logging.getLogger(__name__)
APP = Flask(__name__)
@APP.route("/", methods=["GET", "POST"])
def handle_req():
try:
return _handle_req()
except Exception as err:
LOG.exception(str(err))
return flask.make_response(str(err), 400)
def _handle_req():
try:
args = flask.request.form
cmd = args['cmd']
reload = args.get("reload")
except (KeyError, TypeError):
return flask.make_response('Pass the cmd argument. Example: curl http://127.0.0.1 -d cmd=test.py}', 400)
if reload:
try:
importlib.reload(sys.modules[reload])
except Exception as err:
LOG.exception(err)
return str(pytest.main(cmd.split()))
def main():
logging.basicConfig(level=logging.INFO)
LOG.info("Starting service")
try:
port = int(sys.argv[1])
except ValueError:
LOG.error('need an integer port. Defaulting to 80')
port = 80
except IndexError:
port = 80
try:
server = CherryPyWSGIServer(
bind_addr=("127.0.0.1", port),
wsgi_app=APP,
request_queue_size=5,
accepted_queue_size=-1,
numthreads=10,
)
server.start()
except KeyboardInterrupt:
server.stop()
return
if __name__ == "__main__":
main()
@arvindsree
Copy link
Author

arvindsree commented Jan 9, 2024

Description:
This runs as a daemon and reuses the modules that are imported to speed up your pytest runs. The test run will only need to re-import the modules that have changed. This is useful when the modules being imported are very large, when the actual test run is short and importing the modules, each time take a lot longer.

Requirements:
flask, cherrypy

Usage:
Run the service using the command in your project root.
Defaults to port 80 if no port argument is passed

pytest_service.py
or
pytest_service.py 5000

Run the pytest command that you would normally run using curl as the cmd argument

curl http://127.0.0.1  -d cmd=" -s -o log_cli=1 -o log_cli_level=INFO folder/xx_test.py"
curl http://127.0.0.1:5000  -d cmd=" -s -o log_cli=1 -o log_cli_level=INFO xx_test.py:::test_yy" -d reload=xx_test
curl http://127.0.0.1:5000  -d cmd=" -s -o log_cli=1 -o log_cli_level=INFO xx_test.py" -d reload="module2.module1"

The test output will be visible in the service itself.

Arguments:
cmd: The command you would pass to pytest
reload: Optional argument where you specify the name of the module that changed to re-import it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment