How to develop a NUnit theory?

I created NUnit Theory to help me verify the code. The actual verified code is not as important to this issue as the data that I use to verify it. Namely, hours and minutes of time in 24-hour mode.

I wrote my tool in such a way as to take advantage of the capabilities and comply with the restrictions in the function of NUnit 2.6 Theory. In particular, I felt that I needed to create classes such as “Hour” and “Minutes” to bypass the function that Datapoints map to arguments with the exact type.

[TestFixture] public class TimeWindowParserTheoryFixture { public class Hour { public int Value; } public class Minute { public int Value; public string AsString { get { return Value.ToString("00"); } } } [Datapoints] public IEnumerable<Hour> Hours { get { return Enumerable .Range(0, 25) .Select(v => new Hour() { Value = v }) .Union(Enumerable.Repeat((Hour)null, 1)); } } [Datapoints] public IEnumerable<Minute> Minutes { get { return Enumerable .Range(0, 60) .Select(v => new Minute() { Value = v }) .Union(Enumerable.Repeat((Minute)null, 1)); } } [Datapoints] public IEnumerable<string> Separators { get { return new[] { " ", "-" }; } } [Theory] public void ValidHours(Hour startHour, Minute startMinute, Hour endHour, Minute endMinute, string separator) { Assume.That(startHour != null); Assume.That(endHour != null); var parser = new TimeWindowParser(); var startMinutesString = String.Format("{0}{1}", startMinute == null ? "" : ":", startMinute == null ? "" : startMinute.AsString); var endMinutesString = String.Format("{0}{1}", endMinute == null ? "" : ":", endMinute == null ? "" : endMinute.AsString); var pattern = String.Format("{0}{1}{2}{3}{4}{5}{6}", startHour, startMinutesString, "", separator, endHour, endMinutesString, ""); //Console.WriteLine(pattern); var result = parser.Parse(pattern); Assert.That(result, Is.Not.Null); Assert.That(result.Start, Is.EqualTo(startHour)); Assert.That(result.End, Is.EqualTo(endHour)); } } 

What I found is that the size of the data set created during the default combinatorial logic of NUnit causes the file size to be so large that I run out of memory. This is not like I set up my test, and the data should be a problem, but since this is obviously the case, I ask for advice on how to think about this problem differently. Here is the OutOfMemoryException stack trace that I get.

 System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at System.Text.StringBuilder.ExpandByABlock(Int32 minBlockCharCount) at System.Text.StringBuilder.Append(Char* value, Int32 valueCount) at System.Text.StringBuilder.AppendHelper(String value) at System.Text.StringBuilder.Append(String value) at NUnit.Core.MethodHelper.GetDisplayName(MethodInfo method, Object[] arglist) at NUnit.Core.Builders.NUnitTestCaseBuilder.BuildSingleTestMethod(MethodInfo method, Test parentSuite, ParameterSet parms) 

This exception is odd in itself in the sense that it is thrown by simply trying to get the name of the Test method (see GetDisplayName). I am not sure if this is a mistake (known or otherwise). BTW, I get a very similar OOM exception when I overwrite this fixture using the less experimental Range and Value attributes used in parameter tests.

+7
source share
1 answer

Your question is about the mechanics of using Theory, but I want to talk about the “theory of theories” first, then back to the implementation details.

THEORY OF THEORIES

You should use Theory if you have a theory to start with. Otherwise, you simply use Datapoints to manage traditional example-based testing. “Having a theory”, I mean the general statement of truth that you want to prove by a certain set of inputs. A generalization of the theory (code) will go through possible inputs and filter out everything that does not meet your assumptions. An example of a good theory is: for any positive real number, the square root multiplied by itself will give the same number. "

Looking at your test, I can’t understand what theory your theory is trying to prove. This is similar to a standard parameterized test, except that you are using DataPoints. The only assumption you need to make is that minuts are not null, which is odd since you are providing minutes in the first place.

Bottom line: I do not think this is a good theory.

MECHANICS

You generate 24 * 24 * 60 * 60 * 2 DataPoints. This is a hell of a lot of data. Do you have reason to believe that your parsing algorithm can work, say, 24:13, but 24:14 does not work?

It is true that Datapoints are used combinatorially, and it would be better if they were used in pairs. But remember, DataPoints are just one of many ways to throw data into Theory. The idea is that Theories should process any data you give them.

ALTERNATIVE

I would write this as a test, since I cannot think of any theory about your parser or the parsers in general that will be applied. I would only give test data, probably using TestCaseSourceAttribute, pointing to a method that generated valid strings or just a large array of strings. I will have another test that would handle various invalid data.

Charlie

+10
source

All Articles