Skip to content
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

Pub/Sub: update how to test with mock #2555

Merged
merged 26 commits into from
Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1a85239
Update test with mock
anguillanneuf Nov 19, 2019
1abf3c9
Merge branch 'master' into pubsub_mock
anguillanneuf Nov 25, 2019
666b6bd
clean up resources after tests
anguillanneuf Dec 2, 2019
0cccbf8
update test for async message reception
anguillanneuf Dec 2, 2019
96c66fe
clean up resources for all tests
anguillanneuf Dec 2, 2019
3acf66a
use unique resource names avoid test failures
anguillanneuf Dec 2, 2019
5eba4fa
also delete subscriptions in cleanup phase
anguillanneuf Dec 2, 2019
83bbf39
Merge branch 'master' into pubsub_mock
leahecole Dec 5, 2019
475a57d
tim's suggestions
anguillanneuf Dec 6, 2019
6617f22
Merge branch 'pubsub_mock' of github.com:GoogleCloudPlatform/python-d…
anguillanneuf Dec 6, 2019
bca6eef
unique topic name
anguillanneuf Dec 6, 2019
a3b9de3
Merge branch 'master' into pubsub_mock
anguillanneuf Dec 6, 2019
06d0ce6
reformat
anguillanneuf Dec 6, 2019
3242686
lint
anguillanneuf Dec 6, 2019
8670eff
lint
anguillanneuf Dec 6, 2019
ffa76bb
update assert to remove bytestring notation
anguillanneuf Dec 6, 2019
e877d54
move cleanup code in fixture
anguillanneuf Dec 6, 2019
6fb596c
rewrite PubSubToGCS test using dataflow testing module
anguillanneuf Dec 10, 2019
85a3d98
lint
anguillanneuf Dec 10, 2019
9ef38f5
missing import
anguillanneuf Dec 10, 2019
a4d9a26
redundant import
anguillanneuf Dec 10, 2019
b4a0120
david's suggestions
anguillanneuf Dec 10, 2019
4fadbfc
update requirements.txt
anguillanneuf Dec 10, 2019
fffd0fd
Merge branch 'master' into pubsub_mock
busunkim96 Dec 10, 2019
7cf5693
black -l 79
anguillanneuf Dec 10, 2019
d2afe6a
Merge branch 'pubsub_mock' of github.com:GoogleCloudPlatform/python-d…
anguillanneuf Dec 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions pubsub/cloud-client/iam_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@
# limitations under the License.

import os
import uuid

from google.cloud import pubsub_v1
import pytest

import iam

UUID = uuid.uuid4().hex
PROJECT = os.environ['GCLOUD_PROJECT']
TOPIC = 'iam-test-topic'
SUBSCRIPTION = 'iam-test-subscription'
TOPIC = 'iam-test-topic-' + UUID
SUBSCRIPTION = 'iam-test-subscription-' + UUID


@pytest.fixture(scope='module')
Expand Down Expand Up @@ -63,6 +65,15 @@ def subscription(subscriber_client, topic):
yield subscription_path


def _to_delete():
anguillanneuf marked this conversation as resolved.
Show resolved Hide resolved
publisher_client = pubsub_v1.PublisherClient()
subscriber_client = pubsub_v1.SubscriberClient()
publisher_client.delete_topic(
'projects/{}/topics/{}'.format(PROJECT, TOPIC))
subscriber_client.delete_subscription(
'projects/{}/subscriptions/{}'.format(PROJECT, SUBSCRIPTION))


def test_get_topic_policy(topic, capsys):
iam.get_topic_policy(PROJECT, TOPIC)

Expand Down Expand Up @@ -109,3 +120,6 @@ def test_check_subscription_permissions(subscription, capsys):

assert subscription in out
assert 'pubsub.subscriptions.consume' in out

# Clean up resources.
_to_delete()
12 changes: 11 additions & 1 deletion pubsub/cloud-client/publisher_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import os
import time
import uuid

from gcp_devrel.testing import eventually_consistent
from google.cloud import pubsub_v1
Expand All @@ -22,8 +23,9 @@

import publisher

UUID = uuid.uuid4().hex
PROJECT = os.environ['GCLOUD_PROJECT']
TOPIC = 'publisher-test-topic'
TOPIC = 'publisher-test-topic-' + UUID


