diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index 74329dba..58c7b6c1 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -256,9 +256,15 @@ def handle_none(rv): # Extract the target function from the source file if not hasattr(source_module, target): + non_target_functions = ", ".join( + "'{attr}'".format(attr=attr) + for attr in dir(source_module) + if isinstance(getattr(source_module, attr), types.FunctionType) + ) + raise MissingTargetException( - "File {source} is expected to contain a function named {target}".format( - source=source, target=target + "File {source} is expected to contain a function named '{target}' (found: {non_target_functions} instead)".format( + source=source, target=target, non_target_functions=non_target_functions ) ) function = getattr(source_module, target) diff --git a/tests/test_functions.py b/tests/test_functions.py index 176e2bb1..2969f5c8 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -277,7 +277,8 @@ def test_invalid_function_definition_multiple_entry_points(): create_app(target, source, "event") assert re.match( - "File .* is expected to contain a function named function", str(excinfo.value) + "File .* is expected to contain a function named 'function' \(found: 'fun', 'myFunctionBar', 'myFunctionFoo' instead\)", + str(excinfo.value), ) @@ -289,7 +290,7 @@ def test_invalid_function_definition_multiple_entry_points_invalid_function(): create_app(target, source, "event") assert re.match( - "File .* is expected to contain a function named invalidFunction", + "File .* is expected to contain a function named 'invalidFunction' \(found: 'fun', 'myFunctionBar', 'myFunctionFoo' instead\)", str(excinfo.value), )