-
Notifications
You must be signed in to change notification settings - Fork 7
StorEvil Context Classes
StorEvil instantiates classes that you create (Context Classes) in order to interpret specifications.
These Context classes are similar to Steps in Cucumber.
Your context classes must follow a few rules:
- Must be public and have the StoreEvil.Context attribute
- You must tell StorEvil the assemblies that contain your context classes using the storevil.config or a command-line switch.
for example:
[StorEvil.Context]
public class ExampleContext {
public void Given_some_precondition() {
}
}
Note that the types of any return values of context method for partial matches do not necessarily need to be public:
[StorEvil.Context]
public class ExampleContext {
public ExampleSubContext Given_some_precondition() {
return new ExampleSubContext();
}
}
internal class ExampleSubContext {
...
}
The lifetime of a context class can be set by using the “Lifetime” parameter on the Context Attribute.
[StorEvil.Context(Lifetime=StorEvil.ContextLifetime.Scenario)]
public class ExampleContextThatLivesForOneScenario { }
There are three possible settings for lifetime:
A new instance of the context class will be created for each scenario. Within a scenario, the same instance will be used. For scenario outlines, a new instance is created for each example.
A new instance of the context class will be created for each story (plaintext specification/feature file). Within a story, the same instance will be reused in each scenario.
A single instance of the context class will be created for the entire run. This is intended for use with, for example, setting up a Selenium or WATiN session, or initializing a database to a known state.
If you need to clean up some resources when a context is finished, implement IDisposable in your context class. It will be invoked when the scenario is complete.
StorEvil will do simple constructor injection of dependent contexts.
What this means is that any parameters to the constructor of a context object will be created when the context class is created.
These context instances, like all others, are shared between any classes reference them.
You can have one context that depends on another, or share a context class that is not used to parse grammar between contexts.
In this example, the UserAssertions and AdminUserContext context classes use the UserTestContext to store the state of the system as each step is executed.
The UserTestContext will be created when either of these classes is created (when any line matches a method in either class).
[StorEvil.Context]
public class AdminUserContext {
public AdminUserContext(UserTestContext user) {
_user = user;
}
public void Given_user_has_superuser_privileges() {
...
}
}
[StorEvil.Context]
public class UserAssertions {
public UserAssertionContext(UserTestContext user) {
_user = user; // same instance as given to AdminUserContext... one instance per type, per scenario
}
public void Then_user_should_be_an_admin() {
Assert.IsTrue(_user.IsAdministrator);
}
}
public class UserTestContext {
public CurrentUserId { get; set; }
public bool IsAdministrator {get; set; }
}
Contexts that depend on other contexts (as constructor parameters) cannot depend on contexts that have a shorter lifetime.
If a context class depends on another that has a shorter lifetime, a ConflictingLifetimeException will be thrown.