@pytest.fixture
Expand Down Expand Up @@ -56,6 +58,12 @@ def new_sleep(period):
return mock.patch('time.sleep', new=new_sleep)


def _to_delete():
publisher_client = pubsub_v1.PublisherClient()
publisher_client.delete_topic('projects/{}/topics/{}'.format(
PROJECT, TOPIC))


def test_list(client, topic, capsys):
@eventually_consistent.call
def _():
Expand Down Expand Up @@ -127,3 +135,5 @@ def test_publish_with_futures(topic, capsys):

out, _ = capsys.readouterr()
assert 'Published' in out

_to_delete()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these _to_delete() functions be done with as a module-level fixture teardown?

https://docs.pytest.org/en/latest/fixture.html#fixture-finalization-executing-teardown-code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to call delete out in publisher_test.py because there's a test_delete() and conflicts with teardown after yield. I left this comment earlier for Tim as well: #2555 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are the eventually_consistent necessary? Can they be changed in some way to make sure the resources are available by the time the tests are run so we can delete them through the fixtures?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can address this in a different PR? @eventually_consistent is used throughout the repo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me

41 changes: 21 additions & 20 deletions pubsub/cloud-client/quickstart/sub_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import mock
import os
import pytest

Expand Down Expand Up @@ -68,31 +69,31 @@ def _publish_messages(topic_path):
publish_future.result()


def _sub_timeout(project_id, subscription_name):
# This is an exactly copy of `sub.py` except
# StreamingPullFuture.result() will time out after 10s.
client = pubsub_v1.SubscriberClient()
subscription_path = client.subscription_path(
project_id, subscription_name)
def test_sub(monkeypatch, topic_path, subscription_path, capsys):

def callback(message):
print('Received message {} of message ID {}\n'.format(
message, message.message_id))
message.ack()
print('Acknowledged message {}\n'.format(message.message_id))
real_client = pubsub_v1.SubscriberClient()
mock_client = mock.Mock(spec=pubsub_v1.SubscriberClient,
wraps=real_client)

streaming_pull_future = client.subscribe(
subscription_path, callback=callback)
print('Listening for messages on {}..\n'.format(subscription_path))
# Attributes on mock_client_constructor uses the corresponding
# attributes on pubsub_v1.SubscriberClient.
mock_client_constructor = mock.create_autospec(pubsub_v1.SubscriberClient)
mock_client_constructor.return_value = mock_client

try:
streaming_pull_future.result(timeout=10)
except: # noqa
streaming_pull_future.cancel()
monkeypatch.setattr(pubsub_v1, 'SubscriberClient', mock_client_constructor)

def mock_subscribe(subscription_path, callback=None):
real_future = real_client.subscribe(subscription_path,
callback=callback)
mock_future = mock.Mock(spec=real_future, wraps=real_future)

def test_sub(monkeypatch, topic_path, subscription_path, capsys):
monkeypatch.setattr(sub, 'sub', _sub_timeout)
def mock_result():
return real_future.result(timeout=10)

mock_future.result.side_effect = mock_result
return mock_future

mock_client.subscribe.side_effect = mock_subscribe

_publish_messages(topic_path)

Expand Down
18 changes: 16 additions & 2 deletions pubsub/cloud-client/quickstart_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
# limitations under the License.

import os
import uuid

from google.cloud import pubsub_v1
import pytest
import quickstart

UUID = uuid.uuid4().hex
PROJECT = os.environ['GCLOUD_PROJECT']
TOPIC = 'end-to-end-test-topic'
SUBSCRIPTION = 'end-to-end-test-topic-sub'
TOPIC = 'end-to-end-test-topic-' + UUID
SUBSCRIPTION = 'end-to-end-test-topic-sub-' + UUID
N = 10


Expand Down Expand Up @@ -61,6 +63,15 @@ def subscription(subscriber_client, topic):
yield SUBSCRIPTION


def _to_delete():
publisher_client = pubsub_v1.PublisherClient()
subscriber_client = pubsub_v1.SubscriberClient()
publisher_client.delete_topic(
'projects/{}/topics/{}'.format(PROJECT, TOPIC))
subscriber_client.delete_subscription(
'projects/{}/subscriptions/{}'.format(PROJECT, SUBSCRIPTION))


