Revision: 2560
Author: jprantan
Date: Fri Feb 26 04:39:46 2010
Log: refactored to use the same rule engine which is used with include and exclude
http://code.google.com/p/robotframework/source/detail?r=2560

Modified:
 /trunk/src/robot/common/statistics.py
 /trunk/utest/common/test_statistics.py

=======================================
--- /trunk/src/robot/common/statistics.py       Fri Aug 14 04:43:06 2009
+++ /trunk/src/robot/common/statistics.py       Fri Feb 26 04:39:46 2010
@@ -28,7 +28,7 @@
         self.suite = SuiteStatistics(suite, self.tags, suite_stat_level)
         self.total = TotalStatistics(self.suite)
         self.tags.sort()
-
+
     def serialize(self, serializer):
         serializer.start_statistics(self)
         self.total.serialize(serializer)
@@ -177,40 +177,43 @@


 class TagStatistics:
-
-    def __init__(self, include=None, exclude=None, combine=None, docs=None,
-                 links=None):
+
+    def __init__(self, include=None, exclude=None, tag_stat_combine=None,
+                 docs=None, links=None):
         self.stats = utils.NormalizedDict()
         self._include = utils.to_list(include)
         self._exclude = utils.to_list(exclude)
-        self._combine_and, self._combine_not = self._get_combine(combine)
+ self._patterns_and_names = self._get_patterns_and_names(tag_stat_combine) self._taginfo = TagStatInfo(utils.to_list(docs), utils.to_list(links))

-    def _get_combine(self, combine):
-        ands = []
-        nots = []
-        if combine is None or combine == []:
-            return ands, nots
-        for tags in combine:
-            tags, name = self._split_tag_stat_combine_option(tags)
-            if 'NOT' in tags:
-                parts = [ utils.normalize(t) for t in tags.split('NOT') ]
-                if '' not in parts:
-                    nots.append((parts, name))
-            else:
-                parts = [ tag for tag in utils.normalize(tags).split('&')
-                          if tag != '' ]
-                if parts != []:
-                    ands.append((parts, name))
-        return ands, nots
-
-    def _split_tag_stat_combine_option(self, tags):
-        if ':' in tags:
-            index = tags.rfind(':')
-            return tags[:index], utils.printable_name(tags[index+1:], True)
-        return tags, None
+    def _get_patterns_and_names(self, tag_stat_combine_options):
+        if not tag_stat_combine_options:
+            return []
+        return [ self._parse_name_and_pattern_from(option) \
+                 for option in tag_stat_combine_options ]
+
+    def _parse_name_and_pattern_from(self, option):
+        pattern, name = self._split_pattern_and_name(option)
+        name = self._get_printable_name(pattern, name)
+        return pattern, name
+
+    def _split_pattern_and_name(self, pattern):
+        option_separator = ':'
+        if not option_separator in pattern:
+            return pattern, pattern
+        index = pattern.rfind(option_separator)
+        return pattern[:index], pattern[index+1:]
+
+    def _get_printable_name(self, pattern, name):
+        if pattern != name:
+            name = utils.printable_name(name, True)
+        return name.replace('&', ' & ').replace('NOT', ' NOT ')

     def add_test(self, test, critical):
+        self._add_tags_statistics(test, critical)
+        self._add_tagstatcombine_statistics(test)
+
+    def _add_tags_statistics(self, test, critical):
         for tag in test.tags:
             if not self._is_included(tag):
                 continue
@@ -219,39 +222,19 @@
                                           critical.is_non_critical(tag),
                                           self._taginfo)
             self.stats[tag].add_test(test)
-        self._add_test_to_combined(test, self._combine_and, ' & ',
-                                   self._is_combined_with_and)
-        self._add_test_to_combined(test, self._combine_not, ' NOT ',
-                                   self._is_combined_with_not)
-
- def _add_test_to_combined(self, test, combined_tags, joiner, is_combined):
-        for tags, name in combined_tags:
-            if name is None:
-                name = joiner.join(tags)
-            if not self.stats.has_key(name):
-                self.stats[name] = CombinedTagStat(name)
-            if is_combined(tags, test.tags):
-                self.stats[name].add_test(test)
-
-    def _is_combined_with_and(self, comb_tags, test_tags):
-        for c_tag in comb_tags:
-            if not utils.any_matches(test_tags, c_tag):
-                return False
-        return True
-
-    def _is_combined_with_not(self, comb_tags, test_tags):
-        if not utils.any_matches(test_tags, comb_tags[0]):
-            return False
-        for not_tag in comb_tags[1:]:
-            if utils.any_matches(test_tags, not_tag):
-                return False
-        return True
-
+
     def _is_included(self, tag):
