Skip to content

Commit 06dfd29

Browse files
authored
Raise TypeError on bare test decorator usage, fix bare @requires_crt usages, and add regression tests (boto#372)
* Raise TypeError on bare @skip_if_windows, @skip_if_using_serial_implementation, @requires_crt usage, fix bare @requires_crt usages, and add regression tests * Fix import sorting lint errors * Fix license issue of the new file test_decorators.py
1 parent 127fc61 commit 06dfd29

File tree

5 files changed

+134
-7
lines changed

5 files changed

+134
-7
lines changed

tests/__init__.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ def test_some_non_windows_stuff(self):
100100
self.assertEqual(...)
101101
102102
"""
103+
if callable(reason):
104+
raise TypeError(
105+
"Use @skip_if_windows('reason') with parentheses, "
106+
"not bare @skip_if_windows"
107+
)
103108

104109
def decorator(func):
105110
return unittest.skipIf(
@@ -111,17 +116,30 @@ def decorator(func):
111116

112117
def skip_if_using_serial_implementation(reason):
113118
"""Decorator to skip tests when running as the serial implementation"""
119+
if callable(reason):
120+
raise TypeError(
121+
"Use @skip_if_using_serial_implementation('reason') with parentheses, "
122+
"not bare @skip_if_using_serial_implementation"
123+
)
114124

115125
def decorator(func):
116126
return unittest.skipIf(is_serial_implementation(), reason)(func)
117127

118128
return decorator
119129

120130

121-
def requires_crt(cls, reason=None):
131+
def requires_crt(reason=None):
132+
if callable(reason):
133+
raise TypeError(
134+
"Use @requires_crt() with parentheses, not bare @requires_crt"
135+
)
122136
if reason is None:
123137
reason = "Test requires awscrt to be installed."
124-
return unittest.skipIf(not HAS_CRT, reason)(cls)
138+
139+
def decorator(func):
140+
return unittest.skipIf(not HAS_CRT, reason)(func)
141+
142+
return decorator
125143

126144

127145
class StreamWithError:

tests/functional/test_crt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def on_done(self, future, **kwargs):
6565
self.on_done_future = future
6666

6767

68-
@requires_crt
68+
@requires_crt()
6969
class TestCRTTransferManager(unittest.TestCase):
7070
def setUp(self):
7171
self.region = 'us-west-2'

tests/integration/test_crt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def on_done(self, **kwargs):
5050
self.on_done_called = True
5151

5252

53-
@requires_crt
53+
@requires_crt()
5454
class TestCRTS3Transfers(BaseTransferManagerIntegTest):
5555
"""Tests for the high level s3transfer based on CRT implementation."""
5656

tests/unit/test_crt.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def test_multiple_acquires_return_same_lock(self, mock_crt_process_lock):
8989
mock_crt_process_lock.return_value.acquire.assert_called_once_with()
9090

9191

92-
@requires_crt
92+
@requires_crt()
9393
class TestBotocoreCRTRequestSerializer(unittest.TestCase):
9494
def setUp(self):
9595
self.region = 'us-west-2'
@@ -291,7 +291,7 @@ def test_to_crt_credentials_provider(self, botocore_credentials):
291291
self.assert_crt_credentials(crt_credentials)
292292

293293

294-
@requires_crt
294+
@requires_crt()
295295
class TestCRTTransferFuture(unittest.TestCase):
296296
def setUp(self):
297297
self.mock_s3_request = mock.Mock(awscrt.s3.S3RequestType)
@@ -320,7 +320,7 @@ def test_set_exception_can_override_previous_exception(self):
320320
self.future.result()
321321

322322

323-
@requires_crt
323+
@requires_crt()
324324
class TestOnBodyFileObjWriter(unittest.TestCase):
325325
def test_call(self):
326326
fileobj = io.BytesIO()

tests/unit/test_decorators.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
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+
from unittest import mock
15+
16+
import pytest
17+
18+
from tests import (
19+
requires_crt,
20+
skip_if_using_serial_implementation,
21+
skip_if_windows,
22+
)
23+
24+
25+
class TestSkipIfWindows:
26+
def test_bare_skip_if_windows_fails_immediately(self):
27+
with pytest.raises(TypeError):
28+
29+
@skip_if_windows
30+
def my_test():
31+
pass
32+
33+
def test_skip_if_windows_skips_on_windows(self):
34+
with mock.patch('tests.platform') as mock_platform:
35+
mock_platform.system.return_value = 'Windows'
36+
37+
@skip_if_windows('Not supported on Windows')
38+
def my_test():
39+
assert False
40+
41+
assert getattr(my_test, '__unittest_skip__', False) is True
42+
43+
def test_skip_if_windows_runs_on_non_windows(self):
44+
with mock.patch('tests.platform') as mock_platform:
45+
mock_platform.system.return_value = 'Linux'
46+
47+
@skip_if_windows('Not supported on Windows')
48+
def my_test():
49+
pass
50+
51+
assert getattr(my_test, '__unittest_skip__', False) is False
52+
53+
54+
class TestSkipIfUsingSerialImplementation:
55+
def test_bare_skip_if_using_serial_implementation_fails_immediately(self):
56+
with pytest.raises(TypeError):
57+
58+
@skip_if_using_serial_implementation
59+
def my_test():
60+
pass
61+
62+
def test_skip_if_using_serial_implementation_skips_when_serial(self):
63+
with mock.patch('tests.is_serial_implementation', return_value=True):
64+
65+
@skip_if_using_serial_implementation(
66+
'Not supported in serial mode'
67+
)
68+
def my_test():
69+
assert False
70+
71+
assert getattr(my_test, '__unittest_skip__', False) is True
72+
73+
def test_skip_if_using_serial_implementation_runs_when_not_serial(self):
74+
with mock.patch('tests.is_serial_implementation', return_value=False):
75+
76+
@skip_if_using_serial_implementation(
77+
'Not supported in serial mode'
78+
)
79+
def my_test():
80+
pass
81+
82+
assert getattr(my_test, '__unittest_skip__', False) is False
83+
84+
85+
class TestRequiresCrt:
86+
def test_bare_requires_crt_fails_immediately(self):
87+
with pytest.raises(TypeError):
88+
89+
@requires_crt
90+
def my_test():
91+
pass
92+
93+
def test_requires_crt_skips_when_no_crt(self):
94+
with mock.patch('tests.HAS_CRT', False):
95+
96+
@requires_crt()
97+
def my_test():
98+
assert False
99+
100+
assert getattr(my_test, '__unittest_skip__', False) is True
101+
102+
def test_requires_crt_runs_when_crt_available(self):
103+
with mock.patch('tests.HAS_CRT', True):
104+
105+
@requires_crt()
106+
def my_test():
107+
pass
108+
109+
assert getattr(my_test, '__unittest_skip__', False) is False

0 commit comments

Comments
 (0)