Merge "Fix how tier_handler is imported"
[functest.git] / functest / core / unit.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 Cable Television Laboratories, Inc. and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 """Define the parent class to run unittest.TestSuite as TestCase."""
11
12 from __future__ import division
13
14 import logging
15 import time
16 import unittest
17
18 import six
19
20 from functest.core import testcase
21
22 __author__ = ("Steven Pisarski <s.pisarski@cablelabs.com>, "
23               "Cedric Ollivier <cedric.ollivier@orange.com>")
24
25
26 class Suite(testcase.TestCase):
27     """Base model for running unittest.TestSuite."""
28
29     __logger = logging.getLogger(__name__)
30
31     def __init__(self, **kwargs):
32         super(Suite, self).__init__(**kwargs)
33         self.suite = None
34
35     def run(self, **kwargs):
36         """Run the test suite.
37
38         It allows running any unittest.TestSuite and getting its
39         execution status.
40
41         By default, it runs the suite defined as instance attribute.
42         It can be overriden by passing name as arg. It must
43         conform with TestLoader.loadTestsFromName().
44
45         It sets the following attributes required to push the results
46         to DB:
47
48             * result,
49             * start_time,
50             * stop_time,
51             * details.
52
53         Args:
54             kwargs: Arbitrary keyword arguments.
55
56         Returns:
57             TestCase.EX_OK if any TestSuite has been run,
58             TestCase.EX_RUN_ERROR otherwise.
59         """
60         try:
61             name = kwargs["name"]
62             try:
63                 self.suite = unittest.TestLoader().loadTestsFromName(name)
64             except ImportError:
65                 self.__logger.error("Can not import %s", name)
66                 return testcase.TestCase.EX_RUN_ERROR
67         except KeyError:
68             pass
69         try:
70             assert self.suite
71             self.start_time = time.time()
72             stream = six.StringIO()
73             result = unittest.TextTestRunner(
74                 stream=stream, verbosity=2).run(self.suite)
75             self.__logger.debug("\n\n%s", stream.getvalue())
76             self.stop_time = time.time()
77             self.details = {
78                 "testsRun": result.testsRun,
79                 "failures": len(result.failures),
80                 "errors": len(result.errors),
81                 "stream": stream.getvalue()}
82             self.result = 100 * (
83                 (result.testsRun - (len(result.failures) +
84                                     len(result.errors))) /
85                 result.testsRun)
86             return testcase.TestCase.EX_OK
87         except AssertionError:
88             self.__logger.error("No suite is defined")
89             return testcase.TestCase.EX_RUN_ERROR
90         except ZeroDivisionError:
91             self.__logger.error("No test has been run")
92             return testcase.TestCase.EX_RUN_ERROR