Skip to content

Commit 586c7f7

Browse files
authored
chore(bigtable): fix flaky batcher flush interval test (googleapis#17545)
**Flaky test**: - The unit test `test_mutations_batcher_flush_interval` was flaky under load because it relied on real wall-clock sleep durations (`time.sleep(0.4)` and `time.sleep(0.1)`). On busy VM executors, minor CPU scheduling delays caused the test thread to wake up out of sync with the background `threading.Timer` execution thread, triggering sporadic test failures. **Solution**: - Refactored the test to completely mock `threading.Timer` instead of relying on real-time sleeps: a. Verifies that `MutationsBatcher` instantiates the background timer with the correct `flush_interval` and starts it. b. Manually triggers the timer's callback function to verify it calls `flush()` synchronously. This makes the unit test 100% deterministic, immune to VM executor load, and significantly faster.
1 parent 234c7c5 commit 586c7f7

1 file changed

Lines changed: 7 additions & 10 deletions

File tree

packages/google-cloud-bigtable/tests/unit/v2_client/test_batcher.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
# limitations under the License.
1414

1515

16-
import time
17-
1816
import mock
1917
import pytest
2018

@@ -175,23 +173,22 @@ def test_mutations_batcher_context_manager_flushed_when_closed():
175173
assert table.mutation_calls == 1
176174

177175

176+
@mock.patch("google.cloud.bigtable.batcher.threading.Timer")
178177
@mock.patch("google.cloud.bigtable.batcher.MutationsBatcher.flush")
179-
def test_mutations_batcher_flush_interval(mocked_flush):
178+
def test_mutations_batcher_flush_interval(mocked_flush, mocked_timer):
180179
table = _Table(TABLE_NAME)
181180
flush_interval = 0.5
182181
mutation_batcher = MutationsBatcher(table=table, flush_interval=flush_interval)
183182

184-
assert mutation_batcher._timer.interval == flush_interval
185-
mocked_flush.assert_not_called()
186-
187-
time.sleep(0.4)
183+
mocked_timer.assert_called_once_with(flush_interval, mutation_batcher.flush)
184+
mocked_timer.return_value.start.assert_called_once_with()
188185
mocked_flush.assert_not_called()
189186

190-
time.sleep(0.1)
187+
# Manually invoke the timer callback to verify it calls flush
188+
timer_callback = mocked_timer.call_args[0][1]
189+
timer_callback()
191190
mocked_flush.assert_called_once_with()
192191

193-
mutation_batcher.close()
194-
195192

196193
def test_mutations_batcher_response_with_error_codes():
197194
from google.rpc.status_pb2 import Status

0 commit comments

Comments
 (0)