-
-
Save forki/835226 to your computer and use it in GitHub Desktop.
public class Math | |
{ | |
public static int Fac(int x) | |
{ | |
if (x <= 1) | |
return 1; | |
return Fac(x - 1)*x; | |
} | |
} | |
public class TestCaseList<T> : TestCaseList | |
{ | |
readonly List<T> _data = new List<T>(); | |
public TestCaseList<T> Add(T item) | |
{ | |
_data.Add(item); | |
return this; | |
} | |
} | |
public static class Data | |
{ | |
public static TestCaseList<T> Create<T>(T item) | |
{ | |
return new TestCaseList<T>().Add(item); | |
} | |
public static TestCaseList<Tuple<T, S>> Create<T, S>(T x, S y) | |
{ | |
return Create(Tuple.Create(x, y)); | |
} | |
public static TestCaseList<Tuple<T, S>> Create<T, S>(this TestCaseList<Tuple<T, S>> list, T x, S y) | |
{ | |
return list.Add(Tuple.Create(x, y)); | |
} | |
} | |
public interface TestCaseList | |
{ | |
} | |
public delegate TestCaseList TestData(); | |
public delegate void Establish<in T>(T x); | |
public delegate void Establish<in T, in S>(T x, S y); | |
public class when_calculating_fac_of_ITEM1 | |
{ | |
static int x; | |
static int y; | |
static int result; | |
TestData data = | |
() => | |
Data | |
.Create(1, 1) | |
.Create(2, 2); | |
Establish<int, int> context = (a,b) => | |
{ | |
x = a; | |
y = b; | |
}; | |
Because of = () => result = Math.Fac(x); | |
It should_equal_ITEM2 = () => result.ShouldEqual(y); | |
} |
I like the idea to have the test data inline in the spec. However multiple problems with the syntax you've chosen:
a) You can't redefine the Establish, Because and It delegates. They are all of the type "void del()"
b) I don't think that all AAA steps need to or even should be parametrized. If you ask me, parametrization should only be done at the level of Establish. This however raises the question of how to do that without changing the Establish delegate. ;-( Just a quick thought, but I think that parametrization has to be outside of the scope of Establish in order to ensure backwards compatibility.
c)I don't think the generic type - parameters in the spec are necessary (or useful in this context for that for that matter)
This leaves us with your TestData. How about this:
public class when_calculating_fac
{
static int result;
Data<Tuple<int,int>> data = Data.Create(() =>
{
yield return Tuple.Create(1, 1);
yield return Tuple.Create(2, 2);
...
});
Establish context = () => { ... };
Because of = () => result = Fac(data.Current.Item1);
It should_equal_the_fac = () => result.ShouldEqual(data.Current.Item2);
}
What do you think?
Another think I would like to add to the parametrization mix, is encoding the parameters in the context / specification names. So that each run can be displayed as a separate spec in the report. Something like "Given_the_number_is_PARAM1_when_calculating_fac : should_return_RETURN1()"
Hi Björn,
thanks for the feedback. I added your suggestions and removed a little bit of noise. I think this could lead to something.
Regards,
Steffen
I absolutely don't like the noise added by the generic Establish delegates:
Establish<int, int> context = (a,b) =>
{
x = a;
y = b;
};
Rest of the stuff looks good though. One point to mention about why I thought Data<> was a good idea. I wanted that information to be compile time visible so that it information about what type is contained can be extracted without having to execute the delegate. Would be nice for reporting (I guess ;-)).
Cheers
Björn
Doesn't compile. Just an idea how it could look like.