Re: NUnit 2.5: What's In It Now

"Kelly Anderson" <[email protected]> Tue, 8 Apr 2008 20:07:01 -0600
Newsgroups gmane.comp.windows.dotnet.nunit.devel
Message-ID <[email protected]>
On Tue, Apr 8, 2008 at 6:51 PM, Charlie Poole
<[email protected]> wrote:
> Hi Kelly,
>
>  Actually, I don't find it more expressive - which is probably why
>  we aren't agreeing. To me, it looks as if it ought to do something
>  more than just return, so I waste energy trying to figure it out.
>  Then I learn it's just a way for the test to succeed. I guess
>  expressiveness is a matter of opinion.

That's really interesting. Do you find Theory to be more expressive? I
thought that part of what made Theory more expressive was Assume. I
guess it might be a matter of what makes sense to you... for example I
don't find this code:

[Test]
public void x()
{
 Assert.Throws<ArgumentException>(new TestSnippet(MethodThatThrows) );
}

To be more expressive than:

[Test]
[ExpectedException(typeof(ArgumentException))]
{
  MethodThatThrows();
}

But I guess maybe that's just me. It may also be that I'm not yet used
to the delegate syntax, and I may grow to like it as I have with
Assert.That()...

Of course, there is also the possibility that you might grow to like
Assume.That, if you used it as much as I used Assert.That...

>  > I guess I'm pragmatic in favor of flexibility. If people can
>  > use tools in different ways than the author might have
>  > intended, in ways that are useful to them, why is that a bad thing?
>
>  That's what I said - that you have a different view. I didn't say
>  it was a bad thing, did I?

No, you didn't. :-)

>  > See my post to Gary a minute ago. In the Framework the Assert
>  > exception is handled, I want to handle the Assume exception
>  > in a similar way.
>
>  They are handled by NUnitTestCase, which is not part of the
>  core of NUnit - it's just another extension like you might write.

But to write that extension would mean that Assume would only work
within [KellyTests] not [Test]... and I'd really like it to work for
any other sort of test as well... Maybe that's asking too much of the
extensibility framework.

>  > I admit to feeling a slight tinge of frustration, but I'm
>  > trying to make my arguments on a technical basis... Ok,
>  > perhaps not just a technical basis, but rather on the basis
>  > of expressiveness. That's not exactly a technical argument either. :-)
>  >
>  > When you have Theory with a Theory Explorer, then Assume
>  > rises to a technical level.
>
>  I don't understand that.

With a Theory Explorer, you can't predict what the parameters might
be, therefore, you would have to have Assume. If you just used
if(condition) return; then you wouldn't have sure knowledge that the
Theory Explorer had generated cases that reached the code to be truly
explored, that is, the code after the Assume.That's... This could lead
to bad theories. For example, if I wrote this theory...

private bool IsEven(int number)
{
 return true; // wrong
}

[Theory]
public void AllEvenNumbersShouldDivideToFullNumbers(int evenNumber)
{
  if (!IsEven(evenNumber))
     return;
  Assert.That(evenNumber/2, Is.EqualTo( (int) ( (double) evenNumber)/2.0 ) );
}

You see that I messed up the implementation of IsEven, but I would
never know it because the Theory would always pass. However, if I
wrote it with Assume like so...

[Theory]
public void AllEvenNumbersShouldDivideToFullNumbers(int evenNumber)
{
  Assume.That (IsEven(evenNumber));
  Assert.That(evenNumber/2, Is.EqualTo( (int) ( (double) evenNumber)/2.0));
}

Then the framework would tell me that IsEven was implemented
incorrectly, because the test would never complete successfully as the
Assume would fire every time.

That seems like a technical argument, rather than an argument of expressiveness.

>  > Ok, I could not figure out how to do it in the current
>  > structure without changing the code in the nunit.framework,
>  > specifically in ProcessException.
>
>  ProcessException is in nunit.core, in TestMethod or TestCase -
>  I forget which at the moment. But it's not truly "core" - that
>  is it's not part of the stuff we extend. Rather, it is itself
>  an extension. When you write your own extension, with your own
>  test case, then you can handle any exception you like in any
>  way you like.

It's in TestMethod. Ok, then I just misunderstood the architecture. I
would just have to subclass TestCase, and write my own kind of
ProcessException...

>  In principle, this is no different from the exceptions that
>  signal a failure. There is no place in NUnit that recognizes
>  those exceptions for all tests. NUnitTestMethod recogizes the
>  particular exception that it knows about. CsUnitTestMethod -
>  to take one example - recogizes a completely different exception.

Ok, I think I "get it" now. I really would like for all kinds of
TestCase subclasses to be able to handle Assume, just like they all
can handle Assert (I suppose that they all just choose to handle
Assert at this point, if I'm understanding)... but that is probably
not going to happen.

>  > >  If you want to re-cast this discussion to "how can I do it"
>  > >  rather than "why doesn't NUnit do X?" I'd be glad to help.
>  >
>  > I'm super happy with that approach. How do I do what's now
>  > done in ProcessException in an Addin?
>
>  By creating a test case that contains the code to process that
>  kind of exception.

Ok.

>  > It differs only in expressiveness. You could say exactly the
>  > same for ExpectedException... because you can write a try
>  > catch block and do your own Assert.Fail after the catch.
>
>  OK, then the discussion turns on whether one finds it
>  expressive in the sense you are using it.

Right. Got it.

-Kelly

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone