2 new revisions:

Revision: eb8a34757e89
Author:   Pekka Klärck
Date:     Thu Nov 17 13:48:07 2011
Log:      Final suite and tag statistics cleanup
http://code.google.com/p/robotframework/source/detail?r=eb8a34757e89

Revision: 4a2bb1ab18fb
Author:   Pekka Klärck
Date:     Thu Nov 17 14:33:17 2011
Log:      separated tag stat tests to their own module
http://code.google.com/p/robotframework/source/detail?r=4a2bb1ab18fb

==============================================================================
Revision: eb8a34757e89
Author:   Pekka Klärck
Date:     Thu Nov 17 13:48:07 2011
Log:      Final suite and tag statistics cleanup
http://code.google.com/p/robotframework/source/detail?r=eb8a34757e89

Modified:
 /src/robot/model/suitestatistics.py
 /src/robot/model/tagstatistics.py
 /utest/model/test_statistics.py

=======================================
--- /src/robot/model/suitestatistics.py Thu Nov 17 12:53:04 2011
+++ /src/robot/model/suitestatistics.py Thu Nov 17 13:48:07 2011
@@ -46,7 +46,7 @@
 class SuiteStatisticsBuilder(object):

     def __init__(self, suite_stat_level):
-        self._stat_level = suite_stat_level
+        self._suite_stat_level = suite_stat_level
         self._stats_stack = []
         self.root = None

@@ -68,10 +68,10 @@
             self.current.add_child_stats(stats, self._is_child_included())

     def _is_child_included(self):
-        return self._include_all_levels() or self._level_below_threshold()
+        return self._include_all_levels() or self._below_threshold()

     def _include_all_levels(self):
-        return self._stat_level == -1
-
-    def _level_below_threshold(self):
-        return len(self._stats_stack) < self._stat_level
+        return self._suite_stat_level == -1
+
+    def _below_threshold(self):
+        return len(self._stats_stack) < self._suite_stat_level
=======================================
--- /src/robot/model/tagstatistics.py   Thu Nov 17 13:39:51 2011
+++ /src/robot/model/tagstatistics.py   Thu Nov 17 13:48:07 2011
@@ -37,13 +37,12 @@

 class TagStatisticsBuilder(object):

- def __init__(self, criticality, include=None, exclude=None, combine=None, + def __init__(self, criticality, included=None, excluded=None, combined=None,
                  docs=None, links=None):
-        # TODO: Check argument names
-        self._include = TagPatterns(include)
-        self._exclude = TagPatterns(exclude)
+        self._included = TagPatterns(included)
+        self._excluded = TagPatterns(excluded)
         self._info = TagStatInfo(criticality, docs, links)
-        self.stats = TagStatistics(self._info.get_combined_stats(combine))
+        self.stats = TagStatistics(self._info.get_combined_stats(combined))

     def add_test(self, test):
         self._add_tags_to_statistics(test)
@@ -57,9 +56,9 @@
                 self.stats.tags[tag].add_test(test)

     def _is_included(self, tag):
-        if self._include and not self._include.match(tag):
+        if self._included and not self._included.match(tag):
             return False
-        return not self._exclude.match(tag)
+        return not self._excluded.match(tag)

     def _add_to_combined_statistics(self, test):
         for comb in self.stats.combined:
@@ -75,7 +74,7 @@
         self._links = [TagStatLink(*link) for link in links or []]

     def get_stat(self, tag):
-        return TagStat(tag, self._get_doc(tag), self._get_links(tag),
+        return TagStat(tag, self.get_doc(tag), self.get_links(tag),
                        self._criticality.tag_is_critical(tag),
                        self._criticality.tag_is_non_critical(tag))

@@ -84,13 +83,13 @@

     def get_combined_stat(self, pattern, name=None):
         name = name or pattern
-        return CombinedTagStat(pattern, name, self._get_doc(name),
-                               self._get_links(name))
-
-    def _get_doc(self, tag):
+        return CombinedTagStat(pattern, name, self.get_doc(name),
+                               self.get_links(name))
+
+    def get_doc(self, tag):
         return ' & '.join(doc.text for doc in self._docs if doc.match(tag))

-    def _get_links(self, tag):
+    def get_links(self, tag):
return [link.get_link(tag) for link in self._links if link.match(tag)]


=======================================
--- /utest/model/test_statistics.py     Thu Nov 17 13:39:51 2011
+++ /utest/model/test_statistics.py     Thu Nov 17 13:48:07 2011
@@ -169,7 +169,7 @@
         assert_equals(len(builder.stats), 2)

     def test_len_with_combine(self):
- builder = TagStatisticsBuilder(Criticality(), combine=[('x*', 'title')]) + builder = TagStatisticsBuilder(Criticality(), combined=[('x*', 'title')])
         assert_equals(len(builder.stats), 1)
         builder.add_test(TestCase(tags=['xxx', 'yyy']))
         assert_equals(len(builder.stats), 3)
@@ -183,7 +183,7 @@
                 ([('3*', '')], '3*' ),
                 ([('4NOT5', 'Some new name')], 'Some new name')
                ]:
- builder = TagStatisticsBuilder(Criticality(), combine=comb_tags) + builder = TagStatisticsBuilder(Criticality(), combined=comb_tags)
             assert_equals(bool(builder.stats), expected_name != '')
             if expected_name:
assert_equals([s.name for s in builder.stats], [expected_name])
@@ -203,7 +203,7 @@
self._verify_combined_statistics(comb_tags, test_tags, expected_count)

def _verify_combined_statistics(self, comb_tags, test_tags, expected_count): - builder = TagStatisticsBuilder(Criticality(), combine=[(comb_tags, 'name')]) + builder = TagStatisticsBuilder(Criticality(), combined=[(comb_tags, 'name')])
         builder._add_to_combined_statistics(TestCase(tags=test_tags))
assert_equals([s.total for s in builder.stats if s.combined], [expected_count])

@@ -231,7 +231,7 @@
self._verify_combined_statistics(comb_tags, test_tags, expected_count)

     def test_combine_with_same_name_as_existing_tag(self):
- builder = TagStatisticsBuilder(Criticality(), combine=[('x*', 'name')]) + builder = TagStatisticsBuilder(Criticality(), combined=[('x*', 'name')])
         builder.add_test(TestCase(tags=['name', 'another']))
         assert_equals([(s.name, s.combined) for s in builder.stats],
                       [('name', 'x*'), ('another', ''), ('name', '')])
@@ -252,7 +252,7 @@
                ]:
             # 1) Create tag stats
             builder = TagStatisticsBuilder(Criticality(crit_tags),
- combine=[(t, '') for t in comb_tags]) + combined=[(t, '') for t in comb_tags])
             all_tags = []
             for tags in tests_tags:
                 builder.add_test(TestCase(status='PASS', tags=tags),)
