The python API allows simulation. Simulation has the following benefits:

There are however restrictions. If the definition has large loops due to Repeat date attributes, which run indefinitely, then in this case the simulation will never complete, and will timeout after a years worth of run time. Hence it's best to restrict simulation, to definitions which are known to complete.
If the simulation does not complete it will produce two files, which will help in the analysis:

Both files will show which nodes are holding, and include the state of the holding trigger expressions.
def simulate_deadlock():

This simulation is expected to fail, since we have a deadlock/ race condition

defs = ecflow.Defs() # create a empty defs
suite = defs.add_suite("dead_lock")
fam = suite.add_family("family")
fam.add_task("t1").add_trigger("t2 == complete")
fam.add_task("t2").add_trigger("t1 == complete")
theResult = defs.simulate(); # simulate the definition
assert len(theResult) != 0, "Expected simulation to return errors" 
print theResult
if _name_ == "_main_":
    simulate_deadlock()