Added testcase decorator to use in logging. Added class decorator LogResults that outputs test results in separate log file.

Submitted by Lucian Musat on June 27, 2014, 2:32 p.m.

Details

Message ID 1403879533-20717-1-git-send-email-georgex.l.musat@intel.com
State Accepted
Commit 7e2b73f1ccfe2968ef780fef2edfaa31c3dae853
Headers show

Commit Message

Lucian Musat June 27, 2014, 2:32 p.m.
Signed-off-by: Lucian Musat <georgex.l.musat@intel.com>
---
 meta/lib/oeqa/selftest/base.py     |  2 ++
 meta/lib/oeqa/selftest/bblayers.py |  6 ++++
 meta/lib/oeqa/utils/decorators.py  | 66 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

Patch hide | download patch | download mbox

diff --git a/meta/lib/oeqa/selftest/base.py b/meta/lib/oeqa/selftest/base.py
index fc880e9..80b9b4b 100644
--- a/meta/lib/oeqa/selftest/base.py
+++ b/meta/lib/oeqa/selftest/base.py
@@ -15,7 +15,9 @@  import errno
 
 import oeqa.utils.ftools as ftools
 from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
+from oeqa.utils.decorators import LogResults
 
+@LogResults
 class oeSelfTest(unittest.TestCase):
 
     log = logging.getLogger("selftest.base")
diff --git a/meta/lib/oeqa/selftest/bblayers.py b/meta/lib/oeqa/selftest/bblayers.py
index 52aa4f8..1ead8e8 100644
--- a/meta/lib/oeqa/selftest/bblayers.py
+++ b/meta/lib/oeqa/selftest/bblayers.py
@@ -7,25 +7,31 @@  import shutil
 import oeqa.utils.ftools as ftools
 from oeqa.selftest.base import oeSelfTest
 from oeqa.utils.commands import runCmd
+from oeqa.utils.decorators import testcase
 
 class BitbakeLayers(oeSelfTest):
 
+    @testcase(756)
     def test_bitbakelayers_showcrossdepends(self):
         result = runCmd('bitbake-layers show-cross-depends')
         self.assertTrue('aspell' in result.output)
 
+    @testcase(83)
     def test_bitbakelayers_showlayers(self):
         result = runCmd('bitbake-layers show_layers')
         self.assertTrue('meta-selftest' in result.output)
 
+    @testcase(93)
     def test_bitbakelayers_showappends(self):
         result = runCmd('bitbake-layers show_appends')
         self.assertTrue('xcursor-transparent-theme_0.1.1.bbappend' in result.output, msg='xcursor-transparent-theme_0.1.1.bbappend file was not recognised')
 
+    @testcase(90)
     def test_bitbakelayers_showoverlayed(self):
         result = runCmd('bitbake-layers show_overlayed')
         self.assertTrue('aspell' in result.output, msg='xcursor-transparent-theme_0.1.1.bbappend file was not recognised')
 
+    @testcase(95)
     def test_bitbakelayers_flatten(self):
         self.assertFalse(os.path.isdir(os.path.join(self.builddir, 'test')))
         result = runCmd('bitbake-layers flatten test')
diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py
index b99da8d..a0d94e6 100644
--- a/meta/lib/oeqa/utils/decorators.py
+++ b/meta/lib/oeqa/utils/decorators.py
@@ -7,6 +7,8 @@ 
 # creating dependecies between two test methods.
 
 from oeqa.oetest import *
+import logging
+import sys
 
 class skipIfFailure(object):
 
@@ -48,3 +50,67 @@  class skipUnlessPassed(object):
             return f(*args)
         wrapped_f.__name__ = f.__name__
         return wrapped_f