if self._include != [] and not utils.matches_any(tag, self._include):
             return False
         return not utils.matches_any(tag, self._exclude)
-
+
+    def _add_tagstatcombine_statistics(self, test):
+        for pattern, name in self._patterns_and_names:
+            if not self.stats.has_key(name):
+                self.stats[name] = CombinedTagStat(name)
+            if test.is_included([pattern], []):
+                self.stats[name].add_test(test)
+
     def serialize(self, serializer):
         if not self.stats and (self._include or self._exclude):
             return
=======================================
--- /trunk/utest/common/test_statistics.py      Fri Jun 26 00:21:58 2009
+++ /trunk/utest/common/test_statistics.py      Fri Feb 26 04:39:46 2010
@@ -4,7 +4,7 @@
 from robot import utils
 from robot.utils.asserts import *
 from robot.common.statistics import *
-from robot.common.model import _Critical
+from robot.common.model import _Critical, BaseTestCase
 from robot.errors import DataError


@@ -40,11 +40,13 @@
         return test


-class TestMock:
+class TestMock(BaseTestCase):
+
     def __init__(self, status='PASS', tags=None, critical=True):
         self.status = status
         self.tags = tags is not None and tags or []
         self.critical = critical and 'yes' or 'no'
+        self.name = ''


 def verify_stat(stat, name, passed, failed, critical=None, non_crit=None):
@@ -190,105 +192,65 @@
             keys.sort()
             assert_equal(keys, exp, "Incls: %s, Excls: %s" % (incl, excl))

