Test structure – stage, players and scenario

This post is part of the SATF work.

The procedure stated in the “Test flow” section defines the entities involved in simulation auto acceptance testing. But the MRDS mechanics and general unit testing patterns are what determines the actual structure of a test. An example of that structure was presented early on in the “Test example” section, although now, MRDS have been reviewed, it starts making more sense. Since the current section is actually an explanation of what was presented there, I do not reference the section explicitly below, but imply it as a primary example. A simulation auto acceptance test consists of three parts: physics environment description, software description and test scenario.

The physics environment description – the snapshot of the physical world at the beginning of the test – amounts to the stored state of the simulation engine at that moment. Like the state of any other service, it could be persisted into a conventional xml file by standard DSS means. As a part of simulation test, the extension of this file is “environ.xml”. Among all the simulation entities there, dynamic ones could be discerned by the name, which by convention contain the “@” symbol. To run ahead, the same convention applies to the services’ names. The software part of the test description provides information about all involved services and their relations. In fact, that is exactly what DSS manifest files are supposed to do. But the service part could be more than a single “manifest.xml” file, because each service could possess some settings stored in the corresponding “config.xml” file. Jointly, physics and software test parts comprise a test fixture – test environment prepared for execution of the test scenario. In practice, single test fixture handles multiple tests imposing different challenges on the same object in the same circumstances. These challenges – test scenarios or simply tests – are stated in code.

Each test fixture has a corresponding C# class with multiple inner classes for each of the simulation acceptance tests. That one-to-many relation between the fixture and the tests conforms with conventional unit tests organization. The difference is that a standard unit test corresponds to a fixture class method, not an inner class. This is explained by much more rigid, complicated and specialized structure and flow of simulation acceptance test. The test runner implements better part of the testing procedure described in the “Test flow” section, leaving a test author to implement only few key parts of the test. But these parts, having to be located in one place, could not be logically crammed into a single method. And an inner fixture class looks like the most appropriate container for them. Whereas a standard unit test could contain arbitrary code, assertions and flow as long as they fit logically into one method. As is usually the case, versatility is traded for efficiency.

Namely, these key missing test parts are:

  • the test duration (stated in the special test attribute)
  • the Prepare method, that could alter the state of loaded dynamic entities at the beginning of a test try (it receives them as a parameter)
    void Prepare(IEnumerable<Mrse.VisualEntity> dynamicEntities);
  • the Start method, that commences execution of a test script
    IEnumerator<ITask> Start();
  • the Test method, that executes test assertions at the end of a test try (it receives a list of dynamic simulation entities comprising the simulation world at the end of a try and the actual test duration, which could differ slightly from the one stated in the test declaration)
    IEnumerator<ITask> Test(Action<bool> @return, IEnumerable<MrsePxy.VisualEntity> entities, double elapsedTime);
  • the fixture Setup method, that configures and wires up reloaded simulation entities and services at the beginning of a test try (it receives the instance of the test runner service, which exposes that way all of its API to a simulation test)
    void SetUp(SimulationTesterService testerService);

Return types of the the Start and Test methods (IEnumerator<ITask>) is required for CCR asynchrony pattern.

Indeed, due to the structure, the simulation acceptance tests look intimidating compared to single method unit tests. And they are, but no more than their real life counterparts. It is not that simulation acceptance tests are so complicated – life is.

Previous Next

Leave a Reply

Your email address will not be published. Required fields are marked *