Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test helper that asserts all transitions occurred #38

Open
markrwilliams opened this issue Jan 18, 2017 · 2 comments
Open

Test helper that asserts all transitions occurred #38

markrwilliams opened this issue Jan 18, 2017 · 2 comments

Comments

@markrwilliams
Copy link
Collaborator

Automat should have a test helper that asserts all transitions occurred.

It might go a little something like this:

tracer = TraceAllTransitions()
someMachineInstance.traceWith(tracer)

# testing intensifies

assertHasAllTransitions(tracer, for_=SomeMachine)

...where the tracer stuff would come from #36

@markrwilliams
Copy link
Collaborator Author

(Per @tomprince)

@warner
Copy link
Collaborator

warner commented May 21, 2017

At dinner tonight, @markrwilliams and I came up with some ideas:

  • a context manager which takes one or more Transitioner instances, and returns an object with accumulates transitions that occur while the context is active (as a set)
  • a test function that takes a MethodicalMachine instance and returns a set of all transitions that are defined

Then standard set-intersection tests can be used to decide if the right transitions have been exercised. You could merge the traces of multiple context managers to look at combined coverage, or you could use setUp/tearDown to merge multiple test cases and check the results at the very end of the test class.

class Foo(object):
    m = MethodicalMachine()
    ...
f = Foo()
with gather_transitions(f.m) as edges:
    f.trigger_stuff()
assert edges.all_transitions() == Foo.m.all_transitions()

(the difference between a machine instance, like Foo.m, and a transitioner instance, like f.m, is pretty important, both for implementation and for discoverability/learnability/error-reporting. my example probably gets at least one of them wrong)

This also avoids the need to be able to name specific transitions, since the sets contain opaque objects (one per transition). This would let us continue to keep the tracing function private, and these opaque objects would be the strings or tuples that the tracing function provides.

#37 would, of course, need a way to name these things.

Other questions:

  • should the gatherer context-manager look at all transitions, of all Automat state machines? Or should we give it a list of classes, and it looks for all transitions of all machines used by those classes? Or a list of state machines? Or a list of transitioners?
  • pointing at specific transitioners would require that those objects exist before the context is entered, but many apps will only create the object that uses the state machine inside some wrapper method, so marking the class/factory object seems more usable (just like mock.patch can patch something other than what's about to be called)
  • using a context manager makes it easy to invoke multiple methods, in case it takes multiple steps to set up the transition
  • this would work by using the private tracing function from add tracing API, with docs #56 to accumulate transitions. we might want to enhance that method to accomodate multiple tracers (added/removed with a set, rather than a push-pull stack or return-the-old-tracer one-at-a-time method). This would allow the set_trace method to be used in the tests, while debugging the code that is failing to hit all transitions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants