dwhall / farc

Framework for state machines with run-to-completion concurrency using asyncio. Python 3.4 or later
MIT License
28 stars 6 forks source link

Allow to run several unit test cases independently #9

Open maxpeng opened 3 years ago

maxpeng commented 3 years ago

When I perform unit testing for the state machines using farc, I want to independently run several test cases. That is, I want to have a new loop created for each test. Currently, once we import the farc package, a default event loop, which is a class variable, is created for the Framework class.

class Framework(object):
    """Framework is a composite class that holds:
    - the asyncio event loop
    - the registry of AHSMs
    - the set of TimeEvents
    - the handle to the next TimeEvent
    - the table subscriptions to events
    """

    _event_loop = asyncio.get_event_loop()

I propose to add a class method to allow us to specify the used event loop and reset the Framework.

For example:

class Framework(object):
    """Framework is a composite class that holds:
    - the asyncio event loop
    - the registry of AHSMs
    - the set of TimeEvents
    - the handle to the next TimeEvent
    - the table subscriptions to events
    """

    #_event_loop = asyncio.get_event_loop()
    _event_loop = None

    ...

    @classmethod
    def init(cls, loop):
        cls._event_loop = loop
        cls._priority_dict.clear()
        # May need to reset other class variables too.

        # Bind a useful set of POSIX signals to the handler
        # (ignore a NotImplementedError on Windows)
        try:
            cls._event_loop.add_signal_handler(signal.SIGINT, lambda: Framework.stop())
            cls._event_loop.add_signal_handler(signal.SIGTERM, lambda: Framework.stop())
            cls._event_loop.add_signal_handler(29, Framework.print_info)
        except NotImplementedError:
            pass
dwhall commented 3 years ago

First concern is about these lines

    #_event_loop = asyncio.get_event_loop()
    _event_loop = None

this would force all existing users to change their code to use the new init() method. I believe the list of users is very small, but I would prefer not to force a method like this. I would leave out this code change and then only the people using init() will have the _event_loop that was instantiated by default be replaced by the one given in init().

Second concern is about people passing in outside event loops. farc assumes that the asyncio event loop is used. I don't know what would happen if other types of event loops were used.

If you have an example of your suggestion, I would appreciate seeing how it works. As in, you could create a fork of farc, make your suggested code modifications and also provide a generic example in the examples/ folder and submit a pull request.