Skip to content

Commit 7e96370

Browse files
authored
gh-61215: threadingmock: Improve test suite to avoid race conditions (#106822)
threadingmock: Improve test suite to avoid race conditions Simplify tests and split them into multiple tests to prevent assertions from triggering race conditions. Additionally, we rely on calling the mocks without delay to validate the functionality of matching calls.
1 parent 2b94a05 commit 7e96370

File tree

1 file changed

+58
-137
lines changed

1 file changed

+58
-137
lines changed

Lib/test/test_unittest/testmock/testthreadingmock.py

+58-137
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
threading_helper.requires_working_threading(module=True)
1010

11+
VERY_SHORT_TIMEOUT = 0.1
12+
1113

1214
class Something:
1315
def method_1(self):
@@ -93,167 +95,86 @@ def test_no_name_clash(self):
9395
waitable_mock.wait_until_called()
9496
waitable_mock.wait_until_any_call_with("works")
9597

96-
def test_wait_success(self):
98+
def test_patch(self):
9799
waitable_mock = self._make_mock(spec=Something)
98100

99-
with patch(f"{__name__}.Something", waitable_mock):
100-
something = Something()
101-
self.run_async(something.method_1, delay=0.01)
102-
something.method_1.wait_until_called()
103-
something.method_1.wait_until_any_call_with()
104-
something.method_1.assert_called()
105-
106-
def test_wait_success_with_instance_timeout(self):
107-
waitable_mock = self._make_mock(timeout=1)
108-
109-
with patch(f"{__name__}.Something", waitable_mock):
110-
something = Something()
111-
self.run_async(something.method_1, delay=0.01)
112-
something.method_1.wait_until_called()
113-
something.method_1.wait_until_any_call_with()
114-
something.method_1.assert_called()
115-
116-
def test_wait_failed_with_instance_timeout(self):
117-
waitable_mock = self._make_mock(timeout=0.01)
118-
119-
with patch(f"{__name__}.Something", waitable_mock):
120-
something = Something()
121-
self.run_async(something.method_1, delay=0.5)
122-
self.assertRaises(AssertionError, waitable_mock.method_1.wait_until_called)
123-
self.assertRaises(
124-
AssertionError, waitable_mock.method_1.wait_until_any_call_with
125-
)
126-
127-
def test_wait_success_with_timeout_override(self):
128-
waitable_mock = self._make_mock(timeout=0.01)
129-
130-
with patch(f"{__name__}.Something", waitable_mock):
131-
something = Something()
132-
self.run_async(something.method_1, delay=0.05)
133-
something.method_1.wait_until_called(timeout=1)
134-
135-
def test_wait_failed_with_timeout_override(self):
136-
waitable_mock = self._make_mock(timeout=1)
137-
138-
with patch(f"{__name__}.Something", waitable_mock):
139-
something = Something()
140-
self.run_async(something.method_1, delay=0.5)
141-
with self.assertRaises(AssertionError):
142-
something.method_1.wait_until_called(timeout=0.05)
143-
144-
def test_wait_success_called_before(self):
145-
waitable_mock = self._make_mock()
146-
147101
with patch(f"{__name__}.Something", waitable_mock):
148102
something = Something()
149103
something.method_1()
150104
something.method_1.wait_until_called()
151-
something.method_1.wait_until_any_call_with()
152-
something.method_1.assert_called()
153-
154-
def test_wait_magic_method(self):
155-
waitable_mock = self._make_mock()
156105

157-
with patch(f"{__name__}.Something", waitable_mock):
158-
something = Something()
159-
self.run_async(something.method_1.__str__, delay=0.01)
160-
something.method_1.__str__.wait_until_called()
161-
something.method_1.__str__.assert_called()
162-
163-
def test_wait_until_any_call_with_positional(self):
106+
def test_wait_already_called_success(self):
164107
waitable_mock = self._make_mock(spec=Something)
108+
waitable_mock.method_1()
109+
waitable_mock.method_1.wait_until_called()
110+
waitable_mock.method_1.wait_until_any_call_with()
111+
waitable_mock.method_1.assert_called()
165112

166-
with patch(f"{__name__}.Something", waitable_mock):
167-
something = Something()
168-
self.run_async(something.method_1, 1, delay=0.2)
169-
self.assertNotIn(call(1), something.method_1.mock_calls)
170-
self.run_async(something.method_1, 2, delay=0.5)
171-
self.run_async(something.method_1, 3, delay=0.6)
172-
173-
something.method_1.wait_until_any_call_with(1)
174-
something.method_1.assert_called_with(1)
175-
self.assertNotIn(call(2), something.method_1.mock_calls)
176-
self.assertNotIn(call(3), something.method_1.mock_calls)
177-
178-
something.method_1.wait_until_any_call_with(3)
179-
self.assertIn(call(2), something.method_1.mock_calls)
180-
something.method_1.wait_until_any_call_with(2)
181-
182-
def test_wait_until_any_call_with_keywords(self):
113+
def test_wait_until_called_success(self):
183114
waitable_mock = self._make_mock(spec=Something)
115+
self.run_async(waitable_mock.method_1, delay=VERY_SHORT_TIMEOUT)
116+
waitable_mock.method_1.wait_until_called()
184117

185-
with patch(f"{__name__}.Something", waitable_mock):
186-
something = Something()
187-
self.run_async(something.method_1, a=1, delay=0.2)
188-
self.assertNotIn(call(a=1), something.method_1.mock_calls)
189-
self.run_async(something.method_1, b=2, delay=0.5)
190-
self.run_async(something.method_1, c=3, delay=0.6)
191-
192-
something.method_1.wait_until_any_call_with(a=1)
193-
something.method_1.assert_called_with(a=1)
194-
self.assertNotIn(call(b=2), something.method_1.mock_calls)
195-
self.assertNotIn(call(c=3), something.method_1.mock_calls)
196-
197-
something.method_1.wait_until_any_call_with(c=3)
198-
self.assertIn(call(b=2), something.method_1.mock_calls)
199-
something.method_1.wait_until_any_call_with(b=2)
200-
201-
def test_wait_until_any_call_with_no_argument_fails_when_called_with_arg(self):
202-
waitable_mock = self._make_mock(timeout=0.01)
203-
204-
with patch(f"{__name__}.Something", waitable_mock):
205-
something = Something()
206-
something.method_1(1)
207-
208-
something.method_1.assert_called_with(1)
209-
with self.assertRaises(AssertionError):
210-
something.method_1.wait_until_any_call_with()
118+
def test_wait_until_called_method_timeout(self):
119+
waitable_mock = self._make_mock(spec=Something)
120+
with self.assertRaises(AssertionError):
121+
waitable_mock.method_1.wait_until_called(timeout=VERY_SHORT_TIMEOUT)
211122

212-
something.method_1()
213-
something.method_1.wait_until_any_call_with()
123+
def test_wait_until_called_instance_timeout(self):
124+
waitable_mock = self._make_mock(spec=Something, timeout=VERY_SHORT_TIMEOUT)
125+
with self.assertRaises(AssertionError):
126+
waitable_mock.method_1.wait_until_called()
214127

215-
def test_wait_until_any_call_with_global_default(self):
128+
def test_wait_until_called_global_timeout(self):
216129
with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"):
217-
ThreadingMock.DEFAULT_TIMEOUT = 0.01
218-
m = self._make_mock()
130+
ThreadingMock.DEFAULT_TIMEOUT = VERY_SHORT_TIMEOUT
131+
waitable_mock = self._make_mock(spec=Something)
219132
with self.assertRaises(AssertionError):
220-
m.wait_until_any_call_with()
221-
with self.assertRaises(AssertionError):
222-
m.wait_until_called()
133+
waitable_mock.method_1.wait_until_called()
223134

224-
m()
225-
m.wait_until_any_call_with()
226-
assert ThreadingMock.DEFAULT_TIMEOUT != 0.01
135+
def test_wait_until_any_call_with_success(self):
136+
waitable_mock = self._make_mock()
137+
self.run_async(waitable_mock, delay=VERY_SHORT_TIMEOUT)
138+
waitable_mock.wait_until_any_call_with()
227139

228-
def test_wait_until_any_call_with_change_global_and_override(self):
229-
with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"):
230-
ThreadingMock.DEFAULT_TIMEOUT = 0.01
140+
def test_wait_until_any_call_with_instance_timeout(self):
141+
waitable_mock = self._make_mock(timeout=VERY_SHORT_TIMEOUT)
142+
with self.assertRaises(AssertionError):
143+
waitable_mock.wait_until_any_call_with()
231144

232-
m1 = self._make_mock()
233-
self.run_async(m1, delay=0.1)
145+
def test_wait_until_any_call_global_timeout(self):
146+
with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"):
147+
ThreadingMock.DEFAULT_TIMEOUT = VERY_SHORT_TIMEOUT
148+
waitable_mock = self._make_mock()
234149
with self.assertRaises(AssertionError):
235-
m1.wait_until_called()
150+
waitable_mock.wait_until_any_call_with()
236151

237-
m2 = self._make_mock(timeout=1)
238-
self.run_async(m2, delay=0.1)
239-
m2.wait_until_called()
240-
241-
m3 = self._make_mock()
242-
self.run_async(m3, delay=0.1)
243-
m3.wait_until_called(timeout=1)
244-
245-
m4 = self._make_mock()
246-
self.run_async(m4, delay=0.1)
247-
m4.wait_until_called(timeout=None)
152+
def test_wait_until_any_call_positional(self):
153+
waitable_mock = self._make_mock(timeout=VERY_SHORT_TIMEOUT)
154+
waitable_mock.method_1(1, 2, 3)
155+
waitable_mock.method_1.wait_until_any_call_with(1, 2, 3)
156+
with self.assertRaises(AssertionError):
157+
waitable_mock.method_1.wait_until_any_call_with(2, 3, 1)
158+
with self.assertRaises(AssertionError):
159+
waitable_mock.method_1.wait_until_any_call_with()
248160

249-
m5 = self._make_mock(timeout=None)
250-
self.run_async(m5, delay=0.1)
251-
m5.wait_until_called()
161+
def test_wait_until_any_call_kw(self):
162+
waitable_mock = self._make_mock(timeout=VERY_SHORT_TIMEOUT)
163+
waitable_mock.method_1(a=1, b=2)
164+
waitable_mock.method_1.wait_until_any_call_with(a=1, b=2)
165+
with self.assertRaises(AssertionError):
166+
waitable_mock.method_1.wait_until_any_call_with(a=2, b=1)
167+
with self.assertRaises(AssertionError):
168+
waitable_mock.method_1.wait_until_any_call_with()
252169

253-
assert ThreadingMock.DEFAULT_TIMEOUT != 0.01
170+
def test_magic_methods_success(self):
171+
waitable_mock = self._make_mock()
172+
str(waitable_mock)
173+
waitable_mock.__str__.wait_until_called()
174+
waitable_mock.__str__.assert_called()
254175

255176
def test_reset_mock_resets_wait(self):
256-
m = self._make_mock(timeout=0.01)
177+
m = self._make_mock(timeout=VERY_SHORT_TIMEOUT)
257178

258179
with self.assertRaises(AssertionError):
259180
m.wait_until_called()

0 commit comments

Comments
 (0)