-
Notifications
You must be signed in to change notification settings - Fork 324
fix: QueryJob.exception() *returns* the errors, not raises them #467
Changes from 2 commits
a85fe8f
07af774
7d9a7e8
a19f07e
f3ddc14
ef2fe8e
56c4e96
739627a
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 |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
| import copy | ||
| import http | ||
| import textwrap | ||
| import types | ||
|
|
||
| import freezegun | ||
| from google.api_core import exceptions | ||
|
|
@@ -356,6 +357,45 @@ def test_done_w_timeout_and_longer_internal_api_timeout(self): | |
| call_args = fake_reload.call_args | ||
| self.assertAlmostEqual(call_args.kwargs.get("timeout"), expected_timeout) | ||
|
|
||
| def test_done_w_query_results_error(self): | ||
| client = _make_client(project=self.PROJECT) | ||
| bad_request_error = exceptions.BadRequest("Error in query") | ||
| client._get_query_results = mock.Mock(side_effect=bad_request_error) | ||
|
|
||
| resource = self._make_resource(ended=False) | ||
| job = self._get_target_class().from_api_repr(resource, client) | ||
| job._exception = None | ||
|
|
||
| def fake_reload(self, *args, **kwargs): | ||
| self._properties["status"]["state"] = "DONE" | ||
| self.set_exception(copy.copy(bad_request_error)) | ||
|
|
||
| fake_reload_method = types.MethodType(fake_reload, job) | ||
|
|
||
| with mock.patch.object(job, "reload", new=fake_reload_method): | ||
| is_done = job.done() | ||
|
|
||
| assert is_done | ||
| assert isinstance(job._exception, exceptions.BadRequest) | ||
|
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. why use the private property in this and the other tests? any objections to calling
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. The reasoning was that One could argue that the chosen unit of test is too small, and that the class itself should represent a unit as opposed to its individual methods, but addressing that would require quite some refactoring (we already tinker with internal Here, practicality beats purity IMHO, thus the "cheating" by examining the internal state of the class. Or do you have a strong opinion on this?
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. Works for me. I agree that ideally we'd have higher-level tests than this, but makes sense to stay with existing conventions, especially given our 100% coverage requirement. |
||
|
|
||
| def test_done_w_job_reload_error(self): | ||
| client = _make_client(project=self.PROJECT) | ||
| query_results = google.cloud.bigquery.query._QueryResults( | ||
| properties={ | ||
| "jobComplete": True, | ||
| "jobReference": {"projectId": self.PROJECT, "jobId": "12345"}, | ||
| } | ||
| ) | ||
| client._get_query_results = mock.Mock(return_value=query_results) | ||
|
|
||
| resource = self._make_resource(ended=False) | ||
| job = self._get_target_class().from_api_repr(resource, client) | ||
| retry_error = exceptions.RetryError("Too many retries", cause=TimeoutError) | ||
| job.reload = mock.Mock(side_effect=retry_error) | ||
| job._exception = None | ||
|
|
||
| self.assertRaisesRegex(exceptions.RetryError, r"Too many retries", job.done) | ||
|
|
||
| def test_query_plan(self): | ||
| from google.cloud._helpers import _RFC3339_MICROS | ||
| from google.cloud.bigquery.job import QueryPlanEntry | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.