Search code examples
c++unit-testingboostboost-statechart

Unit testing with boost::statechart


We are using the boost statechart library and have troubles writing unit tests for the code.

In our normal execution the state machine starts in ClosedState:

struct BoostStateMachine : sc::state_machine<BoostStateMachine, ClosedState >

We would like to test a specific state transition without having to traverse the state machine till that state, for example we would like to start the test in AnotherState. The problem is that sc::state_machine is templated on its initial state. Feeding the state machine with all the events that lead to the tested states, usually requires a lot of work and complicates the tests.

A primitive solution is to write special debug-only event and add it to ClosedState. This event will trigger an immediate transition to AnotherState.

Do you know any other way to accomplish the task?


Solution

  • I'll admit it's not great, but

    #ifdef DEBUG
    typedef AnotherState StartingState;
    #else
    typedef ClosedState StartingState;
    #endif
    struct BoostStateMachine : sc::state_machine<BoostStateMachine, StartingState > {...
    

    EDIT addressing comment

    #ifndef INITIAL_STATE
    #define INITIAL_STATE ClosedState
    #endif
    struct BoostStateMachine : sc::state_machine<BoostStateMachine, INITIAL_STATE > {...
    

    of course that means you need to recompile to do each test =[

    We could try the following:

    typedef<class InitialState>
    struct StateMachine : sc::state_machine< typename /*?*/ StateMachine<InitialState>, InitialState > {...}
    
    typedef StateMachine<ClosedState> BoostStateMachine; //default case
    
    #ifdef DO_TESTS
        ...
        StateMachine<AnotherState> astate1;
        ...
        StateMachine<AnotherState2> astate2;
        ...
        StateMachine<AnotherState3> astate3;
        ...
    #endif
    

    This of course does not help when it's a substate that needs to start in a different state. But the same thing could apply:

    typedef <typename InitialChild>
    struct ClosedState : sc::simple_state< ClosedState<InitialChild>, BoostStateMachine, InitialChild > {...};
    

    or something like it. I have done templated states before (so that I could have common sub-state sequences) and it is a royal PITA to debug (more so that the rest of statechart).