NUnit 2.5's new Theory feature - anyone grok it? [modified]
-
I'm going through my classic 3-stage grok-ing process in understanding a new concept. 1. Bafflement. 2. Understanding it but not seeing the point. 3. Seeing the point. I ran the sqrt example in the documentation, I've read around a bit The Practice of Theories[^] but I still can't see why you wouldn't just use parameterised (aka row) testing (NUnit's new TestCase attribute). Maybe its one of those cases where I won't really see the benefit until I encounter a scenario for which it's tailor-made?
Kevin
modified on Tuesday, May 12, 2009 11:23 AM
-
I'm going through my classic 3-stage grok-ing process in understanding a new concept. 1. Bafflement. 2. Understanding it but not seeing the point. 3. Seeing the point. I ran the sqrt example in the documentation, I've read around a bit The Practice of Theories[^] but I still can't see why you wouldn't just use parameterised (aka row) testing (NUnit's new TestCase attribute). Maybe its one of those cases where I won't really see the benefit until I encounter a scenario for which it's tailor-made?
Kevin
modified on Tuesday, May 12, 2009 11:23 AM
Your link looks odd - it goes back to CP?
-
Your link looks odd - it goes back to CP?
Cheers. Corrected now. Not sure what happened there! :doh: :-O
Kevin
-
Your link looks odd - it goes back to CP?
That's the Practise of Theory impatient one, you must Theorize harder in order truely follow the link.
10110011001111101010101000001000001101001010001010100000100000101000001000111100010110001011001011
-
I'm going through my classic 3-stage grok-ing process in understanding a new concept. 1. Bafflement. 2. Understanding it but not seeing the point. 3. Seeing the point. I ran the sqrt example in the documentation, I've read around a bit The Practice of Theories[^] but I still can't see why you wouldn't just use parameterised (aka row) testing (NUnit's new TestCase attribute). Maybe its one of those cases where I won't really see the benefit until I encounter a scenario for which it's tailor-made?
Kevin
modified on Tuesday, May 12, 2009 11:23 AM
Assert that: For all developers, there exists a subset that feel things are sometimes made more complicated than they need to be. Marc
-
I'm going through my classic 3-stage grok-ing process in understanding a new concept. 1. Bafflement. 2. Understanding it but not seeing the point. 3. Seeing the point. I ran the sqrt example in the documentation, I've read around a bit The Practice of Theories[^] but I still can't see why you wouldn't just use parameterised (aka row) testing (NUnit's new TestCase attribute). Maybe its one of those cases where I won't really see the benefit until I encounter a scenario for which it's tailor-made?
Kevin
modified on Tuesday, May 12, 2009 11:23 AM
That's sounding a bit like Haskell's QuickCheck[^], except without the automatic test-case generation. QuickCheck is incredibly useful - not only does it generate test cases, but it is very good at finding counter-cases (i.e. cases where your defined property (== NUnit Theory) doesn't hold).
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
I'm going through my classic 3-stage grok-ing process in understanding a new concept. 1. Bafflement. 2. Understanding it but not seeing the point. 3. Seeing the point. I ran the sqrt example in the documentation, I've read around a bit The Practice of Theories[^] but I still can't see why you wouldn't just use parameterised (aka row) testing (NUnit's new TestCase attribute). Maybe its one of those cases where I won't really see the benefit until I encounter a scenario for which it's tailor-made?
Kevin
modified on Tuesday, May 12, 2009 11:23 AM
Parameterized unit tests aren't that valuable by themselves. Couple them with static code analysis that fills in the parameters for you, then you've got something. I've been using the Microsoft Pex framework which utilizes a similar feature and statically analyzes your code to generate inputs that will cover all possible code paths. :cool: Then, if you wish, it will generate unit tests for each of these code paths. With that, you can start writing tests like this:
[Test]
void MyCodeDoesntCrash(int input)
{
SomeFunc(input);
}Pex will fill in all values for input that cause a different code path to be executed, then gives you the results of all the meaningful inputs. It's pretty nifty.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon Judah Himango
-
I'm going through my classic 3-stage grok-ing process in understanding a new concept. 1. Bafflement. 2. Understanding it but not seeing the point. 3. Seeing the point. I ran the sqrt example in the documentation, I've read around a bit The Practice of Theories[^] but I still can't see why you wouldn't just use parameterised (aka row) testing (NUnit's new TestCase attribute). Maybe its one of those cases where I won't really see the benefit until I encounter a scenario for which it's tailor-made?
Kevin
modified on Tuesday, May 12, 2009 11:23 AM
I haven't used it yet, but if i understand it correctly then i'm looking forward to it. Here's why:
public void ValidInputs(int diameter, int centerToCenter, Pricing engine)
{
if ( diameter >= 6 && diameter <= 160
&& centerToCenter >= 0 && centerToCenter <= 120 )
Assert.That(engine.Total(diameter, centerToCenter), Is.TypeOf(typeof(double)));
}I wrote this test the other day (well, roughly this test) to verify that i was getting something valid back from a certain calculation engine for each combination of valid inputs. Note that this test does nothing for inputs that are out of range, and doesn't attempt to verify that the calculated value is correct... merely that the calculation produces a number for any set of valid inputs. I could now re-write that as:
public void ValidInputs(int diameter, int centerToCenter, Pricing engine)
{
Assume.That(diameter, Is.AtLeast(6))
Assume.That(diameter, Is.AtMost(160))
Assume.That(centerToCenter, Is.AtLeast(0))
Assume.That(centerToCenter, Is.AtMost(120))
Assert.That(engine.Total(diameter, centerToCenter), Is.TypeOf(typeof(double)));
}Same idea, but now i'm explicit about what i'm doing: the test doesn't really pass when inputs are out of range, but it will only fail if they're in-range and the assertion fails. Other tests are then responsible for verifying that specific inputs produce correct outputs, out of range inputs produce the expected error, etc.
-
Parameterized unit tests aren't that valuable by themselves. Couple them with static code analysis that fills in the parameters for you, then you've got something. I've been using the Microsoft Pex framework which utilizes a similar feature and statically analyzes your code to generate inputs that will cover all possible code paths. :cool: Then, if you wish, it will generate unit tests for each of these code paths. With that, you can start writing tests like this:
[Test]
void MyCodeDoesntCrash(int input)
{
SomeFunc(input);
}Pex will fill in all values for input that cause a different code path to be executed, then gives you the results of all the meaningful inputs. It's pretty nifty.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon Judah Himango
Judah Himango wrote:
Pex will fill in all values for input that cause a different code path to be executed, then gives you the results of all the meaningful inputs. It's pretty nifty.
Interesting... I haven't really looked at Pex; i'd assumed it was a .NET adaption of their PICT pairwise testing tool. Can I assume then, that Pex isn't really useful for generating tests when the logic being tested is not entirely represented in managed code?
-
Judah Himango wrote:
Pex will fill in all values for input that cause a different code path to be executed, then gives you the results of all the meaningful inputs. It's pretty nifty.
Interesting... I haven't really looked at Pex; i'd assumed it was a .NET adaption of their PICT pairwise testing tool. Can I assume then, that Pex isn't really useful for generating tests when the logic being tested is not entirely represented in managed code?
Shog9 wrote:
Can I assume then, that Pex isn't really useful for generating tests when the logic being tested is not entirely represented in managed code?
Right. It's managed-only since it looks at the IL to do the static analysis. FYI, one of the guys behind Pex is CPian-turned-Microsoftie Jonathan de Halleux[^], who co-authored several articles here on CP with Marc Clifton. He also created the popular MbUnit framework.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon Judah Himango
-
Assert that: For all developers, there exists a subset that feel things are sometimes made more complicated than they need to be. Marc
Amen! Or should I say: AbstractPraiseManager.getInstance().getAffirmationRegistry().findAffirmationClass().instanceNew().prepareToAmenize().doIt();
-
Shog9 wrote:
Can I assume then, that Pex isn't really useful for generating tests when the logic being tested is not entirely represented in managed code?
Right. It's managed-only since it looks at the IL to do the static analysis. FYI, one of the guys behind Pex is CPian-turned-Microsoftie Jonathan de Halleux[^], who co-authored several articles here on CP with Marc Clifton. He also created the popular MbUnit framework.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon Judah Himango
Judah Himango wrote:
FYI, one of the guys behind Pex is CPian-turned-Microsoftie Jonathan DeHalleux, who co-authored several articles here on CP with Marc Clifton. He also created the popular MbUnit framework.
Ah, that's cool. I never used MbUnit (NUnit had a better website... ;-P ), but if i recall it had solid test generation long before NUnit. I'm more interested in doing black-box testing than strict, TDD-style unit testing, so seeing that folded into the testing frameworks has been gratifying.