Re: Tearing down when SetUp fails?
"Olof Bjarnason" <[email protected]> Tue, 16 Sep 2008 21:45:00 +0200
| Newsgroups | gmane.comp.windows.dotnet.nunit.devel |
|---|---|
| Message-ID | <[email protected]> |
Start simple, extent if needed ... So one Setup, one TearDown is my vote 2008/9/15 Kelly Anderson <[email protected]>: > Multiple Setups seems like a bad idea to me. If you need multiple > setups, why not have multiple TestFixture classes? > > What order would they run in? How do you associate a particular SetUp > with a particular TearDown... this sounds like opening up a can of > worms with no real payback. > > Is this really being considered seriously? > > -Kelly > > On Fri, Sep 12, 2008 at 3:22 PM, Hans Christian Falkenberg > <[email protected]> wrote: >> (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=/ > _______________________________________________ > 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=/