configurationengine/doc/plugins/dev-plugin/example-plugin.rst
author m2lahtel
Tue, 10 Aug 2010 14:29:28 +0300
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
permissions -rw-r--r--
ConE 1.2.11 release
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     1
.. _plugin-howto-example-plugin:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     2
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     3
Example plug-in
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     4
===============
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     5
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     6
The example plug-in implements a simple Implementation Markup Language that can write
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     7
text files with possibly some content coming from ConfML setting values. The plug-in
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     8
demonstrates some recommended practices for developing ConE plug-ins:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     9
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    10
- Plug-in structure:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    11
    - Reader class
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    12
    - Implementation class
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    13
    - Implementation model
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    14
- Using ``cone.public.utils`` for ConfML setting reference handling
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    15
- Providing XML schema validation and model-level validation
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    16
- Unit tests:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    17
    - Testing the reader class, the implementation class and the model classes separately
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    18
    - Output generation testing (plug-in scope integration test)
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    19
    - Validation testing
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    20
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    21
The ExampleML language
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    22
----------------------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    23
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    24
The Implementation Markup Language in the example plug-in is ExampleML. The language
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    25
offers a simple mechanism to write text files to the output directory. For example:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    26
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    27
.. code-block :: xml
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    28
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    29
    <?xml version="1.0" encoding="UTF-8"?>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    30
    <exampleml xmlns="http://www.example.org/xml/exampleml/1">
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    31
        <output file="test1.txt" encoding="UTF-8">Test</output>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    32
        <output file="some/dir/test2.txt" encoding="UTF-16">Test</output>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    33
    </exampleml>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    34
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    35
To demonstrate the use of ConfML setting references, the language supports also
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    36
those with the form ``${Feature.Setting}``. This is the usual way of using them
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    37
in implementation languages, and it is recommended to use the same convention
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    38
in all ImplMLs. For example:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    39
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    40
.. code-block :: xml
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    41
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    42
    <?xml version="1.0" encoding="UTF-8"?>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    43
    <exampleml xmlns="http://www.example.org/xml/exampleml/1">
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    44
        <output file="${SomeFeature.OutputDir}/test2.txt"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    45
                encoding="${SomeFeature.OutputEncoding}">
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    46
            Value from ConfML: ${SomeFeature.OutputText}
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    47
        </output>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    48
    </exampleml>
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    49
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    50
.. _plugin-howto-example-plugin-dir-structure:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    51
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    52
Directory structure
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    53
-------------------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    54
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    55
- ``plugins/`` - Root directory for all ConE plug-in sources
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    56
    - ``example/`` - Example plug-in package directory
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    57
        - ``ConeExamplePlugin/`` - Source for the example plug-in
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    58
            - ``examplemlplugin/`` - Module directory containing all plug-in code
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    59
                - ``tests/`` - Unit tests and test data for the plug-in
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    60
                    - ``testdata/`` - Directory containing all test data needed by the test cases
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    61
                    - ``__init__.py`` - Test module initialization file
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    62
                    - ``runtests.py`` - Script for running all test cases
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    63
                    - ``unittest_exampleml_impl.py`` - File containing test cases
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    64
                    - ``unittest_exampleml_reader.py`` - File containing test cases
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    65
                    - ``unittest_exampleml_generation.py`` - File containing test cases
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    66
                    - ``unittest_exampleml_validation.py`` - File containing test cases
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    67
                - ``xsd/`` - XML Schema files for schema validation
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    68
                    - ``exampleml.xsd`` - Schema file for schema validation
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    69
                - ``__init__.py`` - Plug-in module initialization file
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    70
                - ``exampleml_impl.py`` - Plug-in source file
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    71
                - ``exampleml_reader.py`` - Plug-in source file
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    72
                - ``exampleml_validators.py`` - Plug-in source file
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    73
            - ``setup.py`` - Setup script for packaging the plug-in into an .egg file
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    74
            - ``setup.cfg`` - Configuration file for ``setup.py``
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    75
        - ``integration-test/`` - Integration tests for the example plug-in package
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    76
            - ``testdata/`` - Test data for the integration tests
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    77
            - ``__init__.py`` - Test module initialization file
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    78
            - ``runtests.py`` - Script for running all test cases
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    79
            - ``export_standalone.py`` - Script for exporting extra data for standalone test export
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    80
            - ``unittest_generate.py`` - File containing test cases
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    81
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    82
Logical structure
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    83
-----------------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    84
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    85
Logically the plug-in is divided into three parts:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    86
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    87
- *Implementation model*, represents the logical model of the implementation specified in the XML data
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    88
- *Implementation class*, works as the interface of the plug-in towards ConE and uses the model to do the actual work
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    89
- *Implementation reader*, converts the XML data into the logical model and creates a new implementation class instance
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    90
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    91
Here the *model* consists just of the class Output, which corresponds to the ``<output>`` element.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    92
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    93
In addition to these, there is a collection of *validator classes* that are
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    94
responsible for handling model-level validation.
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    95
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    96
Plug-in code
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    97
------------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    98
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    99
exampleml_model.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   100
..................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   101
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   102
This file defines the ``Output`` class, which comprises the whole implementation model
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   103
in this case. The class contains the same attributes as its XML element counterpart:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   104
file, encoding and text, as well as the methods for generating output from the
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   105
``Output`` object.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   106
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   107
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_model.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   108
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   109
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   110
Notice the use of ``cone.public.utils`` to handle the ConfML settings references. Usage of
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   111
setting refs is common enough to warrant a set of functions related to their handling in ``utils``.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   112
It is strongly recommended to use these utility functions instead of creating your own.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   113
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   114
.. note::
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   115
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   116
    The expanding of ConfML setting references is done here, in the ``Output`` object, instead of in the reader
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   117
    when the implementation is parsed. If it was done in the parsing phase, ConfML setting values changed
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   118
    in rules would not be expanded to their new values.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   119
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   120
Another noteworthy thing is that the ``Output`` class implements the methods ``__eq__()``,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   121
``__ne__()`` and ``__repr__()``. These have no real use in the actual implementation, but they
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   122
make unit testing easier, as will be seen later on.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   123
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   124
The logic for creating the output is here encoded directly in the model, but in cases where
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   125
the model is more complex, it may be necessary to create a separate writer class, particularly
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   126
if there is more than one output format to be created based on the same model.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   127
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   128
exampleml_impl.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   129
.................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   130
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   131
This file defines the implementation class. As can be seen, the class is quite simple, since
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   132
it uses the model class to do the actual work and only works as an interface towards ConE.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   133
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   134
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_impl.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   135
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   136
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   137
exampleml_reader.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   138
...................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   139
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   140
This file defines the reader class. Note how the reading of a single element is given its
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   141
own method. Again, this is to make unit testing easier.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   142
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   143
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_reader.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   144
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   145
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   146
Note that the reader class provides the XML schema by overriding
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   147
``get_schema_data()``. If this method was not overridden, a default schema
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   148
that accepts (almost) anything would be used for schema validation.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   149
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   150
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   151
exampleml_validators.py
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   152
...................
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   153
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   154
This file defines all validator classes. Since ExampleML is so simple, there
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   155
are only two cases that need to be validated on the model level: setting
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   156
references and the encoding. Notice that the setting reference validator
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   157
uses the method ``check_feature_reference()`` inherited from ``ImplValidatorBase``.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   158
As there are utility functions for handling references in a uniform way, there
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   159
is also a utility function for validating them.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   160
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   161
Note also the class list VALIDATOR_CLASSES at the bottom, which contains both
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   162
of the validator classes. The file ``setup.py`` contains an entry point
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   163
definition that points to this list, and the validation framework finds the
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   164
validators via that.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   165
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   166
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/exampleml_validators.py
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   167
   :linenos:
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   168
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   169
Unit tests
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   170
----------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   171
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   172
Due to the dynamic nature of Python, an extensive set of unit tests is required for every plug-in.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   173
The unit tests for a ConE plug-in should be in a ``tests`` module (directory) under the plug-in's
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   174
main module directory, and contain a set ``unittests_*.py`` files. The naming here is important,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   175
since the ``runtests.py`` file used to run all the unit tests at once collects test cases only
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   176
from .py files starting with ``unittest_``.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   177
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   178
Unit tests can be executed by running each individual unit test file separately using "Run as" -> "Python unit-test" or
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   179
all of the plug-in's unit tests at once by using "Run as" -> "Python run" on ``runtests.py``.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   180
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   181
.. image:: run_unittest.png
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   182
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   183
*Running a single unit test file*
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   184
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   185
It is recommended (well, actually required) to make sure that all unit tests pass before committing changes made to
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   186
the code of any plug-in. Also, it should be checked that all of the plug-in's unit tests pass when run as part
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   187
of all plug-in unit tests. It is possible that tests that pass when running ``runtests.py`` fail when running them
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   188
as part of the whole plug-in test set, as in that case the working directory is not the same. The entire plug-in test
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   189
set can be run from ``source/plugins/tests/runtests.py``.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   190
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   191
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   192
unittest_exampleml_reader.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   193
............................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   194
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   195
This file tests that the reader class functions properly. See how there is a test case for reading
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   196
a single ``<output>`` element that tests all the special cases there, and then another that
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   197
tests the top-level reader method. Here it becomes obvious why it is worthwhile to implement the
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   198
``__eq__()`` etc. methods in model classes, as in the tests we can just give the parser an XML
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   199
string and specify exactly what kind of a Python object is expected to be parsed from it.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   200
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   201
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_reader.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   202
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   203
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   204
unittest_exampleml_impl.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   205
..........................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   206
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   207
This file tests that the implementation class works as expected. The methods to test are ``has_ref()``
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   208
and ``list_output_files()``, since it is vital for the plug-in's correct operation that these methods
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   209
do what they are supposed to. Note that ``generate()`` is not tested here, as it is tested in its own
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   210
file.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   211
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   212
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_impl.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   213
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   214
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   215
unittest_exampleml_generation.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   216
................................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   217
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   218
This file tests that the plug-in works correctly throughout its lifecycle, so it works as an integration test.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   219
Note that plug-in instances are not created manually, but an implementation container is created from the project.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   220
This means that the test also makes sure that the plug-in interoperates correctly with ConE's plug-in machinery.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   221
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   222
Also note that the output is checked against an expected set of files using the method ``assert_dir_contents_equal()``,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   223
which comes from a unit test base class defined in a special ``testautomation`` module. This module contains also other
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   224
helper methods for use in unit tests, so if you need something more sophisticated than the simple methods provided
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   225
by the ``unittest`` module, you should check the ``testautomation`` module before writing the methods yourself.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   226
The module can be found under ``source/``.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   227
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   228
Notice also how the generation output directory is set to be in a ``temp/`` directory in the same directory
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   229
as the test .py file is. It is recommended to keep all temporary test data in a single place like this, so that
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   230
they don't litter e.g. the current working directory. When using a single ``temp/`` directory, it can also be
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   231
ignored in version control to avoid unnecessarily listing the temporary data when checking for modification in
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   232
the workding copy.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   233
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   234
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_generation.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   235
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   236
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   237
unittest_exampleml_validation.py
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   238
................................
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   239
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   240
Like ``unittest_exampleml_generation.py`` test output generation, this file
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   241
tests validation. The test cases themselves are pretty simple, since there are
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   242
pre-existing helper methods for running the tests, and the tests mainly consist
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   243
of test data and expected.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   244
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   245
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/examplemlplugin/tests/unittest_exampleml_validation.py
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   246
   :linenos:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   247
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   248
   
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   249
Plug-in packaging
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   250
-----------------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   251
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   252
The file ``setup.py`` handles the packaging of the plug-in into an egg file.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   253
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   254
The most important thing here is the plug-in's entry point info. The
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   255
plug-in's reader and validator classes must be specified as entry points,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   256
or they won't be loaded.
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   257
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   258
.. literalinclude:: /../source/plugins/example/ConeExamplePlugin/setup.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   259
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   260
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   261
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   262
.. _plugin-howto-example-plugin-integration-tests:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   263
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   264
Integration tests
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   265
-----------------
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   266
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   267
In addition to the unit tests inside the plug-in itself there is a separate integration test set.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   268
The purpose of these tests is to make sure that the plug-ins in the package work properly
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   269
together with other implementations from the CLI level. E.g. a common case that is good to
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   270
test is to check that ConfML settings changed in rules affect the implementations using
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   271
references to those settings work properly.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   272
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   273
These tests are also exported as part of the standalone test set used to test a pre-built
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   274
ConE distribution (see :ref:`installation-export-tests`). This affects the way some things
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   275
are handled in the test cases, for example the way the command to run is determined.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   276
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   277
The integration test set is plug-in package specific, not plug-in specific, so the test
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   278
project(s) used there should contain implementations of all the implementation languages
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   279
provided by the plug-ins in the package. Of course, in this case there are only ExampleML
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   280
implementations, since the example plug-in is the only plug-in in the example package.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   281
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   282
runtests.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   283
...........
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   284
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   285
This file simply acts as a shortcut to run all test cases easily.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   286
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   287
__init__.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   288
...........
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   289
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   290
This file performs all integration test specific initialization using the plug-in utility
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   291
functions in the root ``plugins/`` directory. Note that when the integration test set is
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   292
exported as standalone, the contents of this file are erased (the integration test
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   293
initialization cannot be done there, since the full ConE source is not available). Because
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   294
of this, you should not put anything that is always needed in this file.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   295
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   296
export_standalone.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   297
....................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   298
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   299
This file contains a function for exporting any needed extra data into the standalone test
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   300
set (e.g. something from under the plug-in sources). The file doesn't necessarily need to
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   301
exist if there is no extra data in need of exporting, but in this example it exists to show
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   302
what could be done in it.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   303
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   304
.. literalinclude:: /../source/plugins/example/integration-test/export_standalone.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   305
   :linenos:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   306
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   307
unittest_generate.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   308
....................
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   309
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   310
This file contains tests for generating output using the example plug-in.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   311
Note the following things:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   312
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   313
- The check if ``CONE_CMD`` is in the environment variables in ``get_cmd()``.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   314
  This variable is set to contain the actual ConE command to run if the tests
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   315
  are being run from the exported standalone test set. In practice this will be
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   316
  something like  ``C:/cone_test/cone/cone.cmd``.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   317
- The actual generation and testing is done in a separate function, ``_run_test_generate()``,
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   318
  and there are two actual test functions that call it. One runs the test directly on the
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   319
  test project on the file system, and another first zips the test project and then runs
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   320
  the test on that. It is a good idea to test that generation works the same in both cases,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   321
  since it can be easy to forget to take into account generation from a ZIP file when creating
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   322
  a plug-in (e.g. using ``shutil`` functions to perform copy operations when the ConE API
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   323
  should be used).
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   324
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   325
.. literalinclude:: /../source/plugins/example/integration-test/unittest_generate.py
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   326
   :linenos: