On my original test setup with .NET Framework 4.7.2 and RavenDB 6, it took about 9 minutes to execute my 760 tests.
After upgrading to .NET 10, that by itself reduced the total time to 6-7 minutes.
I spent a couple days looking at how I was executing my tests and using the RavenDB Embedded server and found some ways to improve that even further.
As of right now, that is down to 2.4 minutes. (a 4X reduction).
- Reqnroll
- NUnit 3
- RavenDB 6.2 (Embedded)
- .NET 10
- 6-core CPU
- 64GB RAM
- Ensure
DocumentStoreis scoped and lifecycle is tied to each test (scenario) - Create a global
DocumentStoreto handle server-wide operations (disposed at end of test run) - Create a new database per test
- When the test ends, delete it (fire-and-forget) otherwise disk usage balloons
- Lazily initialize the
DocumentStoreso tests that don't need it, don't instantiate it - Clean/delete any existing
RavenDBdirectory in case there are files leftover - Leverage Reqnroll + NUnit parallelization
- Run in memory
- Disable topology updates/cache (single node)
- Use Developer license (uses all available cores)
While my test harness is using Reqnroll and NUnit, you can apply these patterns to other test frameworks.
DbTestHarness-- Singleton, created by ReqnrollDbContext-- Scoped (scenario/test), injected by Reqnroll through Microsoft.DependencyInjectionTestingContext-- Scoped, but staticCreateServicesis invoked once for the test run
Test Hooks
[BeforeTestRun]-- happens before all tests run[BeforeScenario]-- happens before a standalone test runs[AfterScenario]-- happens after the test executes[AfterTestRun]-- happens at the end
Dependencies/services can be added using Reqnroll.Microsoft.Extensions.DependencyInjection and the [ScenarioDependencies] attribute.
Things I tried that didn't seem to make a difference:
- Use explicit
Listof indexes andExecuteIndexes(no discernible difference) - Create a
Snapshotbackup on first test and restore for each subsequent test without re-initializing docstore (test run took >20 min!) - Don't delete databases (eats up disk quickly)
- Delete batches of databases at a time (<10s difference)
Definitely the biggest win was parallelization, which cut the 6.4 mins into 2.4 mins on my machine (6-core, 64GB RAM).