[Python] Using pytest to test a while loop in module level

Discussão em 'Python' iniciado por Stack, Julho 29, 2025.

  1. Stack

    Stack Membro Participativo

    I'm a beginner and I'm stuck with this problem:

    I want to write a test using pytest, but I'm having a hard time. I've tried many solutions from Google, YouTube, and StackOverflow, but none of them worked. Most suggestions say to refactor the code, but I really want to test it as-is, without changing the original code. I cannot change the original file because it's already in production and changing it could cause major side effects across the system.

    In my code (main.py), I have a boolean function check_condition() that returns False when something is wrong. The file structure looks like this:

    import time
    from utils import *

    def check_condition():
    if something_wrong:
    return False # Only get False by an external condition, not by the function's internal logic
    return True

    queue = get_MQ()
    while True:
    # some logic
    if not check_condition():
    break
    # some logic

    queue.close_connect()
    time.sleep(30)


    When check_condition() returns False, the main loop should break.
    I tried to patch check_condition with side_effect = [True, False] to simulate this in tests, but during testing, it always returns True, and the loop never exits.

    I printed some logs inside main.py and noticed that the code always executes fully during import, before the patch is even applied. It reaches the time.sleep(30) line at the end, then keeps restarting in an infinite loop — which is why the patch has no effect.

    Here’s a simplified version of my test case:

    @pytest.fixture()
    def mock_message_queue():
    with patch('mq.pika.BlockingConnection') as mock_conn, \
    patch('mq.pika.PlainCredentials'), \
    patch('mq.pika.ConnectionParameters'):

    mock_conn_instance = Mock()
    mock_channel = Mock()

    # Setup connection mock
    mock_conn_instance.is_open = True
    mock_conn_instance.channel.return_value = mock_channel
    mock_conn.return_value = mock_conn_instance

    # Setup channel mock
    mock_channel.is_open = True
    mock_channel.queue_declare.return_value = Mock()
    mock_channel.basic_publish.return_value = None
    mock_channel.basic_qos.return_value = None
    mock_channel.basic_consume.return_value = None
    mock_channel.start_consuming.return_value = None

    mq = MessageQueue(
    host=HOST,
    port=PORT,
    virtual_host=VIRTUAL_HOST,
    user=USER,
    password=PASSWORD
    )


    mq.get_channel = Mock(return_value=mock_channel)
    mq.send_message = Mock()

    mq._test_mocks = {
    'connection': mock_conn,
    'connection_instance': mock_conn_instance,
    'channel': mock_channel
    }

    yield mq

    try:
    mq.close()
    except:
    pass
    def test_main(mock_message_queue):
    sample_data = { } # Input data when run file main.py
    with \
    patch('utils.list_doc', return_value=[sample_data]), \
    patch('utils.get_MQ', return_value = mock_message_queue), \
    patch('main.check_condition', side_effect=[True,False]):
    import main # <-- this triggers the actual execution

    # Assertions (this part doesn't even get reached correctly)
    calls = mock_message_queue.send_message.call_args_list
    assert mock_message_queue.send_message.call_count == 3


    The issue seems to be that:


    • When I patch('main.check_condition'), it already imports main.py at patch time, so the logic is triggered before the patch takes effect.


    • As a result, check_condition() is not patched, and always returns True.


    • I confirmed this by printing logs from main.py, which shows the file goes through all logic and hits the final time.sleep() block.
    File structure



    project/
    ├── main.py
    ├── utils.py
    ├── test_main.py


    Has anyone dealt with this kind of issue before? How can I test a file like this without modifying the code?

    Any help would be appreciated. Thank you!

    "Please note again: refactoring is not an option due to production constraints."

    Continue reading...

Compartilhe esta Página