Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...


Fig. 18 Wrapper and test classes for the Simple river model


There is a one-to-one relation between the wrapper classes and the test classes, with two exceptions. There is no test class for the SimpleRiverEngineDLLAccess class and there is one additional class called UseCaseTests. The test class for the SimpleRiverEngineDLLAccess class was left out because every method in the SimpleRiverEngineDotNetAccess class will invoke the corresponding method in the SimpleRiverEngineDLLAccess class; therefore testing all methods in the SimpleRiverEngineDotNetAccess class will be sufficient.


The main idea of unit testing is to create very simple code that will test each method in the classes. However, it can also be useful to make some more advanced tests that are actually running full simulations. This is done in the UseCaseTests class. This class ensures that the use cases described in section 2.1 run without errors.


As described earlier, the model is migrated by implementing the IEngine interface. For every IEngine method in the MyEngineWrapper class you decide which method needs to be implemented in the remaining wrapper classes. You will implement the methods or functions that are needed in the engine core and then implement the corresponding methods in the MyEngineDLLAccess class and MyEngineDotNetAccess class. Each time you have
completed the implementation of a method you can create a test method in the MyEngineDotNetAccessTest class and run the unit test. You can then move on to implement the method in MyEngineAccess and the associated test methods.


Below is the sample test code for the GetModelID method implementation in the Simple River model. Figure 19 shows the NUnit interface.

Code Block

using System;
using Oatc.OpenMI.Examples.ModelComponents.SimpleRiver.Wrapper;
using NUnit.Framework;
namespace org.OpenMITest.Examples.ModelComponents.SimpleRiver.Wrapper
{
   [TestFixture]
   public class SimpleRiverEngineDotNetAccessTest
   {
      [Test]
      public void GetModelID()
      {
         SimpleRiverEngineDotNetAccess _simpleRiverEngineDotNetAccess;
         String _filePath;
        _simpleRiverEngineDotNetAccess = new SimpleRiverEngineDotNetAccess();
        _filePath = 'C:\\SimpleRiver\\UnitTest\\Data\\Rhine';
        _simpleRiverEngineDotNetAccess.Initialize(_filePath);
        Assert.AreEqual('The river Rhine',
        _simpleRiverEngineDotNetAccess.GetModelID());
        _simpleRiverEngineDotNetAccess.Finish();
      }  
   }
}

Image Added
Fig. 19. NUnit Userinterface with Simple River wrapper classes loaded

7. Implementing IManageState

Implementation of the IManageState interface is not required in order to claim OpenMI compliance. However, if you want to use your model in configurations where iterations are needed or you want to use calibration or optimization controllers, the implementation of the IManageState interface is required. Normally, you should put the bulk of the implementation into the engine core and save the data required in order to restore a state in memory.

The IManageState interface

Implementation of the IManageState interface is shown in Figure 20.


The LinkableEngine class already implements the required methods for the IManageState interface but it is not specified in this class that it implements the IManageState interface.


To implement the IManageState interface when using the LinkableEngine, the procedure is as follows:

  1. In MyLinkableEngine, specify that it implements the IManageState interface.
  2. In MyEngineWrapper, specify that it implements the IManageState interface.
  3. Implement the IManageState methods in all wrapper classes. The implementation will typically be very simple code that redirects the call to the next wrapper class and finally to the engine core, where the bulk of the implementation is located.