2

I have some tests that do some write-operation on a database. I know that´s not really unit-testing, but let´s leave that asside.

In order to enable every test to work on a clean workspace, I rollback all transactions doe so far. However I randomly get concurrency-errors due to database-locks that cannot be established.

This is my code:

Test1.dll

[TestFixture]
class MyTest1
{
    [OneTimeSetup]
    public void SetupFixture()
    {
        myworkspace.StartEditing(); // this will establish a lock on the underlying database
    }
    [OneTimeTearDow]
    public void TearDownFixture()
    {
        myWorkspace.Rollback();
    }
}

The same code also exists within another test-assembly, let's name it Test2.dll. Now when I use the nunit-console-runner using nunit3-console Test1.dll Test2.dll, I get the following error:

System.Runtime.InteropServices.COMException : Table 'GDB_DatabaseLocks' cannot be locked; it is currently used by user 'ADMIN' (this is me) on host 'MyHost' at ESRI.ArcGIS.Geodatabase.IWorkspaceEdit.StartEditing(Boolean withUndoRedo)

myWorkspace is a COM-object (Arcobjects-interface IWorkspace) that relates to an MS-Access-Database. I assume this is because nunit creates multiple threads that enter the above code at the same time. So I added the NonParalizable-attribute to both assemblies without success. I also tried to add Apartment(ApartmentState.STA) to my assembly in order to execute everything in a single thread, which resulted in the console never finishing.

What drives me nuts is that running my tests using ReSahrpers test-runner works perfectly. However I have no clue how ReSharper starts nunit. It seems ReSharper does not use nunit-console, but the nunit-API instead.

Is there another way to force all my tests to run in a single thread? I use nunit3.10 and ArcGIS 10.8.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • Knowing your answers from here, i'm not sure if it helps you. [As shown here](https://stackoverflow.com/questions/2434067/how-to-run-unit-tests-in-stathread-mode) you'll need to add `ApartmentState.STA` to assembly, class *and* method level. Did you tried that? Not entirely clear to me from your question. – nilsK Sep 29 '20 at 11:15
  • @nilsK Woaw, that´s a great deal, as there are hundresds of tests. I´ll try that out, though. – MakePeaceGreatAgain Sep 29 '20 at 11:20

1 Answers1

1

By default, the NUnit Console will run multiple test assemblies in parallel. Add --agents=1 to force the two assemblies to run sequentially, under a single agent.


Just to clarify some of the other things you tried as well...

[NonParallelizable] is used to prevent the parallelization of different tests within a single assembly. By default, tests within an assembly do not run in parallel, so adding this attribute when you haven't specifically added [Parallelizable] at a higher level will have no effect.

[Apartments(Apartment.STA)] can be added as an assembly-level attribute, and does not have to be added per test, as mentioned in the comments. Check out the docs here: https://docs.nunit.org/articles/nunit/writing-tests/attributes/apartment.html

Chris
  • 5,882
  • 2
  • 32
  • 57
  • That´s cool as I don´t need any attributes and thus can leave my test-code as is. Just a last question: what if I´d like to run all **reading** tests in parallel and only the **writing** tests sequentially? Shouldn´t that be possible with a single agent also? So I´d just add `[Parallelizable]` to the tests that do only **read**-operations on my DB and it´s fine (or alternativyl make the assembly parallelizable and the writing tests not)? – MakePeaceGreatAgain Sep 30 '20 at 06:19
  • That's one option, yes! The most efficient way to do this depends really on how your read/write tests are separated out. Probably worth a quick read of the docs here to see the different options here. =) --> https://docs.nunit.org/articles/nunit/writing-tests/attributes/parallelizable.html – Chris Sep 30 '20 at 19:52