Skip to content

Commit af3b725

Browse files
authored
chore: bump test coverage to 100% (#364)
* Exclude unreachable test lines from coverage * Skip abstract methods and unused code in coverage * Assure batch ERROR status is actually set in test One of the tests attempted to set an ERROR status on a batch, but that batch was a mock, meaning that setting a status had no effect. If there was a bug in the corresponding code path, the test would probably not catch it, as that code patch would not be taken. * Skip code branch that is currently not taken * Silence deprecation warning in two gapic tests The tests for flattened arguments to the sync pull() method hit a code path that emits a deprecation warning, but that warning is expected and should not clutter the test output. * Raise required unit test coverage to 100% * Remove unused param in publish flow controller
1 parent ff5028a commit af3b725

16 files changed

Lines changed: 120 additions & 71 deletions

File tree

‎packages/google-cloud-pubsub/.coveragerc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ branch = True
55
fail_under = 100
66
show_missing = True
77
omit =
8+
google/cloud/__init__.py
89
google/pubsub/__init__.py
910
exclude_lines =
1011
# Re-enable the standard pragma

‎packages/google-cloud-pubsub/google/cloud/pubsub_v1/publisher/_batch/base.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __len__(self):
5050

5151
@staticmethod
5252
@abc.abstractmethod
53-
def make_lock():
53+
def make_lock(): # pragma: NO COVER
5454
"""Return a lock in the chosen concurrency model.
5555
5656
Returns:
@@ -60,7 +60,7 @@ def make_lock():
6060

6161
@property
6262
@abc.abstractmethod
63-
def messages(self):
63+
def messages(self): # pragma: NO COVER
6464
"""Return the messages currently in the batch.
6565
6666
Returns:
@@ -70,7 +70,7 @@ def messages(self):
7070

7171
@property
7272
@abc.abstractmethod
73-
def size(self):
73+
def size(self): # pragma: NO COVER
7474
"""Return the total size of all of the messages currently in the batch.
7575
7676
The size includes any overhead of the actual ``PublishRequest`` that is
@@ -84,7 +84,7 @@ def size(self):
8484

8585
@property
8686
@abc.abstractmethod
87-
def settings(self):
87+
def settings(self): # pragma: NO COVER
8888
"""Return the batch settings.
8989
9090
Returns:
@@ -95,7 +95,7 @@ def settings(self):
9595

9696
@property
9797
@abc.abstractmethod
98-
def status(self):
98+
def status(self): # pragma: NO COVER
9999
"""Return the status of this batch.
100100
101101
Returns:
@@ -106,7 +106,7 @@ def status(self):
106106
"""
107107
raise NotImplementedError
108108

109-
def cancel(self, cancellation_reason):
109+
def cancel(self, cancellation_reason): # pragma: NO COVER
110110
"""Complete pending futures with an exception.
111111
112112
This method must be called before publishing starts (ie: while the
@@ -119,7 +119,7 @@ def cancel(self, cancellation_reason):
119119
raise NotImplementedError
120120

121121
@abc.abstractmethod
122-
def publish(self, message):
122+
def publish(self, message): # pragma: NO COVER
123123
"""Publish a single message.
124124
125125
Add the given message to this object; this will cause it to be

‎packages/google-cloud-pubsub/google/cloud/pubsub_v1/publisher/_sequencer/base.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Sequencer(metaclass=abc.ABCMeta):
2424

2525
@staticmethod
2626
@abc.abstractmethod
27-
def is_finished(self):
27+
def is_finished(self): # pragma: NO COVER
2828
""" Whether the sequencer is finished and should be cleaned up.
2929
3030
Returns:
@@ -34,7 +34,7 @@ def is_finished(self):
3434

3535
@staticmethod
3636
@abc.abstractmethod
37-
def unpause(self, message):
37+
def unpause(self, message): # pragma: NO COVER
3838
""" Unpauses this sequencer.
3939
4040
Raises:
@@ -45,7 +45,7 @@ def unpause(self, message):
4545

4646
@staticmethod
4747
@abc.abstractmethod
48-
def publish(self, message, retry=None):
48+
def publish(self, message, retry=None): # pragma: NO COVER
4949
""" Publish message for this ordering key.
5050
5151
Args:

‎packages/google-cloud-pubsub/google/cloud/pubsub_v1/publisher/client.py‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,6 @@
4949
_raw_proto_pubbsub_message = gapic_types.PubsubMessage.pb()
5050

5151

52-
def _set_nested_value(container, value, keys):
53-
current = container
54-
for key in keys[:-1]:
55-
current = current.setdefault(key, {})
56-
current[keys[-1]] = value
57-
return container
58-
59-
6052
@_gapic.add_methods(publisher_client.PublisherClient, blacklist=_BLACKLISTED_METHODS)
6153
class Client(object):
6254
"""A publisher client for Google Cloud Pub/Sub.

‎packages/google-cloud-pubsub/google/cloud/pubsub_v1/publisher/flow_controller.py‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ def _would_overflow(self, message):
258258

259259
return size_overflow or msg_count_overflow
260260

261-
def _load_info(self, message_count=None, total_bytes=None, reserved_bytes=None):
261+
def _load_info(self, message_count=None, total_bytes=None):
262262
"""Return the current flow control load information.
263263
264264
The caller can optionally adjust some of the values to fit its reporting
@@ -271,8 +271,6 @@ def _load_info(self, message_count=None, total_bytes=None, reserved_bytes=None):
271271
The value to override the current message count with.
272272
total_bytes (Optional[int]):
273273
The value to override the current total bytes with.
274-
reserved_bytes (Optional[int]):
275-
The value to override the current number of reserved bytes with.
276274
277275
Returns:
278276
str
@@ -285,13 +283,10 @@ def _load_info(self, message_count=None, total_bytes=None, reserved_bytes=None):
285283
if total_bytes is None:
286284
total_bytes = self._total_bytes
287285

288-
if reserved_bytes is None:
289-
reserved_bytes = self._reserved_bytes
290-
291286
return msg.format(
292287
message_count,
293288
self._settings.message_limit,
294289
total_bytes,
295290
self._settings.byte_limit,
296-
reserved_bytes,
291+
self._reserved_bytes,
297292
)

‎packages/google-cloud-pubsub/google/cloud/pubsub_v1/subscriber/scheduler.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class Scheduler(metaclass=abc.ABCMeta):
3131

3232
@property
3333
@abc.abstractmethod
34-
def queue(self):
34+
def queue(self): # pragma: NO COVER
3535
"""Queue: A concurrency-safe queue specific to the underlying
3636
concurrency implementation.
3737
@@ -40,7 +40,7 @@ def queue(self):
4040
raise NotImplementedError
4141

4242
@abc.abstractmethod
43-
def schedule(self, callback, *args, **kwargs):
43+
def schedule(self, callback, *args, **kwargs): # pragma: NO COVER
4444
"""Schedule the callback to be called asynchronously.
4545
4646
Args:
@@ -54,7 +54,7 @@ def schedule(self, callback, *args, **kwargs):
5454
raise NotImplementedError
5555

5656
@abc.abstractmethod
57-
def shutdown(self, await_msg_callbacks=False):
57+
def shutdown(self, await_msg_callbacks=False): # pragma: NO COVER
5858
"""Shuts down the scheduler and immediately end all pending callbacks.
5959
6060
Args:

‎packages/google-cloud-pubsub/synth.py‎

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
)
143143

