Re: Roadmap Updated

"Kelly Anderson" <[email protected]>
Newsgroups gmane.comp.windows.dotnet.nunit.devel
Message-ID <[email protected]>
On Mon, Mar 10, 2008 at 6:06 PM, Charlie Poole
<[email protected]> wrote:
> Hi Kelly,
>  > The current approach seems to be that the test cases are
>  > created at Load... time, and then are subsequently Run when
>  > you select a test case to run.
>
>  Yes.. and in most cases, user code in the test assembly
>  does not participate in loading tests. The only exception
>  I can think of is the Suite property, which is required
>  to be static.

When we're talking about RowTest, IterativeTest or Theory type
approaches, this doesn't hold, and user code can and does get
involved.

>  > One issue I'm having in using
>  > IterativeTest is that the Load time can get unreasonably long
>  > even in the case where I only want to run a single test. (It
>  > also seems to occasionally gratuitously reload the tests, but
>  > that's a side issue.) This seems to be the case whether I'm
>  > using TestDriven.NET or the NUnit GUI, so I assume that this
>  > must be a core issue, or at least both have chosen the same
>  > implementation.
>
>  If tests are reloading without being told to reload, then I
>  would suspect your extension as being the culprit. :-)

Possibly. I'll look into that. Since I started with RowTest, I can't
claim to have a 100% understanding of everything that's going on right
yet.

>  However, there are many ways to "tell" the test to reload,
>  so check your NUnit options and turn off all automatic
>  reloading while testing this.

Ok, I'll look at that too.

>  > If, on the other hand, one could be lazy about test creation,
>  > and only create the test when it's about to be run, that
>  > would make for a more efficient system. (At least the way I'm
>  > using it.) This might also be the case in general, it's just
>  > more obvious for IterativeTest.
>
>  NUnit creates all "tests" at load time, but those tests are not
>  instances of the user test fixture class. An NUnitTestMethod
>  is fairly lightweight, but it does require a bit of reflection
>  in order to get all the properties of the test to match the
>  attributes you specify. Since the attributes on the method
>  don't change for each test case, you should check to see if
>  your implementation is repeating that reflection every time.
>  It's only needed once, but depending on your inheritance
>  hierarchy it could be happening more for each case.

I must be doing more in the BuildFrom than you are expecting I would
do. In reading this email, and pondering the issue, it strikes me that
I could make my tests do lazy evaluation themselves. So perhaps that's
the better solution, rather than having NUnit do something different.
I don't think it's the IterativeTest Addin, per se, but just the way
I'm using it that's inefficient.

>  > So, is there some way of being indeterminate until you either
>  > try to expand the test in the NUnit GUI, or actually run the
>  > test? Can we do lazy evaluation of the set of tests?
>
>  I'll deal with each option separately:
>
>  The Gui is completely decoupled from the test loader, which
>  is as it should be. The gui doesn't even have tests, just
>  the names of tests and other info about them. Of course,
>  we could have the gui drive the progressive loading of tests,
>  but that would not be a very clean architecture.

I can see where it could get kind of coupled...

>  There is a possibility of having a test that dynamically
>  creates its own children when it is run. That would mean
>  the gui would be receiving notifications about tests that
>  it doesn't know about and would have to figure out where
>  to put them in the tree. I think we may need this at some
>  point, but it's much more complicated than the alternative
>  of using multiple result sets. I'd like to try the simpler
>  alternative first.

Also complicated.

>  Here's what I mean by multiple result sets... Let's say
>  I have a method that tests multiplication. I want to
>  run it with 2x2=4 0x7=0 90x1=90 as cases.

Which could come from some kind of autogenerator, in the Theory case.

>  I can consider this as three tests, listed in the gui
>  tree as Multiply(2,2), Multiply(0,7) and Multiply(90,1).
>  That's how RowTest would do it, for example.

Sure, that's one approach.

>  On the other hand, we can think about this as a single
>  TestMethod producing multiple results. The test tree
>  would list a single Multiply test. After execution,
>  the results would be placed in the tree under the test.
>  They would look pretty much like the tests in the first
>  approach - it's just a matter of how we think about it.

That sounds cleaner.

>  One advantage of this is that a TestResult is a
>  very lightweight, serializable object. It has no
>  existence in the tree of tests created by the loader,
>  which is BTW different from the tree in the Gui, so
>  it doesn't have to be known in advance.
>
>  So that's an approach I plan to follow up on.

I think that's a good plan. There remains what to do in the GUI tree
before the test has run... do you add the + only after the tests have
run? How to differentiate those sorts of tests from those who never
have children? Just details, of course.

>  > It seems that you could get the name of the test from the
>  > metadata without actually creating the test from calling
>  > BuildFrom. Would that constitute an improvement in your
>  > opinion to the current approach?
>  > This question is independent of 2.5 vs 3.0... although the
>  > answer might not be.
>
>  If we are ready to call BuildFrom, what would we do instead
>  in order to defer it? First, we would have to know that
>  this is the type of test that needs to be deferred, but
>  we wouldn't know that until we built it.
>
>  Of course, the builder extension could simply save the
>  data and only build the subtests at the time it needed them,
>  but this has a few problems:
>
>  1) By that time, we have already done most of the work,
>  unless we are talking about very large sets of data.

I was... In my IEnumerator, I was loading the XML files I was testing.
Now, I think I'll restructure it so that it only makes the list of
files, and loads them later, as necessary. My bad.

>  2) A testcase is not a very big object anyway, so it
>  isn't clear we would make a net savings by caching
>  the info needed to create one and building it later.

Only if your ListBuilder is implemented inefficiently, as mine is.

>  > The best answer would seem to me to be that you could have
>  > all the test names show up, and those that are Expandable (a
>  > bool property?) would show potential expansion. Then when you
>  > choose to expand it, A function is called that enumerates the
>  > tests, finally, when you choose to execute a test, then
>  > another function is called to prepare to run the test,
>  > finally the test is run. If we could do lazy evaluation for
>  > each of these steps, that would seem to be a huge improvement
>  > over the current approach, at least in the cases I'm dealing with.
>  >
>  > I'm a big fan of lazy evaluation.
>
>  Except that the entire NUnit approach to loading tests is already
>  based on lazy evaluation. NUnit only creates lightweight objects
>  that contain enough info to create your test fixture object and
>  invoke the tests when needed. I'm suspicious that you may be
>  doing something to defeat this in your extension - I'll try
>  to find time to look over the code.

I don't think that's necessary... I think I know my problem, and it's
not in the IteratorTest code.

>  > Yes, that's what I mean. Internally this requires two
>  > different approaches, of course.
>
>  And to repeat the point Andreas was making, we would like
>  each extension that uses data to be able to use any data
>  providers interchangeably. Just as Theory does.

Yup.

>  > I'm not especially dense, but I am unfamiliar with most of
>  > the NUnit internals. I feel most comfortable and useful at
>  > this point looking at things from the user's point of view.
>  > By user, I mean both a general user as well as someone
>  > writing extensions. I am not against getting my hands dirty
>  > as might be helpful. I just recognize that there is ramp up
>  > time involved to get to that point.
>
>  Bear in mind, for better or worse, NUnit extensibility has
>  never been targeted at the general user.  In fact, that is
>  a valid criticism some people have made. So, you do need
>  to get into certain internals - SimpleTestRunner and everything
>  it calls - to work effectively. But it's just code. :-)

I'm hoping that this is something we want to change in the 3.0 time
frame. I think extensibility should be targeted at the general user.

It is just code, and all it takes to understand it is just time. :-)

-Kelly

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.