Re: Tearing down when SetUp fails?

"Charlie Poole" <[email protected]> Fri, 12 Sep 2008 16:54:05 -0700
Newsgroups gmane.comp.windows.dotnet.nunit.devel
Message-ID <017501c91532$d843f450$6401a8c0@ferrari>
Hi Hans Christian,

I agree. Although we *could* partition SetUps into those
found in the top level, those found in the base, those
found in the base of the base, etc. I don't think I want
to. So either all or none of the TearDowns have to run
and none is pretty useless.

However, I think we can make a distinction between
SetUp, TestFixtureSetUp and higher level SetUp.

Charlie

> -----Original Message-----
> From: [email protected] 
> [mailto:[email protected]] On 
> Behalf Of Hans Christian Falkenberg
> Sent: Friday, September 12, 2008 2:22 PM
> To: [email protected]
> Subject: Re: [nunit-developer] Tearing down when SetUp fails?
> 
> (Let me just try again with batteries in the crazy keyboard)
> 
> Ah, I thought I had some place about support for multiple 
> [SetUp], but I couldn't remember if it was decided for or 
> against, so I read the 2.5 docs (which understandably aren't 
> up to date yet then) and concluded that there would only be a 
> single [SetUp].
> 
> With multiple ones, the conclusion is a given, I think.
> Consider this:
> 
> [SetUp] public void SetUp1() {
>    Acquire1();
> }
> [SetUp] public void SetUp2() {
>    Acquire2();
> }
> 
> [TearDown] public void TearDown1() {
>    Release1();
> }
> 
> [TearDown] public void TearDown2() {
>    Release2();
> }
> 
> Now, if SetUp1 succeeds and SetUp2 throws - what are you gonna do?
> Annotate which [TearDown] belongs to which [SetUp]?
> That's the sure road to overhead, strange constraints and confusion.
> 
> To me it looks like the only intuitive and easily 
> understandable approach is:
> 1. If any [SetUp] method throws, no further [SetUp] methods will be
>     called.
> 2. All [TearDown] methods will *always* be called.
>     (Just check for null values, people) 3. Correspondingly 
> [TestFixture*], obviously
> 
> But feel free to correct me with coming up with something simpler :)
> 
> + Hans Christian
> 
> 
> On Fri, 12 Sep 2008, Charlie Poole wrote:
> 
> > OK, I re-read your first mail and I now see you did make a 
> distinction 
> > betweeen running resharper and nunit-console.
> >
> > I want to do some research before I get back to you on the "how it 
> > should be" part. I have a vague sense that we may have changed the 
> > behavior from what the docs say as the result of a user 
> request and if 
> > so I'd like to get the reasons for that request into the discussion.
> >
> > One part I can explain: in the 2.4 docs I meant the phrase 
> "any setup 
> > method" to mean "either SetUp or TestFixtureSetUp."
> > It's still not working as described, but I should have 
> spelled it out 
> > for clarity.
> >
> > In 2.5, there can be multiple SetUp methods, and the logic of which 
> > TearDowns should and should not be run still has to be determined. 
> > Since there is not likely to be another 2.4 release, it's 
> 2.5 that is 
> > the key to this discussion.
> >
> > Charlie
> >
> > Charlie
> >
> >> -----Original Message-----
> >> From: Hans Christian Falkenberg [mailto:[email protected]]
> >> Sent: Friday, September 12, 2008 1:12 PM
> >> To: Charlie Poole
> >> Cc: [email protected]
> >> Subject: RE: [nunit-developer] Tearing down when SetUp fails?
> >>
> >> Err, well sorry about the name of the test - I originally 
> used it to 
> >> submit a bug report to ReSharper because I saw different behavior 
> >> wrt. whether the [TearDown] method was invoked when I used
> >> 1) nunit-console.exe (see my exact command in orig mail) and
> >> 2) Right click -> Run Unit Tests (with ReSharper in VS)
> >>
> >> So the answer is most likely that I used both :)
> >>
> >> After submitting that bug report I noticed that even NUnit does it 
> >> different between [TearDown] and [TestFixtureTearDown] so 
> I read the 
> >> documentation and then I wrote this mail.
> >>
> >> + Hans Christian
> >>
> >> PS! I also told the ReSharper guys (who replied just an 
> hour after my 
> >> bug report that they would look on the issue) that I started a 
> >> discussion on what the behavior should be in NUnit.
> >>
> >> On Fri, 12 Sep 2008, Charlie Poole wrote:
> >>
> >>> Hi Hans Christian,
> >>>
> >>> We should discuss this behavior and try to get it right
> >> (whatever we
> >>> decide that is) for 2.5.
> >>>
> >>> But before we get into it, because of the name of your test, I'm 
> >>> wondering if you actually ran under NUnit.
> >>> When you run under resharper, no matter what version of the NUnit 
> >>> framework your test references, you get the semantics that
> >> resharper
> >>> defines. That's because this particular behavior is not
> >> implemented in
> >>> nunit.framework, but in nunit.core, which is not used in this 
> >>> situation.
> >>>
> >>> I'll run my own tests as well, but I thought I should ask.
> >>>
> >>>
> >>> Charlie.
> >>>
> >>>> -----Original Message-----
> >>>> From: [email protected]
> >>>> [mailto:[email protected]] 
> On Behalf Of 
> >>>> Hans Christian Falkenberg
> >>>> Sent: Friday, September 12, 2008 5:33 AM
> >>>> To: [email protected]
> >>>> Subject: [nunit-developer] Tearing down when SetUp fails?
> >>>>
> >>>> Hi,
> >>>>
> >>>> I was about to post a bug about this - but then I read the 
> >>>> documentation and realized this might be something up for 
> >>>> discussion. Please let me know if it's there's a previous 
> >>>> conclusion on this and I'll just submit the bug report...
> >>>>
> >>>> Issues:
> >>>> 1. TearDown behavior is inconsistent between
> >>>>     [TearDown] and [TestFixtureTearDown] 2. The documentation 
> >>>> specifies that it should
> >>>>     do the Wrong Thing (imho) :p
> >>>>
> >>>> What I think should happen:
> >>>>    If there is an exception in any [SetUp] method, still run
> >>>>    all [TearDown] methods.
> >>>>    If there is an exception in any [TestFixtureSetUp] method,
> >>>>    still run all [TestFixtureTearDown] methods.
> >>>> (I realize only one of each method is allowed, but the doc
> >> says "any")
> >>>>
> >>>> What the documentation says (in both 2.4.8 and 2.5 alpha 3):
> >>>>    So long as any SetUp method runs without error, the TearDown 
> >>>> method is
> >>>>    guaranteed to run. It will not run if a SetUp method fails or 
> >>>> throws an
> >>>>    exception.
> >>>> and
> >>>>    So long as any TestFixtureSetUp method runs without error, the
> >>>>    TestFixtureTearDown method is guaranteed to run. It 
> will not run 
> >>>> if a
> >>>>    TestFixtureSetUp method fails or throws an exception.
> >>>>
> >>>> What actually happens (in both 2.4.8 and 2.5 alpha 3):
> >>>> Running attached code:
> >>>>    c:\>"c:\Program Files\NUnit 2.4.8\bin\nunit-console.exe"
> >>>>      /nologo bin\Debug\Dummy.dll
> >>>>    Fixture Setting up
> >>>>    .Setting up
> >>>>    Tearing down
> >>>>    FFixture Tearing down
> >>>>
> >>>>    Tests run: 1, Failures: 1, Not run: 0, Time: 0.030 seconds 
> >>>> Uncommenting FixtureSetUp exception:
> >>>>    c:\>"c:\Program Files\NUnit 2.4.8\bin\nunit-console.exe"
> >>>>     /nologo bin\Debug\Dummy.dll
> >>>>    Fixture Setting up
> >>>>    .F
> >>>>    Tests run: 1, Failures: 1, Not run: 0, Time: 0.028 seconds
> >>>>
> >>>>
> >>>> So [TearDown] doesn't behave as specified when a [SetUp] method 
> >>>> throws an exception, that's a bug report, right?
> >>>>
> >>>> Except I think it *should* behave that way, so I was going to 
> >>>> submit a bug report on [TestFixtureTearDown] :)
> >>>>
> >>>> Here's my reasoning:
> >>>> Say you are acquiring two resources in the SetUp method:
> >>>> [SetUp] public void SetUp() {
> >>>>    r1 = Resources.Acquire1();
> >>>>    r2 = Resources.Acquire2();
> >>>> }
> >>>>
> >>>> And of course the must be released:
> >>>> [TearDown] public void TearDown() {
> >>>>    Resources.Release(r1);
> >>>>    r1 = null;
> >>>>    Resources.Release(r2);
> >>>>    r2 = null;
> >>>> }
> >>>>
> >>>> Now, since Resource.Release will just return if its argument is 
> >>>> null and never throws, everything is fine. Except if the 
> >>>> documentation is to believed: If an exception can occur while 
> >>>> acquiring r2 (and it can), we'll have to write this:
> >>>>
> >>>> [SetUp] public void SetUp() {
> >>>>    r1 = Resources.Acquire1();
> >>>>    try {
> >>>>      r2 = Resources.Acquire2();
> >>>>    } catch {
> >>>>      Resources.Release(r1);
> >>>>      throw;
> >>>>    }
> >>>> }
> >>>>
> >>>> Which I think is bad, but I guess not *that* bad... 
> until you have 
> >>>> 4-5 resources. Then there's suddenly a crazy amount of TearDown 
> >>>> code duplication in SetUp. So here is how I decided to 
> work around 
> >>>> this problem:
> >>>>
> >>>> [SetUp] public void SetUp() {
> >>>>    setUpCalled = true;
> >>>>    r1 = Resources.Acquire1();
> >>>>    r2 = Resources.Acquire2();
> >>>> }
> >>>>
> >>>> [TearDown] public void TearDown() {
> >>>>    if (!setUpCalled) return;
> >>>>    setUpCalled = false;
> >>>>    Resources.Release(r1);
> >>>>    r1 = null;
> >>>>    Resources.Release(r2);
> >>>>    r2 = null;
> >>>> }
> >>>>
> >>>> Not the worst of solution's, but now I'm basically doing NUnit's 
> >>>> work myself. And when the methods in TearDown *can* throw 
> >>>> Exceptions they will now be reported as if they were thrown in 
> >>>> SetUp, which is just to ask for someone being confused later.
> >>>> But at least the code will release resources properly in 
> both NUnit 
> >>>> 2.4.8 (and 2.5 alpha 3), ReSharper 4.1.933.3 (which behaves like 
> >>>> the NUnit doc says it should) and future NUnit versions 
> which might 
> >>>> adhere to the documentation.
> >>>>
> >>>> So... could we instead please change the NUnit behavior so that 
> >>>> other people don't have to write workarounds like this?
> >>>>
> >>>> I know junit doesn't run TearDown (or didn't when I last 
> used it a 
> >>>> year back) when SetUp throws, but junit didn't report test 
> >>>> exceptions when TearDown throwed either, so not much 
> cause to let 
> >>>> them set the standard here...
> >>>>
> >>>> A better argument against might be that people didn't 
> write code to 
> >>>> check for null in their [TearDown] and [TestFixtureTearDown] 
> >>>> methods. But then their [TearDown] methods are already 
> failing, and 
> >>>> they'll just have to fix their [TestFixtureTearDown] 
> methods when 
> >>>> upgrading to 2.5,
> >> won't they?
> >>>>
> >>>> + Hans Christian
> >>>>
> >>>>
> >>>>
> >>>> PS: If you are wondering wth. I'm thinking wrt. acquiring 4-5 
> >>>> resources before a unit tests... Well, the resources are files 
> >>>> (with Acquire==Create and Release==Delete) and it would 
> hardly be 
> >>>> proper to use mocked files for unit testing when testing 
> writing to 
> >>>> the OS - that would kind of void the entire testing.
> >>>>
> >>>> PPS: Why should a unit test need files? Well - it does.
> >>>>
> >>>
> >>>
> >>>
> >>
> >
> >
> >
> 
> --------------------------------------------------------------
> -----------
> This SF.Net email is sponsored by the Moblin Your Move 
> Developer's challenge Build the coolest Linux based 
> applications with Moblin SDK & win great prizes Grand prize 
> is a trip for two to an Open Source event anywhere in the 
> world http://moblin-contest.org/redirect.php?banner_id=100&url=/
> _______________________________________________
> nunit-developer mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/nunit-developer
> 



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/