Interestingly I had a (mail) discussion with someone else having the
same idea. I'll re-post here the relevant parts.
There I came to the same conclusion as Darren, but for partly
different reasons (while I also agree with Darren's notes as well):
1. I fear that such extension would increase the confusion about
whether SpecFlow should be used for unit testing or functional
testing. Currently we try to describe it as a functional testing tool
(inside the BDD story of course), because that’s the area where the
benefits of business readability more clearly overweight the
additional effort of the loose (free-text, regex, etc.) bindings. Many
SpecFlow users have realized that it can be also used for testing
technical interfaces (external APIs, web services, units, etc.), but
this is not yet a mainstream and I’m not sure that it is always
efficient. So I would first try find a good story, why this feature
would be also helpful for functional testing, before adding it to the
product.
2. The general workflow of swallowing / propagating and handling the
exceptions is quite complex and error prone in general.
E.g. if a “then” step is not prepared to run after a failing when
(some inconsistent state, for instance), in case of a real error (not
an expected one), the original error will be hidden by the error in
the unprepared “then” step. Also handling the case when there are
multiple “when” steps is hard as you would not be able to distinguish
in the assertion step, which when’s exception you want to assert.
I a scope of a concrete project it is easy to make rules to avoid this
confusion (only one “when”, etc.), but for making it as a generic
feature, I think this is too complex.
My conclusion was that this is something what SpecFlow can support
with allowing good extension points, but the concrete implementation
should not be part of the project (at least now).
I also did a little bit of experiments for "solve" this problem in
SpecFlow 1.6.1. I have two possible solutions.
In the first solution you have to use a “that results in an exception”
postfix for the steps in order to catch the exception. You can see a
working sample here:
http://dl.dropbox.com/u/51289/BlogAttachments/AssertException.zip.
I had to apply some tricks to work and also the config setting
“<runtime stopAtFirstError="true" />” was necessary. It also collects
the unhandled errors and re-throws them at the end of the scenario
(see the second scenario in the feature file). The benefit of this
solution that you can decide about the exception handling per scenario
and not in the step binding itself (so you can safely use it in normal
and expected-exception scenarios as well). The disadvantage is, that
it makes the "go to binding" unusable, as it will always point to the
generic step definition.
The other solution is more closer to what you have imagined. Basically
this is a unit-test provider plugin, that replaces the specflow test
runner to a custom one (AssertExceptionTestRunner), where you can do
the exception manipulation as necessary. You can download this one too
from here:
http://dl.dropbox.com/u/51289/BlogAttachments/AssertExceptionPlugin.zip.
To have this working, you need to do one extra steps. The “generator”
part of the customization (AssertExceptionPlugin.Generator.dll) has to
be placed into the “C:\Program Files (x86)\TechTalk\SpecFlow” folder
(or wherever specflow VS integration was installed to) and the
generator has to be configured in the app.config of the test project.
<specFlow>
<unitTestProvider name="NUnit"
generatorProvider="AssertExceptionPlugin.Generator.AssertExceptionTestGenerator,
AssertExceptionPlugin.Generator" />
</specFlow>
You also need stopAtFirstError="true" for this solution.
You should have a look at the AssertExceptionTestRunner class, where
there is an commented-out part, that limits this behavior only for
scenarios having a special tag. Also I have now separated the
generator/runtime part of the plugin into two different assemblies to
show more clearly what is used where. Since this plugin is quite
simple and it does not have any additional dependencies, these can be
safely merged into one for better maintainability.
These solutions work with SpecFlow 1.6.1. They are a little bit of
hacks, so there is a chance that you need to alter them for future
versions.
Have fun!
Br,
Gaspar