From 1bacb1e70a9ce80e6a045a81cef437de6d2975e0 Mon Sep 17 00:00:00 2001 From: Ekaterina Chernova Date: Tue, 8 Dec 2015 17:28:30 +0300 Subject: [PATCH] [docs] Add murano test runner information Targets blueprint simulated-execution-mode-murano-engine Change-Id: Ie811b49f27551d0e8765fd9516f16f54026e888f --- .../draft/appdev-guide/app_unit_tests.rst | 223 ++++++++++++++++++ doc/source/draft/appdev-guide/murano_pl.rst | 6 +- doc/source/draft/index.rst | 1 + doc/source/index.rst | 1 + 4 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 doc/source/draft/appdev-guide/app_unit_tests.rst diff --git a/doc/source/draft/appdev-guide/app_unit_tests.rst b/doc/source/draft/appdev-guide/app_unit_tests.rst new file mode 100644 index 00000000..baf90cf4 --- /dev/null +++ b/doc/source/draft/appdev-guide/app_unit_tests.rst @@ -0,0 +1,223 @@ +.. _app-unit-tests: + +.. toctree:: + :maxdepth: 2 + +====================== +Application unit tests +====================== + +Murano applications are written in :ref:`MuranoPL `. +To make the development of applications easier and enable application +testing, a special framework was created. So it is possible to add +unit tests to an application package and check if the application is in +actual state. Also, application deployment can be simulated with unit tests, +so you do not need to run the murano engine. + +A separate service that is called *murano-test-runner* is used to run +MuranoPL unit tests. + +All application test cases should be: + +* Specified in the MuranoPL class, inherited from + `io.murano.test.testFixture `_ + + This class supports loading object model with the corresponding `load(json)` + function. Also it contains a minimal set of assertions such as + ``assertEqual`` and etc. + + Note, that test class has the following reserved methods are: + + * *initialize* is executed once, like in any other murano application + * *setUp* is executed before each test case + * *tearDown* is executed after each test case + +* Named with *test* prefix + +.. code-block:: console + + usage: murano-test-runner [-h] [--config-file CONFIG_FILE] + [--os-auth-url OS_AUTH_URL] + [--os-username OS_USERNAME] + [--os-password OS_PASSWORD] + [--os-project-name OS_PROJECT_NAME] + [-l [ [ ...]]] [-v] + [--version] + + [ [ ...]] + + positional arguments: + + Full name of application package that is going to be + tested + + List of method names to be tested + + optional arguments: + -h, --help show this help message and exit + --config-file CONFIG_FILE + Path to the murano config + --os-auth-url OS_AUTH_URL + Defaults to env[OS_AUTH_URL] + --os-username OS_USERNAME + Defaults to env[OS_USERNAME] + --os-password OS_PASSWORD + Defaults to env[OS_PASSWORD] + --os-project-name OS_PROJECT_NAME + Defaults to env[OS_PROJECT_NAME] + -l [ [ ...]], --load_packages_from [ [ ...]] + Directory to search packages from. Will be used instead of + directories, provided in the same option in murano configuration file. + -v, --verbose increase output verbosity + --version show program's version number and exit + + +The fully qualified name of a package is required to specify the test location. +It can be an application package that contains one or several classes with all +the test cases, or a separate package. You can specify a class name to +execute all the tests located in it, or specify a particular test case name. + +Authorization parameters can be provided in the murano configuration file, or +with higher priority :option:`-os-` parameters. + +Consider the following example of test execution for the Tomcat application. +Tests are located in the same package with application, but in a separate class +called ``io.murano.test.TomcatTest``. It contains ``testDeploy1`` and +``testDeploy2`` test cases. +The application package is located in the */package/location/directory* +(murano-apps repository e.g). As the result of the following command, both +test cases from the specified package and class will be executed. + +.. code-block:: console + + murano-test-runner io.murano.apps.apache.Tomcat io.murano.test.TomcatTest -l /package/location/directory /io.murano/location -v + +The following command runs a single *testApacheDeploy* test case from the +application package. + +.. code-block:: console + + murano-test-runner io.murano.apps.apache.Tomcat io.murano.test.TomcatTest.testDeploy1 + +The main purpose of MuranoPL unit test framework is to enable mocking. +Special :ref:`yaql` functions are registered for that: + +`def inject(target, target_method, mock_object, mock_name)` + ``inject`` to set up mock for *class* or *object*, where mock definition is a *name of the test class method* + +`def inject(target, target_method, yaql_expr)` + ``inject`` to set up mock for *a class* or *object*, where mock definition is a *YAQL expression* + +Parameters description: + +**target** + MuranoPL class name (namespaces can be used or full class name + in quotes) or MuranoPL object + +**target_method** + Method name to mock in target + +**mock_object** + Object, where mock definition is contained + +**mock_name** + Name of method, where mock definition is contained + +**yaql_expr** + YAQL expression, parameters are allowed + +So the user is allowed to specify mock functions in the following ways: + +* Specify a particular method name +* Provide a YAQL expression + +Consider how the following functions may be used in the MuranoPL class with +unit tests: + +.. code-block:: yaml + + Namespaces: + =: io.murano.test + sys: io.murano.system + + Extends: TestFixture + + Name: TomcatTest + + Methods: + initialize: + Body: + # Object model can be loaded from json file, or provided + # directly in MuranoPL code as a yaml insertion. + - $.appJson: new(sys:Resources).json('tomcat-for-mock.json') + - $.heatOutput: new(sys:Resources).json('output.json') + - $.log: logger('test') + - $.agentCallCount: 0 + + # Mock method to replace the original one + agentMock: + Arguments: + - template: + Contract: $ + - resources: + Contract: $ + - timeout: + Contract: $ + Default: null + Body: + - $.log.info('Mocking murano agent') + - $.assertEqual('Deploy Tomcat', $template.Name) + - $.agentCallCount: $.agentCallCount + 1 + + # Mock method, that returns predefined heat stack output + getStackOut: + Body: + - $.log.info('Mocking heat stack') + - Return: $.heatOutput + + testDeploy1: + Body: + # Loading object model + - $.env: $this.load($.appJson) + + # Set up mock for the push method of *io.murano.system.HeatStack* class + - inject(sys:HeatStack, push, $.heatOutput) + + # Set up mock for the concrete object with mock method name + - inject($.env.stack, output, $.heatOutput) + + # Set up mock with YAQL function + - inject('io.murano.system.Agent', call, $this, agentMock) + + # Mocks will be called instead of original function during the deployment + - $.env.deploy() + + # Check, that mock worked correctly + - $.assertEqual(1, $.agentCallCount) + + + testDeploy2: + Body: + - inject(sys:HeatStack, push, $this, getStackOut) + - inject(sys:HeatStack, output, $this, getStackOut) + + # Mock is defined with YAQL function and it will print the original variable (agent template) + - inject(sys:Agent, call, withOriginal(t => $template) -> $.log.info('{0}', $t)) + + - $.env: $this.load($.appJson) + - $.env.deploy() + + - $isDeployed: $.env.applications[0].getAttr(deployed, false, 'io.murano.apps.apache.Tomcat') + - $.assertEqual(true, $isDeployed) + +Provided methods are test cases for the Tomcat application. Object model and +heat stack output are predefined and located in the package ``Resources`` +directory. By changing some object model or heat stack parameters, different +cases may be tested without a real deployment. Note, that some asserts are used +in those example. The first one is checked, that agent call function was called +only once as needed. And assert from the second test case checks for a variable +value at the end of the application deployment. + +Test cases examples can be found in :file:`TomcatTest.yaml` class of the +Apache Tomcat application located at `murano-apps repository `_. +You can run test cases with the commands provided above. diff --git a/doc/source/draft/appdev-guide/murano_pl.rst b/doc/source/draft/appdev-guide/murano_pl.rst index fc7d3ac6..cc123918 100644 --- a/doc/source/draft/appdev-guide/murano_pl.rst +++ b/doc/source/draft/appdev-guide/murano_pl.rst @@ -1,12 +1,12 @@ .. _murano-pl: -.. toctree:: - :maxdepth: 2 - ================== MuranoPL Reference ================== +.. toctree:: + :maxdepth: 2 + To develop applications, murano project refers to Murano Programming Language (MuranoPL). It is represented by easily readable YAML and YAQL languages. The sections below describe these languages. diff --git a/doc/source/draft/index.rst b/doc/source/draft/index.rst index 7a2570d2..ea4fb1e7 100644 --- a/doc/source/draft/index.rst +++ b/doc/source/draft/index.rst @@ -86,6 +86,7 @@ Developing Applications appdev-guide/murano_pl appdev-guide/murano_packages appdev-guide/app_migrating + appdev-guide/app_unit_tests appdev-guide/examples appdev-guide/use_cases appdev-guide/faq diff --git a/doc/source/index.rst b/doc/source/index.rst index 3fd22d4b..5b68afbd 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -99,6 +99,7 @@ Developing Applications draft/appdev-guide/murano_pl draft/appdev-guide/murano_packages draft/appdev-guide/app_migrating + draft/appdev-guide/app_unit_tests draft/appdev-guide/examples draft/appdev-guide/use_cases draft/appdev-guide/faq