From 7a7e32169f02e3fb9409b07862082a54c0f162fa Mon Sep 17 00:00:00 2001 From: Marcel Wilson Date: Fri, 22 Sep 2023 11:41:55 -0500 Subject: [PATCH] fixing https://github.com/ScreenPyHQ/screenpy/issues/102 --- screenpy/actions/eventually.py | 17 ++++++++++++++--- tests/test_actions.py | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/screenpy/actions/eventually.py b/screenpy/actions/eventually.py index dc897d2..ae08d2a 100644 --- a/screenpy/actions/eventually.py +++ b/screenpy/actions/eventually.py @@ -3,7 +3,8 @@ """ import time -from typing import Dict, Optional +from traceback import format_tb +from typing import Optional from screenpy.actor import Actor from screenpy.configuration import settings @@ -138,7 +139,8 @@ def perform_as(self, the_actor: Actor) -> None: return except Exception as exc: # pylint: disable=broad-except self.caught_error = exc - self.unique_errors[exc] = None + if not any(same_exception(exc, c) for c in self.unique_errors): + self.unique_errors.append(exc) count += 1 time.sleep(self.poll) @@ -158,6 +160,15 @@ def __init__(self, performable: Performable): self.performable = performable self.performable_to_log = get_additive_description(self.performable) self.caught_error = None - self.unique_errors: Dict[Exception, None] = {} + self.unique_errors: list[BaseException] = [] self.timeout = settings.TIMEOUT self.poll = settings.POLLING + + +def same_exception(a: BaseException, b: BaseException) -> bool: + """compare exceptions to see if they match""" + return ( + isinstance(a, type(b)) + and (str(a) == str(b)) + and (format_tb(a.__traceback__) == format_tb(b.__traceback__)) + ) diff --git a/tests/test_actions.py b/tests/test_actions.py index 486d7e0..56ef0b8 100644 --- a/tests/test_actions.py +++ b/tests/test_actions.py @@ -300,6 +300,24 @@ def test_mention_all_errors_in_order(self, mocked_time, Tester): " AssertionError: Failure #5" ) + @mock.patch("screenpy.actions.eventually.time", autospec=True) + def test_mention_multiple_errors_once(self, mocked_time, Tester): + mocked_time.time = mock.create_autospec(time.time, side_effect=[1, 1, 1, 100]) + mock_question = FakeQuestion() + mock_question.answered_by.return_value = True + mock_question.describe.return_value = "returns bool" + + with pytest.raises(DeliveryError) as actual_exception: + Eventually(See(mock_question, IsEqualTo(False))).perform_as(Tester) + + assert str(actual_exception.value) == ( + "Tester tried to Eventually see if returns bool is equal to False 3 times " + "over 20.0 seconds, but got:\n" + " AssertionError: \n" + "Expected: \n" + " but: was \n" + ) + def test_describe(self) -> None: mock_action = FakeAction() mock_action.describe.return_value = "An African or a European swallow?"