Storyteller 4.2 added a new ability to apply additive, reusable extensions or add ons to a Storyteller specification project:
- ASP.Net Core Systems
- Relational Databases
- Selenium Integration
- Subcutaneous Testing against Redux Applications
- TestRail
Using IExtension
Extensions are implementations of the IExtension
interface shown below:
public interface IExtension : IDisposable
{
Task Start();
void BeforeEach(ISpecContext context);
void AfterEach(ISpecContext context);
}
As a concrete example, here's the very early (and naive) version of a simplistic extension to add Selenium support to a running Storyteller project that just manages the lifecycle of the Selenium IWebDriver object being used in the specifications:
public class SeleniumExtension : IExtension
{
private readonly Func<IWebDriver> _source;
private IWebDriver _driver;
// You'd want the web driver construction done lazily
// so that it can be parallelized with the system bootstrapping
public SeleniumExtension(Func<IWebDriver> source)
{
_source = source;
}
// Clean up after your
public void Dispose()
{
_driver?.Close();
_driver?.Dispose();
}
// This is executed during the bootstrapping of the system
// under test
public Task Start()
{
return Task.Factory.StartNew(() =>
{
_driver = _source();
});
}
// This gets executed right before each specification
// run. In this case, it puts the current IWebDriver
// where the related ScreenFixture can find it during
// Specification runs
public void BeforeEach(ISpecContext context)
{
context.State.Store(_driver);
}
public void AfterEach(ISpecContext context)
{
// Nothing
}
}
The extension has some value to establish a pattern of how the rather expensive Selenium IWebDriver object is bootstrapped, applied to subsequent specifications, and a clean system under test shutdown -- which is absolutely vital for iterating on automated tests and frequently ignored.
The AfterEach(ISpecContext)
method shown above doesn't do anything in this case, but in other extensions it's been a great place
to add custom logging to the Storyteller results.
Now, to apply an IExtension
, you just need to add it to the CellHandling.Extensions
list as you create your ISystem for your Storyteller specification project.
Here's an example from Storyteller's internal sample project:
public class SeleniumSystem : SimpleSystem
{
protected override void configureCellHandling(CellHandling handling)
{
handling.Extensions.Add(new SeleniumExtension(() => new ChromeDriver()));
}
}