A somewhat cut down example here from some PyTest unit tests that never exit. If I stick a break point on DataListener.__init__
I see it getting called from the from controller import Controller
statement in test_controller.py
which was a bit of a suprise to me; Why does importing a class from a module instantiate an instance of it?
class DataListener:
def __init__(self, port, host='localhost'):
self._stop_monitor = Event()
self._monitor = Thread(target=self.check_last_message)
self._monitor.start()
def __del__(self):
self.stop()
def stop(self):
self._stop_monitor.set()
self._monitor.join()
def check_last_message(self):
while not self._stop_monitor.is_set():
# Code to check for a heartbeat here
pass
from data_listener import DataListener
class Controller:
def __init__(
self,
subscriber=DataListener(port=DEFAULT_SUBSCRIBER_PORT),
publisher=JsonPublisher(DEFAULT_PUBLISHER_PORT)):
pass
from controller import Controller
def test_controller_work_loop():
# ARRANGE
controller = Controller(subscriber=None, publisher=None)
# Some actual tests here
# This test passes and finishes but the test suite never exits
Default arguments are evaluated when the class is loaded.
from data_listener import DataListener
class Controller:
def __init__(
self,
subscriber=DataListener(port=DEFAULT_SUBSCRIBER_PORT), # These are run!
publisher=JsonPublisher(DEFAULT_PUBLISHER_PORT)):
pass
You need to update your Controller
class to initialize them lazily in your initializer
from data_listener import DataListener
class Controller:
def __init__(self, subscriber=None, publisher=None):
self.subscriber = subscriber or DataListener(port=DEFAULT_SUBSCRIBER_PORT)
self.publisher = publisher or JsonPublisher(DEFAULT_PUBLISHER_PORT)