python-docs-samples
python-docs-samples copied to clipboard
Possible improvements to GCF integration tests
In which file did you encounter the issue?
https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/functions/helloworld/sample_http_test_integration.py
Describe the issue
Based on issues described in https://github.com/GoogleCloudPlatform/functions-framework-python/issues/97, there is a simpler / less brittle integration test we could prescribe here (that is used by the Function Framework's own test suite as well.)
Instead of starting background processes, the framework provides a test client that can directly invoke the underlying WSGI application.
Instead of:
def test_args():
name = str(uuid.uuid4())
port = 8080 # Each functions framework instance needs a unique por
process = subprocess.Popen(
[
'functions-framework',
'--target', 'hello_http',
'--port', str(port)
],
cwd=os.path.dirname(__file__),
stdout=subprocess.PIPE
)
# Send HTTP request simulating Pub/Sub message
# (GCF translates Pub/Sub messages to HTTP requests internally)
BASE_URL = os.getenv('BASE_URL')
retry_policy = Retry(total=6, backoff_factor=1)
retry_adapter = requests.adapters.HTTPAdapter(
max_retries=retry_policy)
session = requests.Session()
session.mount(BASE_URL, retry_adapter)
name = str(uuid.uuid4())
res = requests.post(
BASE_URL,
json={'name': name}
)
assert res.text == 'Hello {}!'.format(name)
# Stop the functions framework process
process.kill()
process.wait()
This would become something like the following (untested):
def test_args():
name = str(uuid.uuid4())
target = "hello_http"
source = os.path.dirname(__file__) / "main.py"
client = create_app(target, source).test_client()
resp = client.post("/my_path", json={'name': name})
assert resp.status_code == 200
assert resp.data == b'Hello {}!'.format(name)
This avoids invoking gunicorn/flask's HTTP servers entirely, which is arguably makes this a less "complete" integration test, but probably more ergonomic (and should produce the same results) as what is already suggested.
(cc @ace-n)
Got it working!
import flask
from functions_framework import create_app
def test_integration():
app = create_app('my_function')
app.testing = True # bubble exceptions
client = app.test_client()
res: flask.response = client.post('/', json={'hello': 'world'})
assert res.status_code == 200
I get how people might want to perform their integration tests with a language agnostic tool. But for me this is perfect :) Thanks @di
@di happy to make this change if you and @grant are both in favor. 🙂
@ace-n Sounds like a python GCF testing best practice we can add to our python samples.
I got back here to get this piece of code again. I think this belongs in the oficial docs
Unassigning this, as I'm quite swamped at the moment.
(This may be a good candidate for a future bug burn-down.)