144144
# Emit deprecation warning if return_immediately flag is set with synchronous pull.
145-
count = s.replace(
145+
s.replace(
146146
"google/pubsub_v1/services/subscriber/*client.py",
147147
r"import pkg_resources",
148148
"import warnings\n\g<0>",
@@ -170,6 +170,48 @@
170170
if count != 2:
171171
raise Exception("Too many or too few replacements in pull() methods.")
172172

173+
# Silence deprecation warnings in pull() method flattened parameter tests.
174+
s.replace(
175+
"tests/unit/gapic/pubsub_v1/test_subscriber.py",
176+
"import mock",
177+
"\g<0>\nimport warnings",
178+
)
179+
count = s.replace(
180+
"tests/unit/gapic/pubsub_v1/test_subscriber.py",
181+
textwrap.dedent(
182+
r"""
183+
([^\n\S]+# Call the method with a truthy value for each flattened field,
184+
[^\n\S]+# using the keyword arguments to the method\.)
185+
\s+(client\.pull\(.*?\))"""
186+
),
187+
"""\n\g<1>
188+
with warnings.catch_warnings():
189+
warnings.simplefilter("ignore", category=DeprecationWarning)
190+
\g<2>""",
191+
flags = re.MULTILINE | re.DOTALL,
192+
)
193+
194+
if count < 1:
195+
raise Exception("Catch warnings replacement failed.")
196+
197+
count = s.replace(
198+
"tests/unit/gapic/pubsub_v1/test_subscriber.py",
199+
textwrap.dedent(
200+
r"""
201+
([^\n\S]+# Call the method with a truthy value for each flattened field,
202+
[^\n\S]+# using the keyword arguments to the method\.)
203+
\s+response = (await client\.pull\(.*?\))"""
204+
),
205+
"""\n\g<1>
206+
with warnings.catch_warnings():
207+
warnings.simplefilter("ignore", category=DeprecationWarning)
208+
\g<2>""",
209+
flags = re.MULTILINE | re.DOTALL,
210+
)
211+
212+
if count < 1:
213+
raise Exception("Catch warnings replacement failed.")
214+
173215
# Make sure that client library version is present in user agent header.
174216
s.replace(
175217
[
@@ -206,13 +248,21 @@
206248
"\n\g<0>",
207249
)
208250

251+
# The namespace package declaration in google/cloud/__init__.py should be excluded
252+
# from coverage.
253+
s.replace(
254+
".coveragerc",
255+
r"((?P<indent>[^\n\S]+)google/pubsub/__init__\.py)",
256+
"\g<indent>google/cloud/__init__.py\n\g<0>",
257+
)
258+
209259
# ----------------------------------------------------------------------------
210260
# Add templated files
211261
# ----------------------------------------------------------------------------
212262
templated_files = gcp.CommonTemplates().py_library(
213263
microgenerator=True,
214264
samples=True,
215-
cov_level=99,
265+
cov_level=100,
216266
system_test_external_dependencies=["psutil"],
217267
)
218268
s.move(templated_files, excludes=[".coveragerc"])

‎packages/google-cloud-pubsub/tests/unit/gapic/pubsub_v1/test_subscriber.py‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import os
1919
import mock
20+
import warnings
2021

2122
import grpc
2223
from grpc.experimental import aio
@@ -2338,11 +2339,13 @@ def test_pull_flattened():
23382339

23392340
# Call the method with a truthy value for each flattened field,
23402341
# using the keyword arguments to the method.
2341-
client.pull(
2342-
subscription="subscription_value",
2343-
return_immediately=True,
2344-
max_messages=1277,
2345-
)
2342+
with warnings.catch_warnings():
2343+
warnings.simplefilter("ignore", category=DeprecationWarning)
2344+
client.pull(
2345+
subscription="subscription_value",
2346+
return_immediately=True,
2347+
max_messages=1277,
2348+
)
23462349

23472350
# Establish that the underlying call was made with the expected
23482351
# request object values.
@@ -2382,11 +2385,13 @@ async def test_pull_flattened_async():
23822385
call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(pubsub.PullResponse())
23832386
# Call the method with a truthy value for each flattened field,
23842387
# using the keyword arguments to the method.
2385-
response = await client.pull(
2386-
subscription="subscription_value",
2387-
return_immediately=True,
2388-
max_messages=1277,
2389-
)
2388+
with warnings.catch_warnings():
2389+
warnings.simplefilter("ignore", category=DeprecationWarning)
2390+
await client.pull(
2391+
subscription="subscription_value",
2392+
return_immediately=True,
2393+
max_messages=1277,
2394+
)
23902395

23912396
# Establish that the underlying call was made with the expected
23922397
# request object values.

‎packages/google-cloud-pubsub/tests/unit/pubsub_v1/publisher/batch/test_base.py‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,19 @@
2424
from google.pubsub_v1 import types as gapic_types
2525

2626

27-
def create_batch(status=None, settings=types.BatchSettings()):
27+
def create_batch(status, settings=types.BatchSettings()):
2828
"""Create a batch object, which does not commit.
2929
3030
Args:
31-
status (str): If provided, the batch's internal status will be set
32-
to the provided status.
31+
status (str): The batch's internal status will be set to the provided status.
3332
3433
Returns:
3534
~.pubsub_v1.publisher.batch.thread.Batch: The batch object
3635
"""
3736
creds = mock.Mock(spec=credentials.Credentials)
3837
client = publisher.Client(credentials=creds)
3938
batch = Batch(client, "topic_name", settings)
40-
if status:
41-
batch._status = status
39+
batch._status = status
4240
return batch
4341

4442

‎packages/google-cloud-pubsub/tests/unit/pubsub_v1/publisher/batch/test_thread.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def api_publish_delay(topic="", messages=(), retry=None):
188188

189189
start = datetime.datetime.now()
190190
event_set = api_publish_called.wait(timeout=1.0)
191-
if not event_set:
191+
if not event_set: # pragma: NO COVER
192192
pytest.fail("API publish was not called in time")
193193
batch.publish({"data": b"second message"})
194194
end = datetime.datetime.now()

0 commit comments

Comments
 (0)