tests: fix unit test failure when auto_populated_fields is set#16944
Conversation
There was a problem hiding this comment.
Code Review
This pull request implements auto-population for the request_id field in CreateJob, CancelJob, and DeleteJob methods, as specified in the service configuration and verified in unit tests. Feedback indicates that the auto-population logic should be moved from the sample code into the generated RPC methods to fully comply with AIP-4235. Furthermore, the unit tests should be updated to use re.fullmatch for more robust UUID validation and to use empty strings instead of None when resetting proto3 string fields.
| assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id) | ||
| # clear UUID field so that the check below succeeds | ||
| args[0].request_id = None |
There was a problem hiding this comment.
There are two improvements that can be made here for better robustness and adherence to proto3 standards:
- Use
re.fullmatchinstead ofre.matchto ensure the entirerequest_idstring conforms to the UUID v4 format, preventing false positives from longer strings. - Set the field to an empty string
""instead ofNone. In proto3, string fields default to"". Whileproto-plusmight handleNoneby converting it to the default, it is not valid for standardgoogle.protobufmessages and can lead toTypeErroror unexpected behavior in equality checks.
| assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id) | |
| # clear UUID field so that the check below succeeds | |
| args[0].request_id = None | |
| assert re.fullmatch(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id) | |
| # clear UUID field so that the check below succeeds | |
| args[0].request_id = "" |
References
- In proto3, string fields default to an empty string (""). Using None is not valid for standard google.protobuf messages. (link)
There was a problem hiding this comment.
- will be addressed in chore: replace re.match with re.fullmatch #17024
There was a problem hiding this comment.
- will be addressed in chore: refactor tests related to AIP 4235 #17027
|
The error in https://github.com/googleapis/google-cloud-python/actions/runs/25388575659/job/74456652962?pr=16944 matches what we have in b/508597813 |
| if not request.request_id: | ||
| request.request_id = str(uuid.uuid4()) | ||
|
|
There was a problem hiding this comment.
nit: can this be introduced as a helper once in the client which can simply be called in each methods?
There was a problem hiding this comment.
This file does not touch this template at all. IOW, this is an existing issue at main. I'll open a separate PR to address it.
There was a problem hiding this comment.
This will be addressed in a separate PR #17004
| call.assert_called() | ||
| _, args, _ = call.mock_calls[0] | ||
| # Ensure that the uuid4 field is set according to AIP 4235 | ||
| assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", args[0].request_id) |
There was a problem hiding this comment.
nit: can the regex be defined once and re-used everywhere?
There was a problem hiding this comment.
This is already defined as a macro. You only need to change it in one place
| if isinstance(request, dict): | ||
| request['request_id'] = "explicit value for autopopulate-able field" | ||
| else: | ||
| request.request_id = "explicit value for autopopulate-able field" |
There was a problem hiding this comment.
nit: Can this be included as part of the parametrize above?
There was a problem hiding this comment.
This PR doesn't touch this code. This is an existing issue at main. I'll open a separate PR to address it.
| found_field = None | ||
| for i, (key, value) in enumerate(req.call_args.kwargs['params']): | ||
| if key == "requestId": | ||
| assert re.match(r"[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}", value) | ||
| found_field = i | ||
| break | ||
| if found_field is not None: | ||
| del req.call_args.kwargs['params'][found_field] |
There was a problem hiding this comment.
I don't know how I feel about deleting a field in a mock test.
A couple of options:
- We include
request_idwithinexpected_paramsand have the value set tomock.ANYsince we're already asserting what the value should look like against the regex later on. - We can filter the params we want to compare against the expected_params.
Fixes b/508597813