A few weeks ago, we challenged you to solve the problem of working with external data formats. Most of the good solutions involved moving the complexity of formats and unique value generators away from Given-When-Then steps, and into the automation code. This week, we’re going a bit deeper into the technical implementation parts of that solution. Zoltan Toth (Developer, SpecFlow team at Tricentis) provided a fully working example project that demonstrates the key automation aspects.
- Use the concept business time, provided by a domain service, to control timestamps and make tests repeatable
- Use the idea of automated unique identifier service to avoid testing for random numbers or complex GUIDs
- Simplify the manipulation of complex data formats by using templated messages, and listing only important values in for a specific test case in feature files
- Print out the full message (with replacements applied to a template) to test logs, so they can be audited in the reports.
There’s one more interesting trick to point out in this project: injecting dependencies into step implementations.
SpecFlow has a dependency injection container, so it can provide easy access to service and collaborator classes, minimizing the amount of configuration required to wire dependencies for testing. This is often useful to give step implementation access to test drivers, page objects, or similar utility classes. When the collaborator is a concrete class, the container can guess the correct implementation and provide it automatically.
When the collaborator is specified as an interface (as it is in this project), SpecFlow can’t guess the correct implementation automatically. However, you can enable dependency injection for interfaces by registering a concrete implementation with an object container. In the example project, you can see this in action if you look at the Hooks/ContainerSetup.cs file. It registers two collaborator interfaces for step implementations, one to provide business time, and the other generates payment orders.
For more information on registering interfaces with SpecFlow dependency injection, check out the Context Injection documentation page. If your project already uses a different dependency injection framework, you can also tell SpecFlow to that, to avoid duplicating the context. Check the same page for more information on that as well.
PS: … and don’t forget to share the challenge with your friends and team members by clicking on one of the social icons below 👇