Skip to content

Commit 336a9f2

Browse files
waprindhermes
authored andcommitted
Add error reporting system test (#3348)
1 parent 520637c commit 336a9f2

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

error_reporting/nox.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ def lint_setup_py(session):
6464
'python', 'setup.py', 'check', '--restructuredtext', '--strict')
6565

6666

67+
@nox.session
68+
@nox.parametrize('python_version', ['2.7', '3.6'])
69+
def system_tests(session, python_version):
70+
"""Run the system test suite."""
71+
72+
# Sanity check: Only run system tests if the environment variable is set.
73+
if not os.environ.get('GOOGLE_APPLICATION_CREDENTIALS', ''):
74+
return
75+
76+
# Run the system tests against latest Python 2 and Python 3 only.
77+
session.interpreter = 'python{}'.format(python_version)
78+
79+
# Install all test dependencies, then install this package into the
80+
# virtualenv's dist-packages.
81+
session.install('mock', 'pytest', *LOCAL_DEPS)
82+
session.install('../test_utils/')
83+
session.install('.')
84+
85+
# Run py.test against the system tests.
86+
session.run('py.test', '-vvv', 'tests/system.py')
87+
88+
6789
@nox.session
6890
def cover(session):
6991
"""Run the final coverage report.

error_reporting/tests/system.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Copyright 2017 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import functools
16+
import operator
17+
import unittest
18+
19+
from google.cloud import error_reporting
20+
from google.cloud.gapic.errorreporting.v1beta1 import (
21+
error_stats_service_client)
22+
from google.cloud.proto.devtools.clouderrorreporting.v1beta1 import (
23+
error_stats_service_pb2)
24+
from google.protobuf.duration_pb2 import Duration
25+
26+
from test_utils.retry import RetryResult
27+
from test_utils.system import unique_resource_id
28+
29+
30+
ERROR_MSG = 'Stackdriver Error Reporting System Test'
31+
32+
33+
def setUpModule():
34+
Config.CLIENT = error_reporting.Client()
35+
36+
37+
class Config(object):
38+
"""Run-time configuration to be modified at set-up.
39+
40+
This is a mutable stand-in to allow test set-up to modify
41+
global state.
42+
"""
43+
CLIENT = None
44+
45+
46+
def _list_groups(client):
47+
"""List Error Groups from the last 60 seconds.
48+
49+
This class provides a wrapper around making calls to the GAX
50+
API. It's used by the system tests to find the appropriate error group
51+
to verify the error was successfully reported.
52+
53+
:type client: :class:`~google.cloud.error_reporting.client.Client`
54+
:param client: The client containing a project and credentials.
55+
56+
:rtype: :class:`~google.gax.ResourceIterator`
57+
:returns: Iterable of :class:`~.error_stats_service_pb2.ErrorGroupStats`.
58+
"""
59+
gax_api = error_stats_service_client.ErrorStatsServiceClient(
60+
credentials=client._credentials)
61+
project_name = gax_api.project_path(client.project)
62+
63+
time_range = error_stats_service_pb2.QueryTimeRange()
64+
time_range.period = error_stats_service_pb2.QueryTimeRange.PERIOD_1_HOUR
65+
66+
duration = Duration(seconds=60 * 60)
67+
68+
return gax_api.list_group_stats(
69+
project_name, time_range, timed_count_duration=duration)
70+
71+
72+
def _simulate_exception(class_name, client):
73+
"""Simulates an exception to verify it was reported.
74+
75+
:type class_name: str
76+
:param class_name: The name of a custom error class to
77+
create (and raise).
78+
79+
:type client: :class:`~google.cloud.error_reporting.client.Client`
80+
:param client: The client that will report the exception.
81+
"""
82+
custom_exc = type(class_name, (RuntimeError,), {})
83+
try:
84+
raise custom_exc(ERROR_MSG)
85+
except RuntimeError:
86+
client.report_exception()
87+
88+
89+
def _get_error_count(class_name, client):
90+
"""Counts the number of errors in the group of the test exception.
91+
92+
:type class_name: str
93+
:param class_name: The name of a custom error class used.
94+
95+
:type client: :class:`~google.cloud.error_reporting.client.Client`
96+
:param client: The client containing a project and credentials.
97+
98+
:rtype: int
99+
:returns: Group count for errors that match ``class_name``. If no
100+
match is found, returns :data:`None`.
101+
"""
102+
groups = _list_groups(client)
103+
for group in groups:
104+
if class_name in group.representative.message:
105+
return group.count
106+
107+
108+
class TestErrorReporting(unittest.TestCase):
109+
110+
def test_report_exception(self):
111+
# Get a class name unique to this test case.
112+
class_name = 'RuntimeError' + unique_resource_id('_')
113+
114+
# Simulate an error: group won't exist until we report
115+
# first exception.
116+
_simulate_exception(class_name, Config.CLIENT)
117+
118+
is_one = functools.partial(operator.eq, 1)
119+
is_one.__name__ = 'is_one' # partial() has no name.
120+
wrapped_get_count = RetryResult(is_one)(_get_error_count)
121+
122+
error_count = wrapped_get_count(class_name, Config.CLIENT)
123+
self.assertEqual(error_count, 1)

0 commit comments

Comments
 (0)