Comes down to discipline, correcting bad habits, having a good way of TDD to begin with. Every team member has to have buy in with unit testing, test driven. Also for code style probably someone already mentioned stylecop... and for correcting bad habits this catches some of them $1 in the broken build jar (style cop fails, a test fails, build fails).
I'm pretty hardcore about focusing on test driven, so in fact the standard run with debugger key in visual studio instead launches one of two rake commands: test:feature[highlightedCucumberTag] or test:class[selectedSpecification].
Our specifications are quite small because everything is a well defined unit. We do our best to avoid hard dependencies. So there is a c# file for each behaviour / scenario, and we use an add-in for visual studio to set the "depends on" of the Whens to the base specifcation such as:
Designer.Tests.Model.Observers....
Contained in folder Designer\Models\Observers
ObserverSpecification.cs
--->When_diffuser_observer_is_created.cs
--->[It] public void Should_return_the_expected_diffuser()
---->When_diffuser_observer_is_modified.cs
--->[It] public void Should_raise_property_notification_for_diffuser()
Nice way of organizing everything.
Here's a sample specificaiton:
using MavenThought.Commons.Testing;
using SharpTestsEx;
namespace Designer.Tests.Model.Observers
{
/// <summary>
/// Specification when diffuser observer is created
/// </summary>
[ConstructorSpecification]
public class When_diffuser_observer_is_created
: DiffuserObserverSpecification
{
/// <summary>
/// Checks the diffuser injection
/// </summary>
[It]
public void Should_return_the_injected_diffuser()
{
Sut.Diffuser.Should().Be.SameInstanceAs(this.ConcreteDiffuser);
}
}
}
and in this one we had to use a concrete diffuser because Diffuser is a core / domain object and hence we do not put property notification on it.
using System.ComponentModel;
using MavenThought.Commons.Testing;
using SharpTestsEx;
namespace Designer.Tests.Model.Observers
{
/// <summary>
/// Specification when diffuser observer has the injected diffuser change
/// </summary>
[Specification]
public class When_diffuser_observer_has_diffuser_property_change
: DiffuserObserverSpecification
{
/// <summary>
/// Listen to the property change of the SUT
/// </summary>
private PropertyChangedEventHandler _mockPropertyChangeHandler;
/// <summary>
/// Checks the diffuser injection
/// </summary>
[It]
public void Should_have_diffuser_changed()
{
this._mockPropertyChangeHandler.AssertPropertyChangedWasCalled(this.Sut, o => o.Diffuser.SupplyAirVolume);
}
/// <summary>
/// Mock up the property change handler
/// </summary>
protected override void GivenThat()
{
base.GivenThat();
_mockPropertyChangeHandler = MockIt(this._mockPropertyChangeHandler);
}
/// <summary>
/// Listen to property change of SUT
/// </summary>
protected override void AndGivenThatAfterCreated()
{
base.AndGivenThatAfterCreated();
Sut.PropertyChanged += _mockPropertyChangeHandler;
}
/// <summary>
/// Initialize the SUT with diffuser
/// </summary>
protected override void WhenIRun()
{
ConcreteDiffuser.SupplyAirVolume = 5;
}
}
}
Takes some discipline for practice, however, we have nothing even near 250 line methods for any one of our specifications.