Merge "Unit tests as stress tests"
diff --git a/tempest/stress/actions/unit_test.py b/tempest/stress/actions/unit_test.py
new file mode 100644
index 0000000..95cc1bc
--- /dev/null
+++ b/tempest/stress/actions/unit_test.py
@@ -0,0 +1,79 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.openstack.common import importutils
+import tempest.stress.stressaction as stressaction
+
+
+class SetUpClassRunTime(object):
+
+ process = 'process'
+ action = 'action'
+ application = 'application'
+
+ allowed = set((process, action, application))
+
+ @classmethod
+ def validate(cls, name):
+ if name not in cls.allowed:
+ raise KeyError("\'%s\' not a valid option" % name)
+
+
+class UnitTest(stressaction.StressAction):
+ """This is a special action for running existing unittests as stress test.
+ You need to pass ``test_method`` and ``class_setup_per``
+ using ``kwargs`` in the JSON descriptor;
+ ``test_method`` should be the fully qualified name of a unittest,
+ ``class_setup_per`` should be one from:
+ ``application``: once in the stress job lifetime
+ ``process``: once in the worker process lifetime
+ ``action``: on each action
+ Not all combination working in every case.
+ """
+
+ def setUp(self, **kwargs):
+ method = kwargs['test_method'].split('.')
+ self.test_method = method.pop()
+ self.klass = importutils.import_class('.'.join(method))
+ # valid options are 'process', 'application' , 'action'
+ self.class_setup_per = kwargs.get('class_setup_per',
+ SetUpClassRunTime.process)
+ SetUpClassRunTime.validate(self.class_setup_per)
+
+ if self.class_setup_per == SetUpClassRunTime.application:
+ self.klass.setUpClass()
+ self.setupclass_called = False
+
+ def run_core(self):
+ res = self.klass(self.test_method).run()
+ if res.errors:
+ raise RuntimeError(res.errors)
+
+ def run(self):
+ if self.class_setup_per != SetUpClassRunTime.application:
+ if (self.class_setup_per == SetUpClassRunTime.action
+ or self.setupclass_called is False):
+ self.klass.setUpClass()
+ self.setupclass_called = True
+
+ self.run_core()
+
+ if (self.class_setup_per == SetUpClassRunTime.action):
+ self.klass.tearDownClass()
+ else:
+ self.run_core()
+
+ def tearDown(self):
+ if self.class_setup_per != SetUpClassRunTime.action:
+ self.klass.tearDownClass()
diff --git a/tempest/stress/etc/sample-unit-test.json b/tempest/stress/etc/sample-unit-test.json
new file mode 100644
index 0000000..b388bfe
--- /dev/null
+++ b/tempest/stress/etc/sample-unit-test.json
@@ -0,0 +1,8 @@
+[{"action": "tempest.stress.actions.unit_test.UnitTest",
+ "threads": 8,
+ "use_admin": false,
+ "use_isolated_tenants": false,
+ "kwargs": {"test_method": "tempest.cli.simple_read_only.test_glance.SimpleReadOnlyGlanceClientTest.test_glance_fake_action",
+ "class_setup_per": "process"}
+ }
+]