-
Notifications
You must be signed in to change notification settings - Fork 77
chore: refactor unimplemented method test macro #2138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1756,25 +1756,7 @@ def test_{{ method_name }}_rest_pager(transport: str = 'rest'): | |
| assert page_.raw_page.next_page_token == token | ||
|
|
||
|
|
||
| {%- else %}{# paged_result_field #} | ||
|
|
||
| def test_{{ method_name }}_rest_error(): | ||
| client = {{ service.client_name }}( | ||
| credentials=ga_credentials.AnonymousCredentials(), | ||
| transport='rest' | ||
| ) | ||
| {%- if not method.http_options %} | ||
| # Since a `google.api.http` annotation is required for using a rest transport | ||
| # method, this should error. | ||
| with pytest.raises(NotImplementedError) as not_implemented_error: | ||
| client.{{ method_name }}({}) | ||
| assert ( | ||
| "Method {{ method.name }} is not available over REST transport" | ||
| in str(not_implemented_error.value) | ||
| ) | ||
|
|
||
| {%- endif %}{# not method.http_options #} | ||
| {% endif %}{# flattened_fields #} | ||
| {%- endif %}{# paged_result_field #} | ||
|
|
||
| {% else %}{# this is an lro or streaming method #} | ||
| def test_{{ method_name }}_rest_unimplemented(): | ||
|
|
@@ -1906,8 +1888,8 @@ def test_transport_kind_{{ transport_name }}(): | |
|
|
||
|
|
||
| {% macro transport_close_test(service, transport, is_async) %} | ||
| {% set async_prefix = "async " if is_async else "" %} | ||
| {% set async_decorator = "@pytest.mark.asyncio " if is_async else "" %} | ||
| {% set async_prefix = get_async_prefix(is_async) %} | ||
| {% set async_decorator = get_async_decorator(is_async) %} | ||
| {% set transport_name = get_transport_name(transport, is_async) %} | ||
| {% set close_session = { | ||
| 'rest': "_session", | ||
|
|
@@ -1947,3 +1929,111 @@ def test_unsupported_parameter_rest_asyncio(): | |
| ) | ||
|
|
||
| {% endmacro %} | ||
|
|
||
| {# get_await_prefix sets an "await" keyword | ||
| # to a method call if is_async=True. | ||
| #} | ||
| {% macro get_await_prefix(is_async) %} | ||
| {{- "await " if is_async else "" -}} | ||
| {% endmacro %} | ||
|
|
||
| {# get_async_prefix sets an "async" keyword | ||
| # to a method definition if is_async=True. | ||
| #} | ||
| {% macro get_async_prefix(is_async) %} | ||
| {{- "async " if is_async else "" -}} | ||
| {% endmacro %} | ||
|
|
||
| {# get_async_decorator sets a "@pytest.mark.asyncio" decorator | ||
| # to an async test method if is_async=True. | ||
| #} | ||
| {% macro get_async_decorator(is_async) %} | ||
| {{- "@pytest.mark.asyncio " if is_async else "" -}} | ||
| {% endmacro %} | ||
|
|
||
| {# is_rest_unsupported_method renders: | ||
| # 'True' if transport is async REST. | ||
| # 'True' if transport is sync REST and method is a client streaming method. | ||
| # 'False' otherwise. | ||
| #} | ||
| {# TODO(https://github.com/googleapis/gapic-generator-python/issues/2152): Update this method as we add support for methods in async REST. | ||
| # There are no plans to add support for client streaming. | ||
| #} | ||
| {% macro is_rest_unsupported_method(method, is_async) %} | ||
| {%- if method.client_streaming or is_async -%} | ||
| {{'True'}} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you have the macro return
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. Macros can only return strings and this is the best thing I could come up with.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, right. I guess what I was thinking would be more clearly described in terms of defining the functionality of this macro in Python proper (eg |
||
| {%- else -%} | ||
| {{'False'}} | ||
| {%- endif -%} | ||
| {% endmacro %} | ||
|
|
||
| {# run_transport_tests_for_config generates all the rest specific tests for both | ||
| # sync and async transport. | ||
| # TODO(https://github.com/googleapis/gapic-generator-python/issues/2142): Continue migrating the test cases | ||
| # in macro::run_transport_tests_for_config into here, and then delete that macro in favor of this one. | ||
| # TODO(https://github.com/googleapis/gapic-generator-python/issues/2153): As a follow up, migrate gRPC test cases | ||
| # into `run_transport_tests_for_config` and make any of the rest specific specific macros which are called within more generic. | ||
| #} | ||
| {% macro run_transport_tests_for_config(service, transport, is_async) %} | ||
| {% if 'rest' in transport %} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I support having this More generally, though, I would support changing the name of this macro so it can be used for both REST and gRPC. Obviously we would do the gRPC refactoring later, not in this PR. WDYT? If this sounds feasible, consider editing as below, and let's file an issue. This would help us ensure we're thorough in our tests and consistent for both transports.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't think we need to raise a generation error for gRPC tests since it would add unnecessary toil in the test suite (i.e. this suite shouldn't be run against gRPC transport which is why we're skipping for it). I think It's fine to skip generation for it as long as we have a tracking bug to include gRPC tests.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks!
The idea is to just have a fail-safe to ensure we're indeed skipping it. It protects us from our own future programming errors. I've found this defensive practice valuable. Not a blocker for this PR, but I still say it's a nice to have.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that it's nice to have a fail-safe. Let's sync on this offline and we can address this as a follow up if needed. |
||
| {% for method in service.methods.values() %} | ||
| {% if is_rest_unsupported_method(method, is_async) == 'True' or not method.http_options %} | ||
| {{ rest_method_not_implemented_error(service, method, transport, is_async) }} | ||
| {% endif %}{# is_rest_unsupported_method(method, is_async) == 'False' and method.http_options #} | ||
| {% endfor %} | ||
| {% endif %}{# if 'rest' in transport #} | ||
| {{ initialize_client_with_transport_test(service, transport, is_async) }} | ||
| {% endmacro %} | ||
|
|
||
| {# rest_method_not_implemented_error generates tests for methods | ||
| # which are not supported for rest transport. | ||
| #} | ||
| {% macro rest_method_not_implemented_error(service, method, transport, is_async) %} | ||
| {% if not is_async %}{# TODO(b/362949446): Remove this guard once a not implemented __call__ class method is added to async rest for every wrapper.Method. #} | ||
| {% set await_prefix = get_await_prefix(is_async) %} | ||
| {% set async_prefix = get_async_prefix(is_async) %} | ||
| {% set async_decorator = get_async_decorator(is_async) %} | ||
| {% set transport_name = get_transport_name(transport, is_async) %} | ||
| {% set method_name = method.name|snake_case %} | ||
| {{async_decorator}} | ||
| {{async_prefix}}def test_{{ method_name }}_{{transport_name}}_error(): | ||
| {% if transport_name == 'rest_asyncio' %} | ||
| if not HAS_GOOGLE_AUTH_AIO: | ||
| {# TODO(https://github.com/googleapis/google-auth-library-python/pull/1577): Update the version of google-auth once the linked PR is merged. #} | ||
| pytest.skip("google-auth > 2.x.x is required for async rest transport.") | ||
| {% endif %} | ||
|
|
||
| client = {{ get_client(service, is_async) }}( | ||
| credentials={{get_credentials(is_async)}}, | ||
| transport="{{transport_name}}" | ||
| ) | ||
|
|
||
| with pytest.raises(NotImplementedError) as not_implemented_error: | ||
| {{await_prefix}}client.{{ method_name }}({}) | ||
| assert ( | ||
| "Method {{ method.name }} is not available over REST transport" | ||
| in str(not_implemented_error.value) | ||
| ) | ||
|
|
||
| {% endif %}{# if is_async #} | ||
| {% endmacro %} | ||
|
|
||
| {# initialize_client_with_transport_test adds coverage for transport clients. | ||
| # Note: This test case is needed because we aren't unconditionally | ||
| # generating the not implemented coverage test for every client. | ||
| #} | ||
| {% macro initialize_client_with_transport_test(service, transport, is_async) %} | ||
| {% set transport_name = get_transport_name(transport, is_async) %} | ||
| def test_initialize_client_w_{{transport_name}}(): | ||
| {% if transport_name == 'rest_asyncio' %} | ||
| if not HAS_GOOGLE_AUTH_AIO: | ||
| {# TODO(https://github.com/googleapis/google-auth-library-python/pull/1577): Update the version of google-auth once the linked PR is merged. #} | ||
| pytest.skip("google-auth > 2.x.x is required for async rest transport.") | ||
| {% endif %} | ||
| client = {{ get_client(service, is_async) }}( | ||
| credentials={{get_credentials(is_async)}}, | ||
| transport="{{transport_name}}" | ||
| ) | ||
vchudnov-g marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| assert client is not None | ||
|
|
||
| {% endmacro %} | ||
Uh oh!
There was an error while loading. Please reload this page.