Unit Tests - ArcObjects

3248
9
07-22-2012 08:01 PM
tonydavid
New Contributor III
Has anyone worked with NUnit (or others) unit testing arcobject applications?? Any idea where to start??

I've looked briefly at NUnit but wondering how to:
1. pass features / feature classes (ArcObjects COM objects etc) in testing
2. simulate ArcMap UI steps (i.e. custom tool operations from custom toolbars) performing specific user steps during test cycle
3. large application regression tests


Any advise or push in the right direction much appreciated.
0 Kudos
9 Replies
tonydavid
New Contributor III
add-on ...

worked with VBUnit before few years back but it didn't go far. couldn't test custom UI tools steps in arcmap and VBUnit worked in VB6.

basic scenario - click on custom button >> do some geometry operation >> update forms that pop up or runs methods behind >> results save back in database

heard TestComplete is better at this now ... anyone using it??

Thanks.
0 Kudos
AlexanderGray
Occasional Contributor III
I have used NUnit with ArcObjects 9.2.  Now I use visual studio built in unit tests (same idea.)  Mocking up all the AOs you would need to do full tests is probably not realistic.  I don't use unit tests for everything.   For some things you can have a setup step to your tests that makes a copy of a database with test data, use AO in your test (init licenses and product first like an exe,) to open the featureclasses and pass them to your test.  Use AO again to open the results and examine the contents.  That works well for converters and such.  Classes that require a feature or a geometry passed in, you can create it in your unit test. You can also create in memory workspace populate the values you need, etc.  Again, it is not practical for everything.  Simulating editor, document or application events is not practical (IMHO.)  UI code is a unique challenge if you can write the code is MVP style, that helps.  This is when segregating the business code tier for the UI code pays off, you can test the business code in unit test and the ui code in manual tests.
0 Kudos
RichardWatson
Frequent Contributor
We have different kinds of tests. 

In our unit tests we avoid calling an AO code using IOC and/or mocks.  The goal of these tests is to test our business logic and not AO.

In our integration tests we do call AO.  These are also automated but complexity rises when you do this.  Examples include having to configure the tests to run in STA instead of MTA, having a consistent database state, ability to have multiple users running the tests simultaneously, avoiding anything that has UI, etc.  We use and love R# but it doesn't seem to honor the Visual Studio test settings.  I mention this simply because it is a trivial example of added complexity due to AO.

Finally, we have acceptance tests where the GUI is actually used.  We tried on and off to automate these but doing so has never been productive for us.

Dave Bouwman gave a really nice presentation at the ESRI Developer Summit ~3 years ago on unit testing.  It has good background material.
0 Kudos
tonydavid
New Contributor III
Thanks guys.

Alexander. I suppose thinking with TDD helps ... but what about legacy codes??

Richard, what are the unit test tools you use??
0 Kudos
RichardWatson
Frequent Contributor
We use the tools built into Visual Studio.  In general, we try to use Microsoft tools because using them typically creates the least friction.

IMHO, writing tests forces to make the design of the software testable which itself results in better software.
0 Kudos
AlexanderGray
Occasional Contributor III
If you don't write the software with testing in mind, it is unlikely that you will be able to slap something together after the fact.
0 Kudos
LukeBadgerow
New Contributor
just a question, or a suggestion,  but the majority of the stackexchange sites strongly encourage the inclusion of code snippets.  As I'm newer to unit testing, and am still efforting to refactor an application to become more testable (ultimately, I want it to get to a TDD state) examples of how some of you have successfully used MSTest (Visual Studio's built in framework) and/or any mocking framework would be great.

where I'm at currently with inclusion of mocking to my tests (again, just a snippet):

 [TestMethod()]
        public void GenerateNewPlotDocument_ProperlySetsQuadid () {
            PlotDocumentGeneratorClass plotter = new PlotDocumentGeneratorClass();
            plotter.GenerateNewPlotDocument("449a");
            Assert.AreEqual("449a", plotter.quadid);
        }
        [TestMethod()]
        public void CheckLayoutView_ReturnsIFeatureWorkspaceType () {
            MockRepository mockrepo = new MockRepository();

            IPlotDocument plotter = mockrepo.DynamicMock<PlotDocumentGeneratorClass>();
            IFeatureWorkspace transworkspace = plotter.SetCurrentWorkspace();
            Assert.IsInstanceOfType(transworkspace, typeof(ESRI.ArcGIS.Geodatabase.IFeatureWorkspace));
        }
        [TestMethod()]
        public void GetEditor_MockingTest () {
            MockRepository mockrepo = new MockRepository();
            PlotDocumentGeneratorClass plotter = new PlotDocumentGeneratorClass();
            UID test = mockrepo.StrictMock<UID>();
            Assert.IsNotNull(test);

        }
0 Kudos
RichardWatson
Frequent Contributor
Nirvana would be to have a continuous integration process via which you are able to build and completely test your software.

I think of testing as unit, integration, and acceptance. 

In unit testing you stub/fake/mock ArcObjects because the goal is to test just your code.  People are doing this extensively.

In integration testing you call the ArcObjects code against a database in a known state.  This starts to get much harder and presents significant challenges.  We do this for a much smaller set of code (business logic), i.e. we have low code coverage.

In acceptance testing you bring the UI into the mix.  These can also be automated but doing so is very difficult and tends to result in brittle tests.  We put a lot of effort into trying to do this but, in hindsight, it was not productive.
0 Kudos
DavidHollema
New Contributor III
Open Local.testsettings in a text editor and ensure you're using MTA apartmentState.

<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Local" id="217d9f83-a42a-48a9-aa24-3860a5b13575" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
  <Description>These are default test settings for a local test run.</Description>
  <Deployment enabled="false" />
  <Execution>
    <TestTypeSpecific />
    <AgentRule name="Execution Agents">
    </AgentRule>
 <ExecutionThread apartmentState="MTA" />
  </Execution>
</TestSettings>


Make sure you exit VS after making changes, before running your test suite again.

License initialization at test assembly level...

    
    [TestClass()]
    public class TestRunInitialize
    {
        [AssemblyInitialize()]
        public static void Initialize(TestContext testContext)
        {
                 InitializeLicense();
        }

        private static LicenseInitializer m_AOLicenseInitializer = new LicenseInitializer();

        private static void InitializeLicense()
        {
            m_AOLicenseInitializer.InitializeApplication(new esriLicenseProductCode[] { 
                esriLicenseProductCode.esriLicenseProductCodeArcServer, 
                esriLicenseProductCode.esriLicenseProductCodeStandard, 
                esriLicenseProductCode.esriLicenseProductCodeAdvanced},
            new esriLicenseExtensionCode[] { });
        }
    }
0 Kudos