Re: Tearing down when SetUp fails?

"Kelly Anderson" <[email protected]> Mon, 15 Sep 2008 09:37:01 -0600
Newsgroups gmane.comp.windows.dotnet.nunit.devel
Message-ID <[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=/