def test_end_to_end(topic, subscription, capsys):

quickstart.end_to_end(PROJECT, topic, subscription, N)
Expand All @@ -69,3 +80,6 @@ def test_end_to_end(topic, subscription, capsys):
assert "Received all messages" in out
assert "Publish time lapsed" in out
assert "Subscribe time lapsed" in out

# Clean up resources.
_to_delete()
31 changes: 25 additions & 6 deletions pubsub/cloud-client/subscriber_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import os
import time
import uuid

from gcp_devrel.testing import eventually_consistent
from google.cloud import pubsub_v1
Expand All @@ -22,11 +23,12 @@

import subscriber

UUID = uuid.uuid4().hex
PROJECT = os.environ['GCLOUD_PROJECT']
TOPIC = 'subscription-test-topic'
SUBSCRIPTION_ONE = 'subscription-test-subscription-one'
SUBSCRIPTION_TWO = 'subscription-test-subscription-two'
SUBSCRIPTION_THREE = 'subscription-test-subscription-three'
TOPIC = 'subscription-test-topic-' + UUID
SUBSCRIPTION_ONE = 'subscription-test-subscription-one-' + UUID
SUBSCRIPTION_TWO = 'subscription-test-subscription-two-' + UUID
SUBSCRIPTION_THREE = 'subscription-test-subscription-three-' + UUID
ENDPOINT = 'https://{}.appspot.com/push'.format(PROJECT)
NEW_ENDPOINT = 'https://{}.appspot.com/push2'.format(PROJECT)

Expand Down Expand Up @@ -185,6 +187,20 @@ def new_sleep(period):
return mock.patch('time.sleep', new=new_sleep)


def _to_delete():
publisher_client = pubsub_v1.PublisherClient()
subscriber_client = pubsub_v1.SubscriberClient()
resources = [TOPIC, SUBSCRIPTION_TWO, SUBSCRIPTION_THREE]

for item in resources:
if 'subscription-test-topic' in item:
publisher_client.delete_topic(
'projects/{}/topics/{}'.format(PROJECT, item))
if 'subscription-test-subscription' in item:
subscriber_client.delete_subscription(
'projects/{}/subscriptions/{}'.format(PROJECT, item))


def test_receive(publisher_client, topic, subscription_two, capsys):
_publish_messages(publisher_client, topic)

Expand All @@ -195,7 +211,7 @@ def test_receive(publisher_client, topic, subscription_two, capsys):
out, _ = capsys.readouterr()
assert 'Listening' in out
assert subscription_two in out
assert 'Message 1' in out
assert 'Message' in out


def test_receive_with_custom_attributes(
Expand Down Expand Up @@ -227,7 +243,7 @@ def test_receive_with_flow_control(
out, _ = capsys.readouterr()
assert 'Listening' in out
assert subscription_two in out
assert 'Message 1' in out
assert 'Message' in out


def test_receive_synchronously(
Expand All @@ -249,3 +265,6 @@ def test_receive_synchronously_with_lease(

out, _ = capsys.readouterr()
assert 'Done.' in out

# Clean up resources after all the tests.
_to_delete()
10 changes: 7 additions & 3 deletions pubsub/streaming-analytics/PubSubToGCS_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@

PROJECT = os.environ['GCLOUD_PROJECT']
BUCKET = os.environ['CLOUD_STORAGE_BUCKET']
TOPIC = 'test-topic'
UUID = uuid.uuid4().hex
UUID = uuid.uuid1().hex
TOPIC = 'test-topic-' + UUID


@pytest.fixture
Expand Down Expand Up @@ -95,6 +95,10 @@ def test_run(publisher_client, topic_path):
files = gcs_client.list_prefix('gs://{}/pubsub/{}'.format(BUCKET, UUID))
assert len(files) > 0

# Clean up. Delete topic. Delete files.
# Clean up. Delete subscription. Delete topic. Delete GCS files.
subscriber_client = pubsub_v1.SubscriberClient()
subscriptions = publisher_client.list_topic_subscriptions(topic_path)
for subscription in subscriptions:
subscriber_client.delete_subscription(subscription)
publisher_client.delete_topic(topic_path)
gcs_client.delete_batch(list(files))