+
+class testcase(object):
+
+    def __init__(self, test_case):
+        self.test_case = test_case
+
+    def __call__(self, func):
+	def wrapped_f(*args):
+		return func(*args)
+	wrapped_f.test_case = self.test_case
+	return wrapped_f
+
+def LogResults(original_class):
+    orig_method = original_class.run
+
+    #rewrite the run method of unittest.TestCase to add testcase logging
+    def run(self, result, *args, **kws):
+        orig_method(self, result, *args, **kws)
+	passed = True
+	testMethod = getattr(self, self._testMethodName)
+
+	#if test case is decorated then use it's number, else use it's name
+	try:
+		test_case = testMethod.test_case
+	except AttributeError:
+		test_case = self._testMethodName
+
+	#create custom logging level for filtering.
+	custom_log_level = 100
+	logging.addLevelName(custom_log_level, 'RESULTS')
+	caller = os.path.basename(sys.argv[0])
+
+	def results(self, message, *args, **kws):
+	    if self.isEnabledFor(custom_log_level):
+		self.log(custom_log_level, message, *args, **kws)
+	logging.Logger.results = results
+
+	logging.basicConfig(filename=os.path.join(os.getcwd(),'results-'+caller+'.log'),
+                            filemode='w',
+                            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+                            datefmt='%H:%M:%S',
+                            level=custom_log_level)
+	local_log = logging.getLogger(caller)
+
+	#check status of tests and record it
+        for (name, msg) in result.errors:
+                if self._testMethodName == str(name).split(' ')[0]:
+			local_log.results("Testcase "+str(test_case)+": ERROR")
+			local_log.results("Testcase "+str(test_case)+":\n"+msg)
+			passed = False
+        for (name, msg) in result.failures:
+                if self._testMethodName == str(name).split(' ')[0]:
+			local_log.results("Testcase "+str(test_case)+": FAILED")
+			local_log.results("Testcase "+str(test_case)+":\n"+msg)
+			passed = False
+        for (name, msg) in result.skipped:
+                if self._testMethodName == str(name).split(' ')[0]:
+			local_log.results("Testcase "+str(test_case)+": SKIPPED")
+			passed = False
+	if passed:
+			local_log.results("Testcase "+str(test_case)+": PASSED")
+
+    original_class.run = run
+    return original_class

Comments

Ross Burton July 1, 2014, 2:19 p.m.
Looks good, decorators are fun. :)

Ross

