Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Opposite of Isolated
james
#1 Posted : Sunday, June 22, 2014 8:59:57 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 3/13/2013(UTC)
Posts: 30
Location: United Kingdom

Thanks: 7 times
Was thanked: 9 time(s) in 9 post(s)
Hi

I'm looking for a way to force certain tests to run in the same process.

There is some expensive setup (around 3-4seconds) that only needs to happen once. But since the tests are running in separate processes it's happening multiple times, causing the suite to take a minute or so to run when it could be reduced to a few seconds (it takes about 6 seconds in Resharper). And as the suite grows it's only going to get worse.


The IsolatedAttribute allows me to specify that a test should run in its own process. Is there a way to specify that 2 tests should run in the same process? something like:

Code:

[SharedContext("Name")]
public class TestSuite { ...


Then, when 2 tests are scheduled that have the same SharedContext, they will share the same process.

Thanks in advance

James
Remco
#2 Posted : Sunday, June 22, 2014 10:31:25 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi James,

I'm afraid I don't know of any way that NCrunch can reliably do this at the moment. But it does make good sense for a feature idea if you'd like to suggest it.

Usually there are ways you can design the test code to make it work better in this kind of scenario. If you have setup code that only needs to run once for every process (for example, creating a test database), you can have this code test against a static member to see whether it has been previously invoked for the process. Where the setup code involves external resources that need to be cleaned up at the end of the test run, you can move the cleanup code into the start of the subsequent test run, where it can check for derelict resources that have been left behind from the previous run and then clean them up. This would also improve your test code's handling of certain failure scenarios, such as the test process being unexpectedly terminated before the cleanup could run.

Solving this problem by adjusting the design of the test would give you a much better result than a SharedContext attribute, as NCrunch would then have more freedom in how it runs your tests. The SharedContext would introduce some significant restrictions on test execution that would render many of NCrunch's features (smart execution order, parallel execution, etc) invalid.


Cheers,

Remco
james
#3 Posted : Monday, June 23, 2014 8:48:31 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 3/13/2013(UTC)
Posts: 30
Location: United Kingdom

Thanks: 7 times
Was thanked: 9 time(s) in 9 post(s)
I'm using a static member and initializing it only once. It's all in memory so once the process dies it is cleaned up, it doesn't access any external resources. In the cases where 2 tests do happen to run in the same process, the second one runs quickly (sub 50ms).

In this instance I'm happy to forego the clever scheduling NCrunch does as the overhead if the setup code more than outweighs the benefits gained from parallel execution. It's painful waiting for NCrunch when I know Resharper runs my tests reasonably quickly.

I'll raise the feature request.
james
#4 Posted : Monday, June 23, 2014 8:58:00 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 3/13/2013(UTC)
Posts: 30
Location: United Kingdom

Thanks: 7 times
Was thanked: 9 time(s) in 9 post(s)
1 user thanked james for this useful post.
Remco on 6/23/2014(UTC)
Remco
#5 Posted : Monday, June 23, 2014 9:08:30 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
I find this interesting and I am wondering if I am misunderstanding the way your test is operating.

NCrunch will re-use test processes between test runs, so in theory, if you are using a static member to control the setup, then the same setup can apply for multiple test runs provided they still work within the same process.

If your code is operating as you've described, then there are only two things that could cause the setup code to rerun:

1. If you have NCrunch configured in such a way that it will launch a new test process for each execution task. This won't happen by default, and the only way I know that this will happen is if you set the 'Test process memory limit' to a very low level that isn't zero.

2. If there is no suitable process available for reuse, NCrunch will spawn a new one. This happens quite regularly, for example, if you are using parallel execution and the only pre-launched process is already working on executing a different test task. Different test projects also need to execute inside different test processes as NCrunch cannot re-use a process launched for a different test assembly.

You can probably test the reuse of test processes quite easily by performing a few manual test runs. When you run tests manually, try choosing the 'Run test using existing task runner process' option inside the 'Advanced' context submenu. If there is a process already launched by NCrunch, it will be reused and you should see a sharp reduction in the setup time. Note that if you have the engine set to terminate task runners when execution is completed, then this option won't be available.
james
#6 Posted : Monday, June 23, 2014 12:06:34 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 3/13/2013(UTC)
Posts: 30
Location: United Kingdom

Thanks: 7 times
Was thanked: 9 time(s) in 9 post(s)
So, assuming there's an NCrunch test runner, 'Run selected tests using existing task runner process' only runs the setup once and I get times comparable to a standalone test runner.

Parallel execution *is* enabled. I want to enable parallel execution of my other test assemblies. It's only this one I'm having issues with. Can I set something in the .ncrunchproject file?

Thanks again for your help on this
GreenMoose
#7 Posted : Monday, June 23, 2014 2:06:00 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 6/17/2012(UTC)
Posts: 507

Thanks: 145 times
Was thanked: 66 time(s) in 64 post(s)
Remco wrote:
Different test projects also need to execute inside different test processes as NCrunch cannot re-use a process launched for a different test assembly.

This was quite interesting, I also suffer from the fact that task runner start and stop all the time throughout the testing phase. In many tests we have "initialization routines" which initializes static member(s) and takes over 10s to complete. Since task runners are stopping quite a lot throughout the test run we waste a lot of time on these initialization routines.

We have currently ~15 test projects and according to your statement above I guess that is one of the reason task runners are starting/stopping so often. So:
1) Does NCRunch have any logic for completing tests within a project within same task runner, before starting processing another project? If not, maybe having this will improve overall execution time for cases like this?
2) Can I somehow optimize this, e.g. having a large number of "pooled test runner processes" (e.g. a bit higher than no of test projects) but not as many "max number of processing threads" so NCrunch always should be able to find a suitable test runner process to reuse?

