Hi Boris,
I had to think about this for a bit, since it's actually a fairly
complex question. Anyway, here are my thoughts...
It's fairly trivial to cause test cases to be launched in parallel.
The class CompositeWorkItem has code for running the child tests in
any suite - i.e. fixture, setup fixture or assembly. If the child test
is below the fixture level, it executes it on the same thread where
the fixture setup was just run. Otherwise, it dispatches the test for
parallel execution. So, to run test cases in parallel, eliminate the
check and just dispatch everything.
However, this simple solution won't work except in specially contrived
cases that avoid all the pitfalls. In particular, if any of the test
cases (or the setup method) changes the state of the test class, the
tests will interfere with each other. Furthermore, if the test fixture
setup or any higher level setup is written to assume that all tests
run on the same thread, then tests run on a separate thread may break.
That's what led me to limit parallelism to the fixtures. The original
code for CompositeWorkItem ran the subordinate tests in parallel and
broke my own NUnit tests. I hypothesized that most fixtures - as
opposed to test cases - could probably run safely in parallel and this
turned out to be true, at least for my tests.
So, a more practical list of what's needed to run test cases in
parallel would include:
1. Implementing some ways to limit how much parallelism we have and
where. For example, we need to be able to designate tests that can't
be run in parallel with any other test, tests that can't run in
parallel with one another because they use a common resource, fixtures
whose test cases can or cannot be run in parallel, etc.
2. Allowing the user to designate a "level" at which parallelism takes
place. For example, this might be at the assembly level using parallel
processes, at the fixture level or a the test case level as you are
suggesting.
3. Not absolutely necessary, but I think desirable: allowing work
items to depend upon one another and splitting fixture and higher
level setup and teardown into two separate work items. All tests would
depend on the setup and the teardown would depend on all tests. Doing
this would allow us to schedule all subtests at one time rather than
waiting until each fixture setup completes.
4. Also desirable: having a setting or attribute that causes each test
case to run on a separate instance of the class. This would pretty
much eliminate the difficulty with tests that change the state of the
class and would provide much better separation of the tests.
5. Finally, implementing the dispatch mechanism as described at the
start of this note.
Maybe others, reading this, can come up with further necessary or
desirable steps.
Charlie