On 27 June 2014 15:32, Lucian Musat <georgex.l.musat@intel.com> wrote:
> Signed-off-by: Lucian Musat <georgex.l.musat@intel.com>
> ---
>  meta/lib/oeqa/selftest/base.py     |  2 ++
>  meta/lib/oeqa/selftest/bblayers.py |  6 ++++
>  meta/lib/oeqa/utils/decorators.py  | 66 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 74 insertions(+)
>
> diff --git a/meta/lib/oeqa/selftest/base.py b/meta/lib/oeqa/selftest/base.py
> index fc880e9..80b9b4b 100644
> --- a/meta/lib/oeqa/selftest/base.py
> +++ b/meta/lib/oeqa/selftest/base.py
> @@ -15,7 +15,9 @@ import errno
>
>  import oeqa.utils.ftools as ftools
>  from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
> +from oeqa.utils.decorators import LogResults
>
> +@LogResults
>  class oeSelfTest(unittest.TestCase):
>
>      log = logging.getLogger("selftest.base")
> diff --git a/meta/lib/oeqa/selftest/bblayers.py b/meta/lib/oeqa/selftest/bblayers.py
> index 52aa4f8..1ead8e8 100644
> --- a/meta/lib/oeqa/selftest/bblayers.py
> +++ b/meta/lib/oeqa/selftest/bblayers.py
> @@ -7,25 +7,31 @@ import shutil
>  import oeqa.utils.ftools as ftools
>  from oeqa.selftest.base import oeSelfTest
>  from oeqa.utils.commands import runCmd
> +from oeqa.utils.decorators import testcase
>
>  class BitbakeLayers(oeSelfTest):
>
> +    @testcase(756)
>      def test_bitbakelayers_showcrossdepends(self):
>          result = runCmd('bitbake-layers show-cross-depends')
>          self.assertTrue('aspell' in result.output)
>
> +    @testcase(83)
>      def test_bitbakelayers_showlayers(self):
>          result = runCmd('bitbake-layers show_layers')
>          self.assertTrue('meta-selftest' in result.output)
>
> +    @testcase(93)
>      def test_bitbakelayers_showappends(self):
>          result = runCmd('bitbake-layers show_appends')
>          self.assertTrue('xcursor-transparent-theme_0.1.1.bbappend' in result.output, msg='xcursor-transparent-theme_0.1.1.bbappend file was not recognised')
>
> +    @testcase(90)
>      def test_bitbakelayers_showoverlayed(self):
>          result = runCmd('bitbake-layers show_overlayed')
>          self.assertTrue('aspell' in result.output, msg='xcursor-transparent-theme_0.1.1.bbappend file was not recognised')
>
> +    @testcase(95)
>      def test_bitbakelayers_flatten(self):
>          self.assertFalse(os.path.isdir(os.path.join(self.builddir, 'test')))
>          result = runCmd('bitbake-layers flatten test')
> diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py
> index b99da8d..a0d94e6 100644
> --- a/meta/lib/oeqa/utils/decorators.py
> +++ b/meta/lib/oeqa/utils/decorators.py
> @@ -7,6 +7,8 @@
>  # creating dependecies between two test methods.
>
>  from oeqa.oetest import *
> +import logging
> +import sys
>
>  class skipIfFailure(object):
>
> @@ -48,3 +50,67 @@ class skipUnlessPassed(object):
>              return f(*args)
>          wrapped_f.__name__ = f.__name__
>          return wrapped_f
> +
> +class testcase(object):
> +
> +    def __init__(self, test_case):
> +        self.test_case = test_case
> +
> +    def __call__(self, func):
> +       def wrapped_f(*args):
> +               return func(*args)
> +       wrapped_f.test_case = self.test_case
> +       return wrapped_f
> +
> +def LogResults(original_class):
> +    orig_method = original_class.run
> +
> +    #rewrite the run method of unittest.TestCase to add testcase logging
> +    def run(self, result, *args, **kws):
> +        orig_method(self, result, *args, **kws)
> +       passed = True
> +       testMethod = getattr(self, self._testMethodName)
> +
> +       #if test case is decorated then use it's number, else use it's name
> +       try:
> +               test_case = testMethod.test_case
> +       except AttributeError:
> +               test_case = self._testMethodName
> +
> +       #create custom logging level for filtering.
> +       custom_log_level = 100
> +       logging.addLevelName(custom_log_level, 'RESULTS')
> +       caller = os.path.basename(sys.argv[0])
> +
> +       def results(self, message, *args, **kws):
> +           if self.isEnabledFor(custom_log_level):
> +               self.log(custom_log_level, message, *args, **kws)
> +       logging.Logger.results = results
> +
> +       logging.basicConfig(filename=os.path.join(os.getcwd(),'results-'+caller+'.log'),
> +                            filemode='w',
> +                            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
> +                            datefmt='%H:%M:%S',
> +                            level=custom_log_level)
> +       local_log = logging.getLogger(caller)
> +
> +       #check status of tests and record it
> +        for (name, msg) in result.errors:
> +                if self._testMethodName == str(name).split(' ')[0]:
> +                       local_log.results("Testcase "+str(test_case)+": ERROR")
> +                       local_log.results("Testcase "+str(test_case)+":\n"+msg)
> +                       passed = False
> +        for (name, msg) in result.failures:
> +                if self._testMethodName == str(name).split(' ')[0]:
> +                       local_log.results("Testcase "+str(test_case)+": FAILED")
> +                       local_log.results("Testcase "+str(test_case)+":\n"+msg)
> +                       passed = False
> +        for (name, msg) in result.skipped:
> +                if self._testMethodName == str(name).split(' ')[0]:
> +                       local_log.results("Testcase "+str(test_case)+": SKIPPED")
> +                       passed = False
> +       if passed:
> +                       local_log.results("Testcase "+str(test_case)+": PASSED")
> +
> +    original_class.run = run
> +    return original_class
> --
> 1.9.1
>
> --
> _______________________________________________
> Openembedded-core mailing list
> Openembedded-core@lists.openembedded.org
> http://lists.openembedded.org/mailman/listinfo/openembedded-core