Thanks.
Remco
#8 Posted : Monday, June 23, 2014 11:42:45 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi James,

Assuming you have parallel execution enabled at solution config level, and your max number of processing threads is set higher than 1 (or you have other capacity via distributed processing), NCrunch will run ALL tests in parallel unless they've been specifically configured not to. This means that you shouldn't normally need to change any other settings, but note that there are other things that the engine takes into account when deciding whether or not to kick off a test task.

If you have a max processing threads of 2-3 and you have a 'Fast lane thread' enabled, you may find that the engine is avoiding executing your longer running tests in parallel because they take too long to fit into the fast lane. This means the engine doesn't have enough capacity to pick them up, and they scroll through one at a time. If this is the case for your situation, I recommend playing around with the fast lane settings to see if you can create a better result. You may also take some benefit from increasing the max number of processing threads if you still have some spare CPU.

Other than limiting engine capacity or turning off parallel execution at solution level, the only way to prevent parallel execution is through the use of the ExclusivelyUsesAttribute or SerialAttribute. Both of these need to be declared at class/test level in your code, so you'll probably know about them if they're there.
Remco
#9 Posted : Monday, June 23, 2014 11:55:24 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi GreenMoose,

Yes - I can see the initialisation routines being a bottleneck in your case. Fortunately, there is something you can do to help with this.

NCrunch will execute tests according to their priority sequence, unless there are constraints in place (i.e. exclusively used resources, local machine capabilities, fast lane threads, etc). It doesn't consider the test project to be a factor in this sequence, so it will switch between task runners quite often depending upon what's in the queue.

In this situation, you really want to set the 'Process pool size' global configuration setting as high as you can. By default, this is set to just 1 process, which won't be enough if you have the processing queue switching back and forth between 15 test projects. The only real downside of having a large process pool is that the overall memory consumption of NCrunch is higher. NCrunch will implicitly add the number of processing threads onto the process pool size setting in order to calculate the true process pool size, so setting a lower number of processing threads will probably not help you here, unless you want to decrease memory consumption.
GreenMoose
#10 Posted : Tuesday, June 24, 2014 10:23:55 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 6/17/2012(UTC)
Posts: 507

Thanks: 145 times
Was thanked: 66 time(s) in 64 post(s)
Remco;6082 wrote:
In this situation, you really want to set the 'Process pool size' global configuration setting as high as you can.

Do you mean setting "Max number of test runner processes to pool" ? (I could not find any other with v2.7.0.5)

(I did try setting this to 20 and it "seems" it is not terminating/starting as many processes, still starting/stopping quite a few though).

Thanks.
Remco
#11 Posted : Tuesday, June 24, 2014 11:54:54 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Yes - sorry. I think the name of that config setting changed at some stage or another.

20 should be enough. One way you can test to see whether the setting is optimal is by doing the following:

1. Turn on the Terminate test runners on complete setting
2. Set the engine mode to manual execution
3. Reset the engine, make sure all projects are built and the processing queue is clear
4. Queue all tests for execution with the 'Run all tests' button
5. Open task manager, watch the list of processes available

... In theory, you shouldn't see any processes terminate.
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

YAF | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0.068 seconds.
Trial NCrunch
Take NCrunch for a spin
Do your fingers a favour and supercharge your testing workflow
Free Download