Overview
The SSH Monitoring ZenPacks include a unit testing framework that is easily extendable with the command output from various hosts. This extensibility can be used to add command output found in the field that triggered bugs in the parsers.
The unittest Files that Drive the Tests
Each SSH Monitoring ZenPack should have a testPlugins.py and testParsers.py file in its tests directory. These test scripts walk the plugindata and parserdata directories to find test data.
If those files do not exist in the ZenPack you are working on, create them and add a class that extends BasePluginsTestCase or BaseParserTestCase. The subclass you create should include a single method named runTest.
For plugins, runTest should call the super class's _testDataFiles method passing in the root data directory as
os.path.join(os.path.dirname(__file__), 'plugindata')
and a list of plugin classes that have been imported into the module.
For parsers, runTest should call the super class's _testParsers method passing in the root data directory as
os.path.join(os.path.dirname(__file__), 'parserdata')
and a dictionary that maps commands to parser classes that have been imported into the module.
Both types of test modules need the following function to be defined in them:
def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()
suite.addTest(makeSuite( <YOUR TEST CASE CLASS NAME > ))
return suite
Adding Data to Create a New Test
To create a new test you need to create a new folder with the name of the host under the appropriate testdata directory (e.g. tests/parserdata/linux/leak.zenoss.loc). In that new folder place two files. Both files share the same name; one has no extension and the other has a .py extension.
The file with no extension must contain the command on the first line, and the output of the command on the subsequent lines. The file with the .py extension contains a Python dictionary with expected values that were manually parsed from the command output. The format of these dictionaries is slightly different depending on the type of test (modeling plugin or datapoint parser). The formats will be covered in sections later in this document.
Note that if you are adding the first test data files for a parser, then you must edit testPlugins.py or testParsers.py to import the parser module and add the module to the list of tested modules.
Dictionary Format for Modeling Plugin Tests
Multiple modeling plugins can parse the same command. The first level of keys in the dictionary is the name of the modeling plugin class.
Modeling plugins can return values of the following types (which are defined in Products/):
- ObjectMap
- RelationshipMap
- list of the above data map classes
The test data for each of these return types is in different formats.
Test Data for an ObjectMap
The test data is formatted as a simple dictionary that maps the attribute names of that ObjectMap to the expected values.
Test Data for a RelationshipMap
RelationshipMaps contain many ObjectsMaps. The test data is formatted as a two-level nested dictionary. The first level of keys is the ID that identifies the ObjectMap under test. The second level dictionary maps the attribute names of that ObjectMap to the expected values.
Test Data for a List of Data Maps
The test data is formatted as a list of dictionaries. The dictionaries are flat for ObjectMaps or two-level nested for RelationshipMaps.
Dictionary Format for Datapoint Parser Tests
Datapoint parsers differ in their return values. They can either return Device-level datapoints or component datapoints. The test data is formatted differently based on the return type of the parser.
Test Data for Device-Level Parsers
The test data for a device-level parser is formatted as a simple dictionary. The keys are the IDs of the datapoints returned by the parser.
Test Data for Component Parsers
The test data for a component parser is formatted as a two-deep nested dictionary. The first-level keys are the IDs of the components under test. The second-level dictionary maps the IDs of the datapoints to the expected values.
Running the Tests
To run all the tests in a ZenPack Use the last part of the ZenPack name
runtests --type unit ZenPacks.zenoss.LinuxMonitor
To run a single test
runtests --type unit --name testLinuxPlugins ZenPacks.zenoss.LinuxMonitor