-    def test_set_combine_and(self):
-        for inp, exp in [ ( ['t'], [(['t'], None)] ),
-                          ( ['not*'], [(['not*'], None)] ),
- ( ['T1','T2'], [(['t1'], None), (['t2'], None)] ),
-                          ( ['t1&t2&t3'], [(['t1', 't2', 't3'], None)] ),
-                          ( ['','&','&a&'], [(['a'], None)] ),
-                          ( ['T 1  &  T 2','3&2&1&A','UP'],
-                            [(['t1', 't2'], None),
-                             (['3', '2', '1', 'a'], None),
-                             (['up'], None)] ) ]:
-            assert_equals(TagStatistics([], [], inp)._combine_and, exp)
-            assert_equals(TagStatistics([], [], inp)._combine_not, [])
-
-    def test_set_combine_not(self):
-        for inp, exp, in [ ( ['t1NOTt2'],
-                             [(['t1', 't2'], None)] ),
-                           ( ['t1NOTT2NOTx*'],
-                             [(['t1','t2','x*'], None)] ),
-                           ( ['notNOTNOtt'],
-                             [(['not','nott'], None)] ),
-                           ( ['t1NOTt2','3NOT4','5NOT6NOT7NOT8'],
-                             [(['t1','t2'], None),
-                              (['3','4'], None),
-                              (['5','6','7','8'], None)] ) ]:
-            assert_equals(TagStatistics([], [], inp)._combine_not, exp)
-            assert_equals(TagStatistics([], [], inp)._combine_and, [])
-        for invalid in [ 'NOT', 'NOTNOT', 'xNOTNOTy', 'NOTa', 'bNOT',
-                         'NOTaNOTb', 'aNOTbNOT' ]:
- assert_equals(TagStatistics([], [], [invalid])._combine_not, []) - assert_equals(TagStatistics([], [], [invalid])._combine_and, [])
-
-    def test_set_combine_and_not_together(self):
-        for inp, exp_and, exp_not in [
-                ( [], [], [] ),
-                ( ['t1&t2', 't1NOTt3'],
-                  [(['t1', 't2'], None)],
-                  [(['t1', 't3'], None)] ),
-                ( ['1&2','3*','4NOT5'],
-                  [(['1', '2'], None), (['3*'], None)],
-                  [(['4', '5'], None)] ),
-                ( ['7NOT8','1&2&3','4NOT5NOT6'],
-                  [(['1', '2', '3'], None)],
-                  [(['7', '8'], None), (['4', '5', '6'], None)] ) ]:
-            assert_equals(TagStatistics([], [], inp)._combine_and, exp_and)
-            assert_equals(TagStatistics([], [], inp)._combine_not, exp_not)
-
-    def test_set_combine_and_give_name(self):
-        for inp, exp_and, exp_not in [
-                ( [], [], [] ),
-                ( ['t1&t2:my_name','t1NOTt3:others'],
-                  [(['t1', 't2'], 'My Name')],
-                  [(['t1', 't3'], 'Others')] ),
-                ( ['1:2&2:3:name','3*','4NOT5:some new name'],
-                  [(['1:2', '2:3'], 'Name'), (['3*'], None)],
-                  [(['4', '5'], 'Some New Name')] ) ]:
-            assert_equals(TagStatistics([], [], inp)._combine_and, exp_and)
-            assert_equals(TagStatistics([], [], inp)._combine_not, exp_not)
-
-
-    def test_is_combined_with_and(self):
+    def test_combine_with_name(self):
+        for comb_tags, expected_name in [
+                ( [], '' ),
+                ( ['t1&t2:my_name'], 'My Name' ),
+                ( ['t1NOTt3:others'], 'Others' ),
+                ( ['1:2&2:3:name'], 'Name' ),
+                ( ['3*'], '3*' ),
+                ( ['4NOT5:some new name'], 'Some New Name' )]:
+            stats = TagStatistics(tag_stat_combine=comb_tags)
+            test = TestMock()
+            stats._add_tagstatcombine_statistics(test)
+            assert_equals(len(stats.stats), expected_name != '')
+            if expected_name:
+ assert_equals(stats.stats[expected_name].name, expected_name)
+
+    def test_is_combined_with_and_statements(self):
+        for comb_tags, test_tags, expected_count in [
+                (['t1'], ['t1'], 1),
+                (['t1'], ['t2'], 0),
+                (['t1&t2'], ['t1'], 0),
+                (['t1&t2'], ['t1','t2'], 1),
+                (['t1&t2'], ['T1','t 2','t3'], 1),
+                (['t*'], ['s','t','u'], 1),
+                (['t*'], ['s','tee','t'], 1),
+                (['t*&s'], ['s','tee','t'], 1),
+                (['t*&s&non'], ['s','tee','t'], 0)
+                ]:
+ self._test_combined_statistics(comb_tags, test_tags, expected_count)
+
+ def _test_combined_statistics(self, comb_tags, test_tags, expected_count): + stats = TagStatistics(tag_stat_combine=['%s:name' % rule for rule in comb_tags])
+            test = TestMock(tags=test_tags)
+            stats._add_tagstatcombine_statistics(test)
+            assert_equals(len(stats.stats['Name'].tests), expected_count,
+                          'comb: %s, test: %s' % (comb_tags, test_tags))
+
+    def test_is_combined_with_not_statements(self):
         stats = TagStatistics()
