A couple of days ago Aaron Jensen released MSpec 0.2, a BDD-style testing framework. Since I got hooked on BDD during my last work project (readable test names!) I was eager giving MSpec a shot. MSpec comes with support for TestDriven.NET so using inside of Visual Studio is a no-brainer once you installed the MSpec support for TD.NET. The release contains everything you need.
Today I wrote my first couple of MSpec specifications and had a very good initial experience. However, there's one caveat with ReSharper's absolute killer feature (well, one of its many killer features): Code Cleanup. I usually like to type code without caring too much about its layout and then do a quick re-format to make it align with my formatting conventions.
ReSharper formatted the specification like this:
[Concern(typeof(StringExtensions), "String testing")]
public class When_a_null_string_is_tested_to_have_a_value : String_testing_specification
{
Establish context = () => { Sut = null; };
It it_should_not_hold_a_value = () => HasValue.ShouldBeFalse();
Because of = () => HasValue = Sut.HasValue();
}
The code structure should follow order in which the specification is run, like so:
[Concern(typeof(StringExtensions), "String testing")]
public class When_a_null_string_is_tested_to_have_a_value : String_testing_specification
{
Establish context = () => { Sut = null; };
Because of = () => HasValue = Sut.HasValue();
It it_should_not_hold_a_value = () => HasValue.ShouldBeFalse();
}
Luckily, ReSharper supports defining a custom type member layout to control in which order members are placed in a reformatted code file. Just add the following lines to ReSharper/Options/Languages/C#/Type Members Layout (uncheck "Use Default Patterns"), under the Patterns element:
<!-- Order Machine.Specifications methods: Members, Establish, Cleanup, Because, It -->
<Pattern>
<Match>
<And Weight="100">
<Kind Is="class"/>
<HasAttribute CLRName="Machine.Specifications.ConcernAttribute"
Inherit="true"/>
</And>
</Match>
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Or>
<Access Is="protected"/>
<Static/>
</Or>
</And>
</Match>
</Entry>
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Name Is="context_once"
IgnoreCase="true"/>
</And>
</Match>
</Entry>
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Name Is="context"
IgnoreCase="true"/>
</And>
</Match>
</Entry>
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Name Is="after_each"
IgnoreCase="true"/>
</And>
</Match>
</Entry>
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Name Is="after_all"
IgnoreCase="true"/>
</And>
</Match>
</Entry>
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Name Is="of"
IgnoreCase="true"/>
</And>
</Match>
</Entry>
<!--All other members-->
<Entry/>
</Pattern>