@@ -272,7 +272,7 @@

     def test_sorting(self):
         builder = TagStatisticsBuilder(Criticality(['c2', 'c1'], ['n*']),
- combine=[('c*', ''), ('xxx', 'a title')]) + combined=[('c*', ''), ('xxx', 'a title')])
         builder.add_test(TestCase(tags=['c1', 'c2', 't1']))
         builder.add_test(TestCase(tags=['c1', 'n2', 't2']))
         builder.add_test(TestCase(tags=['n1', 'n2', 't1', 't3']))

==============================================================================
Revision: 4a2bb1ab18fb
Author:   Pekka Klärck
Date:     Thu Nov 17 14:33:17 2011
Log:      separated tag stat tests to their own module
http://code.google.com/p/robotframework/source/detail?r=4a2bb1ab18fb

Added:
 /utest/model/test_tagstatistics.py
Modified:
 /utest/model/test_statistics.py

=======================================
--- /dev/null
+++ /utest/model/test_tagstatistics.py  Thu Nov 17 14:33:17 2011
@@ -0,0 +1,256 @@
+import unittest
+
+from robot.model import Criticality
+from robot.utils.asserts import assert_equals, assert_none
+from robot.model.statistics import Statistics
+from robot.model.tagstatistics import TagStatisticsBuilder, TagStatLink
+from robot.result import TestSuite, TestCase
+from robot import utils
+
+
+class TestTagStatistics(unittest.TestCase):
+    _incl_excl_data = [([], []),
+                       ([], ['t1','t2']),
+                       (['t1'], ['t1','t2']),
+                       (['t1','t2'], ['t1','t2','t3','t4']),
+                       (['UP'], ['t1','t2','up']),
+                       (['not','not2'], ['t1','t2','t3']),
+                       (['t*'], ['t1','s1','t2','t3','s2','s3']),
+                       (['T*','r'], ['t1','t2','r','teeeeeeee']),
+                       (['*'], ['t1','t2','s1','tag']),
+ (['t1','t2','t3','not'], ['t1','t2','t3','t4','s1','s2'])]
+
+    def test_include(self):
+        for incl, tags in self._incl_excl_data:
+            builder = TagStatisticsBuilder(Criticality(), incl, [])
+            builder.add_test(TestCase(status='PASS', tags=tags))
+            expected = [tag for tag in tags
+ if incl == [] or any(utils.matches(tag, i) for i in incl)] + assert_equals([s.name for s in builder.stats], sorted(expected))
+
+    def test_exclude(self):
+        for excl, tags in self._incl_excl_data:
+            builder = TagStatisticsBuilder(Criticality(), [], excl)
+            builder.add_test(TestCase(status='PASS', tags=tags))
+            expected = [tag for tag in tags
+                        if not any(utils.matches(tag, e) for e in excl)]
+ assert_equals([s.name for s in builder.stats], sorted(expected))
+
+    def test_include_and_exclude(self):
+        for incl, excl, tags, exp in [
+               ([], [], ['t0','t1','t2'], ['t0','t1','t2']),
+               (['t1'], ['t2'], ['t0','t1','t2'], ['t1']),
+               (['t?'], ['t2'], ['t0','t1','t2','x'], ['t0','t1']),
+               (['t?'], ['*2'], ['t0','t1','t2','x2'], ['t0','t1']),
+               (['t1','t2'], ['t2'], ['t0','t1','t2'], ['t1']),
+               (['t1','t2','t3','not'], ['t2','t0'],
+                ['t0','t1','t2','t3','x'], ['t1','t3'] )
+              ]:
+            builder = TagStatisticsBuilder(Criticality(), incl, excl)
+            builder.add_test(TestCase(status='PASS', tags=tags))
+            assert_equals([s.name for s in builder.stats], exp),
+
+    def test_len(self):
+        builder = TagStatisticsBuilder(Criticality())
+        assert_equals(len(builder.stats), 0)
+        builder.add_test(TestCase())
+        assert_equals(len(builder.stats), 0)
+        builder.add_test(TestCase(tags=['a']))
+        assert_equals(len(builder.stats), 1)
+        builder.add_test(TestCase(tags=['A', 'B']))
+        assert_equals(len(builder.stats), 2)
+
+    def test_len_with_combine(self):
+ builder = TagStatisticsBuilder(Criticality(), combined=[('x*', 'title')])
+        assert_equals(len(builder.stats), 1)
+        builder.add_test(TestCase(tags=['xxx', 'yyy']))
+        assert_equals(len(builder.stats), 3)
+
+    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')
+               ]:
+ builder = TagStatisticsBuilder(Criticality(), combined=comb_tags)
+            assert_equals(bool(builder.stats), expected_name != '')
+            if expected_name:
+ assert_equals([s.name for s in builder.stats], [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._verify_combined_statistics(comb_tags, test_tags, expected_count)
+
+ def _verify_combined_statistics(self, comb_tags, test_tags, expected_count): + builder = TagStatisticsBuilder(Criticality(), combined=[(comb_tags, 'name')])
+        builder._add_to_combined_statistics(TestCase(tags=test_tags))
+ assert_equals([s.total for s in builder.stats if s.combined], [expected_count])
+
+    def test_is_combined_with_not_statements(self):
+        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', ['S','T'], 0),
+                ('tNOTs*NOTr', ['R','T','s'], 1),
+               ]:
+ self._verify_combined_statistics(comb_tags, test_tags, expected_count)
+
+    def test_combine_with_same_name_as_existing_tag(self):
+ builder = TagStatisticsBuilder(Criticality(), combined=[('x*', 'name')])
+        builder.add_test(TestCase(tags=['name', 'another']))
+        assert_equals([(s.name, s.combined) for s in builder.stats],
+                      [('name', 'x*'), ('another', ''), ('name', '')])
+
+    def test_combine(self):
+        # This is more like an acceptance test than a unit test ...
+        for comb_tags, tests_tags, crit_tags in [
+                (['t1&t2'], [['t1','t2','t3'],['t1','t3']], []),
+                (['1&2&3'], [['1','2','3'],['1','2','3','4']], ['1','2']),
+                (['1&2','1&3'], [['1','2','3'],['1','3'],['1']], ['1']),
+                (['t*'], [['t1','x','y'],['tee','z'],['t']], ['x']),
+ (['t?&s'], [['t1','s'],['tt','s','u'],['tee','s'],['s']], []),
+                (['t*&s','*'], [['s','t','u'],['tee','s'],[],['x']], []),
+                (['tNOTs'], [['t','u'],['t','s']], []),
+                (['tNOTs','t&s','tNOTsNOTu', 't&sNOTu'],
+ [['t','u'],['t','s'],['s','t','u'],['t'],['t','v']], ['t']),
+                (['nonex'], [['t1'],['t1,t2'],[]], [])
+               ]:
+            # 1) Create tag stats
+            builder = TagStatisticsBuilder(Criticality(crit_tags),
+ combined=[(t, '') for t in comb_tags])
+            all_tags = []
+            for tags in tests_tags:
+                builder.add_test(TestCase(status='PASS', tags=tags),)
+                all_tags.extend(tags)
+            # 2) Actual values
+            names = [stat.name for stat in builder.stats]
+            # 3) Expected values
+            exp_crit = []; exp_noncr = []
+            for tag in utils.normalize_tags(all_tags):
+                if tag in crit_tags:
+                    exp_crit.append(tag)
+                else:
+                    exp_noncr.append(tag)
+            exp_names = exp_crit + sorted(comb_tags) + exp_noncr
+            # 4) Verify names (match counts were already verified)
+            assert_equals(names, exp_names)
+
+    def test_sorting(self):
+        builder = TagStatisticsBuilder(Criticality(['c2', 'c1'], ['n*']),
+ combined=[('c*', ''), ('xxx', 'a title')])
+        builder.add_test(TestCase(tags=['c1', 'c2', 't1']))
+        builder.add_test(TestCase(tags=['c1', 'n2', 't2']))
+        builder.add_test(TestCase(tags=['n1', 'n2', 't1', 't3']))
+        assert_equals([(s.name, s.info, s.total) for s in builder.stats],
+                       [('c1', 'critical', 2), ('c2', 'critical', 1),
+ ('n1', 'non-critical', 1), ('n2', 'non-critical', 2),
+                        ('a title', 'combined', 0), ('c*', 'combined', 2),
+                        ('t1', '', 2), ('t2', '', 1), ('t3', '', 1)])
+
+
+class TestTagStatLink(unittest.TestCase):
+
+    def test_valid_string_is_parsed_correctly(self):
+        for arg, exp in [(('Tag', 'bar/foo.html', 'foobar'),
+                          ('^Tag$', 'bar/foo.html', 'foobar')),
+                         (('hello', 'gopher://hello.world:8090/hello.html',
+                           'Hello World'),
+ ('^hello$', 'gopher://hello.world:8090/hello.html',
+                           'Hello World'))]:
+            link = TagStatLink(*arg)
+            assert_equals(exp[0], link._regexp.pattern)
+            assert_equals(exp[1], link._link)
+            assert_equals(exp[2], link._title)
+
+    def test_valid_string_containing_patterns_is_parsed_correctly(self):
+        for arg, exp_pattern in [('*', '^(.*)$'), ('f*r', '^f(.*)r$'),
+                                 ('*a*', '^(.*)a(.*)$'),  ('?', '^(.)$'),
+ ('??', '^(..)$'), ('f???ar', '^f(...)ar$'),
+                                 ('F*B?R*?', '^F(.*)B(.)R(.*)(.)$')]:
+            link = TagStatLink(arg, 'some_url', 'some_title')
+            assert_equals(exp_pattern, link._regexp.pattern)
+
+    def test_underscores_in_title_are_converted_to_spaces(self):
+        link = TagStatLink('', '', 'my_name')
+        assert_equals(link._title, 'my name')
+
+    def test_get_link_returns_correct_link_when_matches(self):
+        for arg, exp in [(('smoke', 'http://tobacco.com', 'Lung_cancer'),
+                          ('http://tobacco.com', 'Lung cancer')),
+                         (('tag', 'ftp://foo:809/bar.zap', 'Foo_in a Bar'),
+                          ('ftp://foo:809/bar.zap', 'Foo in a Bar'))]:
+            link = TagStatLink(*arg)
+            assert_equals(exp, link.get_link(arg[0]))
+
+    def test_get_link_returns_none_when_no_match(self):
+        link = TagStatLink('smoke', 'http://tobacco.com', 'Lung cancer')
+        for tag in ['foo', 'b a r', 's moke']:
+            assert_none(link.get_link(tag))
+
+    def test_pattern_matches_case_insensitively(self):
+        exp = 'http://tobacco.com', 'Lung cancer'
+        link = TagStatLink('smoke', *exp)
+        for tag in ['Smoke', 'SMOKE', 'smoke']:
+            assert_equals(exp, link.get_link(tag))
+
+    def test_pattern_matches_when_spaces(self):
+        exp = 'http://tobacco.com', 'Lung cancer'
+        link = TagStatLink('smoking kills', *exp)
+        for tag in ['Smoking Kills', 'SMOKING KILLS']:
+            assert_equals(exp, link.get_link(tag))
+
+    def test_pattern_match(self):
+        link = TagStatLink('f?o*r', 'http://foo/bar.html', 'FooBar')
+        for tag in ['foobar', 'foor', 'f_ofoobarfoobar', 'fOoBAr']:
+ assert_equals(link.get_link(tag), ('http://foo/bar.html', 'FooBar'))
+
+    def test_pattern_substitution_with_one_match(self):
+        link = TagStatLink('tag-*', 'http://tracker/?id=%1', 'Tracker')
+        for id in ['1', '23', '456']:
+            exp = ('http://tracker/?id=%s' % id, 'Tracker')
+            assert_equals(exp, link.get_link('tag-%s' % id))
+
+    def test_pattern_substitution_with_multiple_matches(self):
+        link = TagStatLink('?-*', 'http://tracker/?id=%1-%2', 'Tracker')
+        for id1, id2 in [('1', '2'), ('3', '45'), ('f', 'bar')]:
+            exp = ('http://tracker/?id=%s-%s' % (id1, id2), 'Tracker')
+            assert_equals(exp, link.get_link('%s-%s' % (id1, id2)))
+
+    def test_pattern_substitution_with_multiple_substitutions(self):
+        link = TagStatLink('??-?-*', '%3-%3-%1-%2-%3', 'Tracker')
+ assert_equals(link.get_link('aa-b-XXX'), ('XXX-XXX-aa-b-XXX', 'Tracker'))
+
+    def test_matches_are_ignored_in_pattern_substitution(self):
+        link = TagStatLink('???-*-*-?', '%4-%2-%2-%4', 'Tracker')
+ assert_equals(link.get_link('AAA-XXX-ABC-B'), ('B-XXX-XXX-B', 'Tracker'))
+
+
+if __name__ == "__main__":
+    unittest.main()
=======================================
--- /utest/model/test_statistics.py     Thu Nov 17 13:48:07 2011
+++ /utest/model/test_statistics.py     Thu Nov 17 14:33:17 2011
@@ -1,11 +1,8 @@
 import unittest

-from robot.model import Criticality
-from robot.utils.asserts import assert_equals, assert_none
+from robot.utils.asserts import assert_equals, assert_true
 from robot.model.statistics import Statistics
-from robot.model.tagstatistics import TagStatisticsBuilder, TagStatLink
 from robot.result import TestSuite, TestCase
-from robot import utils


def verify_stat(stat, name, passed, failed, critical=None, non_crit=None, id=None):
@@ -25,7 +22,7 @@
         all_pass, all_fail = crit_pass, crit_fail
     verify_stat(suite.all, name, all_pass, all_fail, id=id)

-def generate_default_suite():
+def generate_suite():
     suite = TestSuite(name='Root Suite')
     suite.set_criticality(critical_tags=['smoke'])
     s1 = suite.suites.create(name='First Sub Suite')
@@ -65,7 +62,10 @@
 class TestStatisticsNotSoSimple(unittest.TestCase):

     def setUp(self):
-        self.statistics = Statistics(generate_default_suite())
+        suite = generate_suite()
+        suite.set_criticality(critical_tags=['smoke'])
+        self.statistics = Statistics(suite, 2, ['t*','smoke'], ['t3'],
+ [('t? & smoke', ''), ('none NOT t1', 'a title')])

     def test_total(self):
         verify_stat(self.statistics.total.all, 'All Tests', 4, 3)
@@ -78,296 +78,67 @@
         s1, s2 = suite.suites
         verify_suite(s1, 'Root Suite.First Sub Suite', 's1-s1', 2, 1, 4, 2)
verify_suite(s2, 'Root Suite.Second Sub Suite', 's1-s2', 0, 1, 0, 1)
-        assert_equals(len(s1.suites), 3)
-        s11, s12, s13 = s1.suites
- verify_suite(s11, 'Root Suite.First Sub Suite.Sub Suite 1_1', 's1-s1-s1', 0, 0, 1, 1) - verify_suite(s12, 'Root Suite.First Sub Suite.Sub Suite 1_2', 's1-s1-s2', 1, 1, 2, 1) - verify_suite(s13, 'Root Suite.First Sub Suite.Sub Suite 1_3', 's1-s1-s3', 1, 0, 1, 0)
-        assert_equals(len(s2.suites), 1)
-        s21 = s2.suites[0]
- verify_suite(s21, 'Root Suite.Second Sub Suite.Sub Suite 2_1', 's1-s2-s1', 0, 1, 0, 1)
+        assert_equals(len(s1.suites), 0)
+        assert_equals(len(s2.suites), 0)

     def test_tags(self):
+        # Tag stats are tested more thoroughly in their own suite.
         tags = self.statistics.tags
-        assert_equals(len(tags), 4)
-        names = [t.name for t in tags]
-        assert_equals(names, 'smoke t1 t2 t3'.split())
+        assert_equals(len(tags), 5)
         verify_stat(tags.tags['smoke'], 'smoke', 2, 2, True, False)
         verify_stat(tags.tags['t1'], 't1', 3, 2, False, False)
         verify_stat(tags.tags['t2'], 't2', 2, 1, False, False)
-        verify_stat(tags.tags['t3'], 't3', 0, 2, False, False)
+ expected = [('smoke', 4), ('a title', 0), ('t? & smoke', 4), ('t1', 5), ('t2', 3)]
+        assert_equals([(t.name, t.total) for t in tags], expected)


-class TestSuiteStatLevel(unittest.TestCase):
-
-    def test_only_root_level(self):
- suite = Statistics(generate_default_suite(), suite_stat_level=1).suite
+class TestSuiteStatistics(unittest.TestCase):
+
+    def test_all_levels(self):
+        suite = Statistics(generate_suite()).suite
         verify_suite(suite, 'Root Suite', 's1', 2, 2, 4, 3)
-        assert_equals(len(suite.suites), 0)
-
-    def test_stat_level(self):
- suite = Statistics(generate_default_suite(), suite_stat_level=2).suite
-        verify_suite(suite, 'Root Suite', 's1', 2, 2, 4, 3)
         assert_equals(len(suite.suites), 2)
         s1, s2 = suite.suites
         verify_suite(s1, 'Root Suite.First Sub Suite', 's1-s1', 2, 1, 4, 2)
verify_suite(s2, 'Root Suite.Second Sub Suite', 's1-s2', 0, 1, 0, 1)
-        assert_equals(len(s1.suites), 0)
-        assert_equals(len(s2.suites), 0)
-
-
-class TestTagStatistics(unittest.TestCase):
-    _incl_excl_data = [([], []),
-                       ([], ['t1','t2']),
-                       (['t1'], ['t1','t2']),
-                       (['t1','t2'], ['t1','t2','t3','t4']),
-                       (['UP'], ['t1','t2','up']),
-                       (['not','not2'], ['t1','t2','t3']),
-                       (['t*'], ['t1','s1','t2','t3','s2','s3']),
-                       (['T*','r'], ['t1','t2','r','teeeeeeee']),
-                       (['*'], ['t1','t2','s1','tag']),
- (['t1','t2','t3','not'], ['t1','t2','t3','t4','s1','s2'])]
-
-    def test_include(self):
-        for incl, tags in self._incl_excl_data:
-            builder = TagStatisticsBuilder(Criticality(), incl, [])
-            builder.add_test(TestCase(status='PASS', tags=tags))
-            expected = [tag for tag in tags
- if incl == [] or any(utils.matches(tag, i) for i in incl)] - assert_equals([s.name for s in builder.stats], sorted(expected))
-
-    def test_exclude(self):
-        for excl, tags in self._incl_excl_data:
-            builder = TagStatisticsBuilder(Criticality(), [], excl)
-            builder.add_test(TestCase(status='PASS', tags=tags))
-            expected = [tag for tag in tags
-                        if not any(utils.matches(tag, e) for e in excl)]
- assert_equals([s.name for s in builder.stats], sorted(expected))
-
-    def test_include_and_exclude(self):
-        for incl, excl, tags, exp in [
-               ([], [], ['t0','t1','t2'], ['t0','t1','t2']),
-               (['t1'], ['t2'], ['t0','t1','t2'], ['t1']),
-               (['t?'], ['t2'], ['t0','t1','t2','x'], ['t0','t1']),
-               (['t?'], ['*2'], ['t0','t1','t2','x2'], ['t0','t1']),
-               (['t1','t2'], ['t2'], ['t0','t1','t2'], ['t1']),
-               (['t1','t2','t3','not'], ['t2','t0'],
-                ['t0','t1','t2','t3','x'], ['t1','t3'] )
-              ]:
-            builder = TagStatisticsBuilder(Criticality(), incl, excl)
-            builder.add_test(TestCase(status='PASS', tags=tags))
-            assert_equals([s.name for s in builder.stats], exp),
-
-    def test_len(self):
-        builder = TagStatisticsBuilder(Criticality())
-        assert_equals(len(builder.stats), 0)
-        builder.add_test(TestCase())
-        assert_equals(len(builder.stats), 0)
-        builder.add_test(TestCase(tags=['a']))
-        assert_equals(len(builder.stats), 1)
-        builder.add_test(TestCase(tags=['A', 'B']))
-        assert_equals(len(builder.stats), 2)
-
-    def test_len_with_combine(self):
- builder = TagStatisticsBuilder(Criticality(), combined=[('x*', 'title')])
-        assert_equals(len(builder.stats), 1)
-        builder.add_test(TestCase(tags=['xxx', 'yyy']))
-        assert_equals(len(builder.stats), 3)
-
-    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')
-               ]:
- builder = TagStatisticsBuilder(Criticality(), combined=comb_tags)
-            assert_equals(bool(builder.stats), expected_name != '')
-            if expected_name:
- assert_equals([s.name for s in builder.stats], [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._verify_combined_statistics(comb_tags, test_tags, expected_count)
-
- def _verify_combined_statistics(self, comb_tags, test_tags, expected_count): - builder = TagStatisticsBuilder(Criticality(), combined=[(comb_tags, 'name')])
-        builder._add_to_combined_statistics(TestCase(tags=test_tags))
- assert_equals([s.total for s in builder.stats if s.combined], [expected_count])
-
-    def test_is_combined_with_not_statements(self):
-        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', ['S','T'], 0),
-                ('tNOTs*NOTr', ['R','T','s'], 1),
-               ]:
- self._verify_combined_statistics(comb_tags, test_tags, expected_count)
-
-    def test_combine_with_same_name_as_existing_tag(self):
- builder = TagStatisticsBuilder(Criticality(), combined=[('x*', 'name')])
-        builder.add_test(TestCase(tags=['name', 'another']))
-        assert_equals([(s.name, s.combined) for s in builder.stats],
-                      [('name', 'x*'), ('another', ''), ('name', '')])
-
-    def test_combine(self):
-        # This is more like an acceptance test than a unit test ...
-        for comb_tags, tests_tags, crit_tags in [
-                (['t1&t2'], [['t1','t2','t3'],['t1','t3']], []),
-                (['1&2&3'], [['1','2','3'],['1','2','3','4']], ['1','2']),
-                (['1&2','1&3'], [['1','2','3'],['1','3'],['1']], ['1']),
-                (['t*'], [['t1','x','y'],['tee','z'],['t']], ['x']),
- (['t?&s'], [['t1','s'],['tt','s','u'],['tee','s'],['s']], []),
-                (['t*&s','*'], [['s','t','u'],['tee','s'],[],['x']], []),
-                (['tNOTs'], [['t','u'],['t','s']], []),
-                (['tNOTs','t&s','tNOTsNOTu', 't&sNOTu'],
- [['t','u'],['t','s'],['s','t','u'],['t'],['t','v']], ['t']),
-                (['nonex'], [['t1'],['t1,t2'],[]], [])
-               ]:
-            # 1) Create tag stats
-            builder = TagStatisticsBuilder(Criticality(crit_tags),
- combined=[(t, '') for t in comb_tags])
-            all_tags = []
-            for tags in tests_tags:
-                builder.add_test(TestCase(status='PASS', tags=tags),)
-                all_tags.extend(tags)
-            # 2) Actual values
-            names = [stat.name for stat in builder.stats]
-            # 3) Expected values
-            exp_crit = []; exp_noncr = []
-            for tag in utils.normalize_tags(all_tags):
-                if tag in crit_tags:
-                    exp_crit.append(tag)
-                else:
-                    exp_noncr.append(tag)
-            exp_names = exp_crit + sorted(comb_tags) + exp_noncr
-            # 4) Verify names (match counts were already verified)
-            assert_equals(names, exp_names)
-
-    def test_sorting(self):
-        builder = TagStatisticsBuilder(Criticality(['c2', 'c1'], ['n*']),
- combined=[('c*', ''), ('xxx', 'a title')])
-        builder.add_test(TestCase(tags=['c1', 'c2', 't1']))
-        builder.add_test(TestCase(tags=['c1', 'n2', 't2']))
-        builder.add_test(TestCase(tags=['n1', 'n2', 't1', 't3']))
-        assert_equals([(s.name, s.info, s.total) for s in builder.stats],
-                       [('c1', 'critical', 2), ('c2', 'critical', 1),
- ('n1', 'non-critical', 1), ('n2', 'non-critical', 2),
-                        ('a title', 'combined', 0), ('c*', 'combined', 2),
-                        ('t1', '', 2), ('t2', '', 1), ('t3', '', 1)])
-
-    def test_through_suite(self):
-        suite = generate_default_suite()
-        suite.set_criticality(critical_tags=['smoke'])
-        statistics = Statistics(suite, 1, ['t*','smoke'], ['t3'],
-                                [('t1 & t2', ''), ('t? & smoke', ''),
- ('t1 NOT t2', ''), ('none & t1', 'a title')])
-        expected = [('smoke', 4), ('a title', 0), ('t1 & t2', 3),
- ('t1 NOT t2', 2), ('t? & smoke', 4), ('t1', 5), ('t2', 3)] - assert_equals([(t.name, t.total) for t in statistics.tags], expected)
-
-
-class TestTagStatLink(unittest.TestCase):
-
-    def test_valid_string_is_parsed_correctly(self):
-        for arg, exp in [(('Tag', 'bar/foo.html', 'foobar'),
-                          ('^Tag$', 'bar/foo.html', 'foobar')),
-                         (('hello', 'gopher://hello.world:8090/hello.html',
-                           'Hello World'),
- ('^hello$', 'gopher://hello.world:8090/hello.html',
-                           'Hello World'))]:
-            link = TagStatLink(*arg)
-            assert_equals(exp[0], link._regexp.pattern)
-            assert_equals(exp[1], link._link)
-            assert_equals(exp[2], link._title)
-
-    def test_valid_string_containing_patterns_is_parsed_correctly(self):
-        for arg, exp_pattern in [('*', '^(.*)$'), ('f*r', '^f(.*)r$'),
-                                 ('*a*', '^(.*)a(.*)$'),  ('?', '^(.)$'),
- ('??', '^(..)$'), ('f???ar', '^f(...)ar$'),
-                                 ('F*B?R*?', '^F(.*)B(.)R(.*)(.)$')]:
-            link = TagStatLink(arg, 'some_url', 'some_title')
-            assert_equals(exp_pattern, link._regexp.pattern)
-
-    def test_underscores_in_title_are_converted_to_spaces(self):
-        link = TagStatLink('', '', 'my_name')
-        assert_equals(link._title, 'my name')
-
-    def test_get_link_returns_correct_link_when_matches(self):
-        for arg, exp in [(('smoke', 'http://tobacco.com', 'Lung_cancer'),
-                          ('http://tobacco.com', 'Lung cancer')),
-                         (('tag', 'ftp://foo:809/bar.zap', 'Foo_in a Bar'),
-                          ('ftp://foo:809/bar.zap', 'Foo in a Bar'))]:
-            link = TagStatLink(*arg)
-            assert_equals(exp, link.get_link(arg[0]))
-
-    def test_get_link_returns_none_when_no_match(self):
-        link = TagStatLink('smoke', 'http://tobacco.com', 'Lung cancer')
-        for tag in ['foo', 'b a r', 's moke']:
-            assert_none(link.get_link(tag))
-
-    def test_pattern_matches_case_insensitively(self):
-        exp = 'http://tobacco.com', 'Lung cancer'
-        link = TagStatLink('smoke', *exp)
-        for tag in ['Smoke', 'SMOKE', 'smoke']:
-            assert_equals(exp, link.get_link(tag))
-
-    def test_pattern_matches_when_spaces(self):
-        exp = 'http://tobacco.com', 'Lung cancer'
-        link = TagStatLink('smoking kills', *exp)
-        for tag in ['Smoking Kills', 'SMOKING KILLS']:
-            assert_equals(exp, link.get_link(tag))
-
-    def test_pattern_match(self):
-        link = TagStatLink('f?o*r', 'http://foo/bar.html', 'FooBar')
-        for tag in ['foobar', 'foor', 'f_ofoobarfoobar', 'fOoBAr']:
- assert_equals(link.get_link(tag), ('http://foo/bar.html', 'FooBar'))
-
-    def test_pattern_substitution_with_one_match(self):
-        link = TagStatLink('tag-*', 'http://tracker/?id=%1', 'Tracker')
-        for id in ['1', '23', '456']:
-            exp = ('http://tracker/?id=%s' % id, 'Tracker')
-            assert_equals(exp, link.get_link('tag-%s' % id))
-
-    def test_pattern_substitution_with_multiple_matches(self):
-        link = TagStatLink('?-*', 'http://tracker/?id=%1-%2', 'Tracker')
-        for id1, id2 in [('1', '2'), ('3', '45'), ('f', 'bar')]:
-            exp = ('http://tracker/?id=%s-%s' % (id1, id2), 'Tracker')
-            assert_equals(exp, link.get_link('%s-%s' % (id1, id2)))
-
-    def test_pattern_substitution_with_multiple_substitutions(self):
-        link = TagStatLink('??-?-*', '%3-%3-%1-%2-%3', 'Tracker')
- assert_equals(link.get_link('aa-b-XXX'), ('XXX-XXX-aa-b-XXX', 'Tracker'))
-
-    def test_matches_are_ignored_in_pattern_substitution(self):
-        link = TagStatLink('???-*-*-?', '%4-%2-%2-%4', 'Tracker')
- assert_equals(link.get_link('AAA-XXX-ABC-B'), ('B-XXX-XXX-B', 'Tracker'))
+        assert_equals(len(s1.suites), 3)
+        s11, s12, s13 = s1.suites
+ verify_suite(s11, 'Root Suite.First Sub Suite.Sub Suite 1_1', 's1-s1-s1', 0, 0, 1, 1) + verify_suite(s12, 'Root Suite.First Sub Suite.Sub Suite 1_2', 's1-s1-s2', 1, 1, 2, 1) + verify_suite(s13, 'Root Suite.First Sub Suite.Sub Suite 1_3', 's1-s1-s3', 1, 0, 1, 0)
+        assert_equals(len(s2.suites), 1)
+        s21 = s2.suites[0]
+ verify_suite(s21, 'Root Suite.Second Sub Suite.Sub Suite 2_1', 's1-s2-s1', 0, 1, 0, 1)
+
+    def test_only_root_level(self):
+        suite = Statistics(generate_suite(), suite_stat_level=1).suite
+        verify_suite(suite, 'Root Suite', 's1', 2, 2, 4, 3)
+        assert_equals(len(suite.suites), 0)
+
+    def test_deeper_level(self):
+        PASS = TestCase(status='PASS')
+        FAIL = TestCase(status='FAIL')
+        suite = TestSuite(name='1')
+ suite.suites = [TestSuite(name='1'), TestSuite(name='2'), TestSuite(name='3')]
+        suite.suites[0].suites = [TestSuite(name='1')]
+        suite.suites[1].suites = [TestSuite(name='1'), TestSuite(name='2')]
+        suite.suites[2].tests = [PASS, FAIL]
+        suite.suites[0].suites[0].suites = [TestSuite(name='1')]
+        suite.suites[1].suites[0].tests = [PASS, PASS, PASS, FAIL]
+        suite.suites[1].suites[1].tests = [PASS, PASS, FAIL, FAIL]
+        suite.suites[0].suites[0].suites[0].tests = [FAIL, FAIL, FAIL]
+        s1 = Statistics(suite, suite_stat_level=3).suite
+        verify_suite(s1, '1', 's1', 6, 7)
+        [s11, s12, s13] = s1.suites
+        verify_suite(s11, '1.1', 's1-s1', 0, 3)
+        verify_suite(s12, '1.2', 's1-s2', 5, 3)
+        verify_suite(s13, '1.3', 's1-s3', 1, 1)
+        [s111] = s11.suites
+        verify_suite(s111, '1.1.1', 's1-s1-s1', 0, 3)
+        [s121, s122] = s12.suites
+        verify_suite(s121, '1.2.1', 's1-s2-s1', 3, 1)
+        verify_suite(s122, '1.2.2', 's1-s2-s2', 2, 2)
+        assert_equals(len(s111.suites), 0)


 if __name__ == "__main__":

Reply via email to