-        for comb_tags, test_tags, exp in [
-                (['t1'], ['t1'], True),
-                (['t1'], ['t2'], False),
-                (['t1','t2'], ['t1'], False),
-                (['t1','t2'], ['t1','t2'], True),
-                (['t1','t2'], ['T1','t 2','t3'], True),
-                (['t*'], ['s','t','u'], True),
-                (['t*'], ['s','tee','t'], True),
-                (['t*','s'], ['s','tee','t'], True),
-                (['t*','s','non'], ['s','tee','t'], False)
+        for comb_tags, test_tags, expected_count in [
+                ( ['t1NOTt2'], [], 0 ),
+                ( ['t1NOTt2'], ['t1'], 1 ),
+                ( ['t1NOTt2'], ['t1','t2'], 0 ),
+                ( ['t1NOTt2'], ['t3'], 0 ),
+                ( ['t1NOTt2'], ['t3','t2'], 0 ),
+                ( ['t*NOTt2'], ['t1'], 1 ),
+                ( ['t*NOTt2'], ['t'], 1 ),
+                ( ['t*NOTt2'], ['TEE'], 1 ),
+                ( ['t*NOTt2'], ['T2'], 0 ),
+                ( ['T*NOTT?'], ['t'], 1 ),
+                ( ['T*NOTT?'], ['tt'], 0 ),
+                ( ['T*NOTT?'], ['ttt'], 1 ),
+                ( ['T*NOTT?'], ['tt','t'], 0 ),
+                ( ['T*NOTT?'], ['ttt','something'], 1 ),
+                ( ['tNOTs*NOTr'], ['t'], 1 ),
+                ( ['tNOTs*NOTr'], ['t','s'], 0 ),
+                ( ['tNOTs*NOTr'], ['R','T'], 0 ),
+                ( ['tNOTs*NOTr'], ['R','T','s'], 0 ),
                 ]:
- assert_equals(stats._is_combined_with_and(comb_tags, test_tags), exp,
-                          'comb: %s, test: %s' % (comb_tags, test_tags))
-
-    def test_is_combined_with_not(self):
-        stats = TagStatistics()
-        for comb_tags, test_tags, exp in [
-                ( ['t1','t2'], [], False ),
-                ( ['t1','t2'], ['t1'], True ),
-                ( ['t1','t2'], ['t1','t2'], False ),
-                ( ['t1','t2'], ['t3'], False ),
-                ( ['t1','t2'], ['t3','t2'], False ),
-                ( ['t*','t2'], ['t1'], True ),
-                ( ['t*','t2'], ['t'], True ),
-                ( ['t*','t2'], ['TEE'], True ),
-                ( ['t*','t2'], ['T2'], False ),
-                ( ['T*','T?'], ['t'], True ),
-                ( ['T*','T?'], ['tt'], False ),
-                ( ['T*','T?'], ['ttt'], True ),
-                ( ['T*','T?'], ['tt','t'], False ),
-                ( ['T*','T?'], ['ttt','something'], True ),
-                ( ['t','s*','r'], ['t'], True ),
-                ( ['t','s*','r'], ['t','s'], False ),
-                ( ['t','s*','r'], ['R','T'], False ),
-                ( ['t','s*','r'], ['R','T','s'], False ),
-                ]:
- assert_equals(stats._is_combined_with_not(comb_tags, test_tags), exp,
-                          'comb: %s, test: %s' % (comb_tags, test_tags))
+ self._test_combined_statistics(comb_tags, test_tags, expected_count)

     def test_combine(self):
         # This test is more like an acceptance test than a unit test and
@@ -301,7 +263,7 @@
( ['t?&s'], [2], [['t1','s'],['tt','s','u'],['tee','s'],['s']], [] ), ( ['t*&s','*'], [2,3], [['s','t','u'],['tee','s'],[],['x']], [] ),
                 ( ['tNOTs'], [1], [['t','u'],['t','s']], [] ),
-                ( ['tNOTs','t&s','tNOTsNOTu'], [3,2,2],
+                ( ['tNOTs','t&s','tNOTsNOTu', 't&sNOTu'], [3,2,2,1],
[['t','u'],['t','s'],['s','t','u'],['t'],['t','v']], ['t'] ),
                 ( ['nonex'], [0], [['t1'],['t1,t2'],[]], [] )
                 ]:
@@ -339,6 +301,7 @@
         suite.critical_tags = ['smoke']
         statistics = Statistics(suite, -1, ['t*','smoke'], ['t3'],
                                 ['t1&t2','t?&smoke','t1NOTt2','none&t1'])
+        #TODO: Demeter
         stats = statistics.tags.stats.values()
         stats.sort()
         expected = [ ('smoke', 4), ('none & t1', 0), ('t1 & t2', 3),
@@ -347,6 +310,7 @@
         exp_names = [ name for name, count in expected ]
         assert_equals(names, exp_names)
         for name, count in expected:
+            #TODO: Demeter
assert_equals(len(statistics.tags.stats[name].tests), count, name)


Reply via email to