I have completely switched from the classic approach for TDD to the more modern and logical BDD (Behavior Driven Design). In the case of your Number class, I would write the following BDD Specifications (Note that the syntax below is done with SubSpec, which relies on xUnit.NET):
public void Parameterless_constructor_initializes_all_defaults_properly()
{
// State
Number number = null;
// Context
"Given a null context".Context(() => {});
// Concern
"when creating a new Number with no parameters".Do(() => { number = new Number(); });
// Observations
"the Value property should contain the default value 0".Assert(() => Assert.Equal(0, number.value));
"the MinValue property should be 0".Assert(() => Assert.Equal(0, number.MinValue));
"the MaxValue property should be 100".Assert(() => Assert.Equal(100, number.MaxValue));
}
public void Single_parameter_constructor_initializes_all_defaults_and_initial_value_properly()
{
// State
Number number = null;
// Context
"Given a null context".Context(() => {});
// Concern
"when creating a new Number with the initial value".Do(() => { number = new Number(10); });
// Observations
"the Value property should contain the value 10".Assert(() => Assert.Equal(10, number.value));
"the MinValue property should be 0".Assert(() => Assert.Equal(0, number.MinValue));
"the MaxValue property should be 100".Assert(() => Assert.Equal(100, number.MaxValue));
}
public void Full_constructor_initializes_all_values_properly()
{
// State
Number number = null;
// Context
"Given a null context".Context(() => {});
// Concern
"when creating a new Number with the initial, min, and max values".Do(() => { number = new Number(10, 1, 50); });
// Observations
"the Value property should contain the value 10".Assert(() => Assert.Equal(10, number.value));
"the MinValue property should be 1".Assert(() => Assert.Equal(1, number.MinValue));
"the MaxValue property should be 50".Assert(() => Assert.Equal(50, number.MaxValue));
}
In addition, I noticed that you also have a possible exceptional scenario for your full constructor, when the min value is greater than the max value. You would also want to verify proper behavior in this exceptional case:
public void Full_constructor_throws_proper_exception_when_minvalue_greater_than_maxvalue()
{
// State
Number number = null;
Exception expectedEx = null;
// Context
"Given a null context".Context(() => {});
// Concern
"when creating a new Number with inverted min and max values".Do(
() =>
{
try { number = new Number(10, 50, 1); }
catch (Exception ex) { expectedEx = ex }
}
);
// Observations
"an exception should be thrown".Assert(() => Assert.NotNull(expectedEx));
"the exception should be an ArgumentException".Assert(() => Assert.IsType<ArgumentException>(expectedEx));
}
The above specifications should give you 100% test coverage. They also produce a very nice, human readable, logical report when executed with xunit.net and output the default report.