未验证 提交 25cc3755 编写于 作者: C Caio Carrara

Merge remote-tracking branch 'clebergnu/test_params_v2'

Signed-off-by: NCaio Carrara <ccarrara@redhat.com>
...@@ -134,6 +134,16 @@ class Job(object): ...@@ -134,6 +134,16 @@ class Job(object):
self.test_suite = None self.test_suite = None
self.test_runner = None self.test_runner = None
#: Placeholder for test parameters (related to --test-parameters command
#: line option). They're kept in the job because they will be prepared
#: only once, since they are read only and will be shared acrross all
#: tests of a job.
self.test_parameters = None
if "test_parameters" in self.args:
self.test_parameters = {}
for parameter_name, parameter_value in self.args.test_parameters:
self.test_parameters[parameter_name] = parameter_value
# The result events dispatcher is shared with the test runner. # The result events dispatcher is shared with the test runner.
# Because of our goal to support using the phases of a job # Because of our goal to support using the phases of a job
# freely, let's get the result events dispatcher ready early. # freely, let's get the result events dispatcher ready early.
......
...@@ -25,6 +25,7 @@ import sys ...@@ -25,6 +25,7 @@ import sys
import time import time
from . import test from . import test
from . import tree
from . import exceptions from . import exceptions
from . import output from . import output
from . import status from . import status
...@@ -505,8 +506,7 @@ class TestRunner(object): ...@@ -505,8 +506,7 @@ class TestRunner(object):
return False return False
return True return True
@staticmethod def _template_to_factory(self, template, variant):
def _template_to_factory(template, variant):
""" """
Applies test params from variant to the test template Applies test params from variant to the test template
...@@ -520,19 +520,25 @@ class TestRunner(object): ...@@ -520,19 +520,25 @@ class TestRunner(object):
""" """
var = variant.get("variant") var = variant.get("variant")
paths = variant.get("paths") paths = variant.get("paths")
empty_variants = varianter.is_empty_variant(var)
if "params" not in template[1]: if "params" not in template[1]:
factory = [template[0], template[1].copy()] factory = [template[0], template[1].copy()]
if self.job.test_parameters and empty_variants:
var[0] = tree.TreeNode().get_node("/", True)
var[0].value = self.job.test_parameters
paths = ["/"]
factory[1]["params"] = (var, paths) factory[1]["params"] = (var, paths)
return factory, variant return factory, variant
if not varianter.is_empty_variant(var): if not empty_variants:
raise NotImplementedError("Specifying test params from test loader " raise NotImplementedError("Specifying test params from test loader "
"and from varianter at the same time is " "and from varianter at the same time is "
"not yet supported. Please remove either " "not yet supported. Please remove either "
"variants defined by the varianter (%s) " "variants defined by the varianter (%s) "
"or make the test loader oftest %s to not " "or make the test loader of test %s to "
"to fill variants." % (variant, template)) "not to fill variants." % (variant,
template))
return template, {"variant": var, return template, {"variant": var,
"variant_id": varianter.generate_variant_id(var), "variant_id": varianter.generate_variant_id(var),
......
...@@ -42,6 +42,15 @@ class Run(CLICmd): ...@@ -42,6 +42,15 @@ class Run(CLICmd):
description = ("Runs one or more tests (native test, test alias, binary " description = ("Runs one or more tests (native test, test alias, binary "
"or script)") "or script)")
@staticmethod
def _test_parameter(string):
param_name_value = string.split('=', 1)
if len(param_name_value) < 2:
msg = ('Invalid --test-parameter option: "%s". Valid option must '
'be a "NAME=VALUE" like expression' % string)
raise argparse.ArgumentTypeError(msg)
return param_name_value
def configure(self, parser): def configure(self, parser):
""" """
Add the subparser for the run action. Add the subparser for the run action.
...@@ -54,6 +63,15 @@ class Run(CLICmd): ...@@ -54,6 +63,15 @@ class Run(CLICmd):
metavar="TEST_REFERENCE", metavar="TEST_REFERENCE",
help='List of test references (aliases or paths)') help='List of test references (aliases or paths)')
parser.add_argument("-p", "--test-parameter", action="append",
dest='test_parameters', default=[],
metavar="NAME_VALUE", type=self._test_parameter,
help="Parameter name and value to pass to all "
"tests. This is only applicable when not using a "
"varianter plugin. This option format must be "
"given in the NAME=VALUE format, and may be given "
"any number of times, or per parameter.")
parser.add_argument("-d", "--dry-run", action="store_true", parser.add_argument("-d", "--dry-run", action="store_true",
help="Instead of running the test only " help="Instead of running the test only "
"list them and log their params.") "list them and log their params.")
......
...@@ -26,16 +26,17 @@ Overall picture of how the params handling works is: ...@@ -26,16 +26,17 @@ Overall picture of how the params handling works is:
.. code-block:: c .. code-block:: c
+-----------+ +-----------+
| | // Test uses variant to produce AvocadoParams | | // Test uses AvocadoParams, with content either from
| Test | | Test | // a variant or from the test parameters given by
| | | | // "--test-parameters"
+-----^-----+ +-----^-----+
| // single variant is passed to Test |
| |
+-----------+ +-----------+
| Runner | // iterates through tests and variants to run all | Runner | // iterates through tests and variants to run all
+-----^-----+ // desired combinations specified by "--execution-order" +-----^-----+ // desired combinations specified by "--execution-order".
| | // if no variants are produced by varianter plugins,
| // use the test parameters given by "--test-parameters"
| |
+-------------------+ provide variants +-----------------------+ +-------------------+ provide variants +-----------------------+
| |<-----------------| | | |<-----------------| |
...@@ -273,6 +274,33 @@ Where: ...@@ -273,6 +274,33 @@ Where:
* path - the location of this parameter. When the path does not exists yet, * path - the location of this parameter. When the path does not exists yet,
it's created out of `TreeNode`_. it's created out of `TreeNode`_.
Test parameters
~~~~~~~~~~~~~~~
This is an Avocado core feature, that is, it's not dependent on any
varianter plugin. In fact, it's only active when no Varianter plugin
is used and produces a valid variant.
Avocado will use those simple parameters, and will pass them to all
tests in a job execution. This is done on the command line via
``--test-parameters``, or simply, ``-p``. It can be given multiple
times for multiple parameters.
Because Avocado parameters do not have a mechanism to define their
types, test code should always consider that a parameter value is a
string, and convert it to the appropriate type.
.. note:: Some varianter plugins would implicitly set parameters
with different data types, but given that the same test can be
used with different, or none, varianter plugins, it's safer if
the test does an explicit check or type conversion.
Because the :class:`avocado.core.varianter.AvocadoParams` mandates the
concept of a parameter path (a legacy of the tree based Multiplexer)
and these test parameters are flat, those test parameters are placed
in the ``/`` path. This is to ensure maximum compatibility with tests
that do not choose an specific parameter location.
Varianter plugins Varianter plugins
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
......
...@@ -18,7 +18,7 @@ class SleepTest(Test): ...@@ -18,7 +18,7 @@ class SleepTest(Test):
""" """
Sleep for length seconds. Sleep for length seconds.
""" """
sleep_length = self.params.get('sleep_length', default=1) sleep_length = float(self.params.get('sleep_length', default=1))
self.log.debug("Sleeping for %.2f seconds", sleep_length) self.log.debug("Sleeping for %.2f seconds", sleep_length)
time.sleep(sleep_length) time.sleep(sleep_length)
......
...@@ -554,6 +554,18 @@ class RunnerOperationTest(unittest.TestCase): ...@@ -554,6 +554,18 @@ class RunnerOperationTest(unittest.TestCase):
self.assertEqual(result.exit_status, 1, "Expected exit status is 1\n%s" self.assertEqual(result.exit_status, 1, "Expected exit status is 1\n%s"
% result) % result)
def test_runner_test_parameters(self):
cmd_line = ('%s --show=test run --sysinfo=off --job-results-dir %s '
'-p "sleep_length=0.01" -- sleeptest.py ' % (AVOCADO,
self.tmpdir))
result = process.run(cmd_line, ignore_status=True)
expected_rc = exit_codes.AVOCADO_ALL_OK
self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" % (expected_rc, result))
self.assertIn(b"PARAMS (key=sleep_length, path=*, default=1) => '0.01'",
result.stdout)
self.assertIn(b"Sleeping for 0.01 seconds", result.stdout)
def tearDown(self): def tearDown(self):
shutil.rmtree(self.tmpdir) shutil.rmtree(self.tmpdir)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册