diff --git a/git_code_debt_server/metric_config.py b/git_code_debt_server/metric_config.py index 7c7ed21..0995324 100644 --- a/git_code_debt_server/metric_config.py +++ b/git_code_debt_server/metric_config.py @@ -2,6 +2,7 @@ import collections import re +import staticconf.errors import staticconf.getters from git_code_debt_util.config import get_config_watcher @@ -25,6 +26,11 @@ def contains(self, metric_name): @classmethod def from_yaml(cls, name, metrics, metric_expressions): + if not metrics and not metric_expressions: + raise staticconf.errors.ValidationError( + 'Group {0} must define at least one of ' + '`metrics` or `metric_expressions`'.format(name) + ) return cls( name, set(metrics), @@ -38,7 +44,11 @@ def _get_groups_from_yaml(yaml): # Here's an example yaml: # [{'Bar': {'metrics': ['Foo', 'Bar'], 'metric_expressions': ['^Baz']}}] return tuple( - Group.from_yaml(*group_dict.keys(), **group_dict.values()[0]) + Group.from_yaml( + group_dict.keys()[0], + group_dict.values()[0].get('metrics', []), + group_dict.values()[0].get('metric_expressions', []), + ) for group_dict in yaml ) diff --git a/metric_config.yaml b/metric_config.yaml index 7b84dd2..1c6e39b 100644 --- a/metric_config.yaml +++ b/metric_config.yaml @@ -11,6 +11,7 @@ # # This defines a group named Group1 which explicitly includes the metrics # FooMetric and BarMetric and also includes all metrics which match ^.*Baz.*$. +# NOTE: metrics and metric_expressions may be omitted Groups: - Cheetah: @@ -18,14 +19,11 @@ Groups: metric_expressions: - ^.*Cheetah.*$ - Python: - metrics: [] metric_expressions: - ^.*Python.*$ - CurseWords: - metrics: [] metric_expressions: - ^TotalCurseWords.*$ - LinesOfCode: - metrics: [] metric_expressions: - ^TotalLinesOfCode.*$ diff --git a/tests/git_code_debt_server/metric_config_test.py b/tests/git_code_debt_server/metric_config_test.py index 98de7ab..3d8e0bb 100644 --- a/tests/git_code_debt_server/metric_config_test.py +++ b/tests/git_code_debt_server/metric_config_test.py @@ -2,79 +2,106 @@ import mock import re +import staticconf.errors import testify as T from git_code_debt_server.metric_config import _get_groups_from_yaml from git_code_debt_server.metric_config import Group +from testing.base_classes.test import test -class GroupTest(T.TestCase): - def test_from_yaml(self): - # Simulate a call we would get from yaml - group = Group.from_yaml('BazGroup', **{ - 'metrics': ['Foo', 'Bar'], - 'metric_expressions': ['^.*Baz.*$'], - }) - - T.assert_equal( - group, - Group('BazGroup', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)), - ) - - def test_contains_does_not_contain(self): - group = Group('G', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)) - T.assert_is(group.contains('buz'), False) - - def test_contains_contains_by_name(self): - group = Group('G', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)) - T.assert_is(group.contains('Foo'), True) - - def test_contains_by_regex(self): - group = Group('G', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)) - T.assert_is(group.contains('FooBaz'), True) - - -class TestGetGroupsFromYaml(T.TestCase): - def test_get_groups_from_yaml(self): - # Grapped from sample run - groups_yaml = [ - {'Cheetah': { - 'metrics': [], - 'metric_expressions': ['^.*Cheetah.*$'], - }}, - {'Python': { - 'metrics': [], - 'metric_expressions': ['^.*Python.*$'], - }}, - {'CurseWords': { - 'metrics': [], - 'metric_expressions': ['^TotalCurseWords.*$'], - }}, - {'LinesOfCode': { - 'metrics': [], - 'metric_expressions': ['^TotalLinesOfCode.*$'], - }} - ] - - groups = _get_groups_from_yaml(groups_yaml) - T.assert_equal( - groups, - ( - # Regexes tested below - Group('Cheetah', set([]), (mock.ANY,)), - Group('Python', set([]), (mock.ANY,)), - Group('CurseWords', set([]), (mock.ANY,)), - Group('LinesOfCode', set([]), (mock.ANY,)), - ), - ) - - regexes = [group.metric_expressions[0].pattern for group in groups] - T.assert_equal( - regexes, - [ - '^.*Cheetah.*$', - '^.*Python.*$', - '^TotalCurseWords.*$', - '^TotalLinesOfCode.*$', - ], - ) +@test +def test_Group_from_yaml(): + # Simulate a call we would get from yaml + group = Group.from_yaml('BazGroup', **{ + 'metrics': ['Foo', 'Bar'], + 'metric_expressions': ['^.*Baz.*$'], + }) + + T.assert_equal( + group, + Group('BazGroup', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)), + ) + +@test +def test_Group_from_yaml_complains_if_nothing_useful_specified(): + with T.assert_raises_exactly( + staticconf.errors.ValidationError, + 'Group G1 must define at least one of `metrics` or `metric_expressions`' + ): + Group.from_yaml('G1', [], []) + +@test +def test_Group_contains_does_not_contain(): + group = Group('G', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)) + T.assert_is(group.contains('buz'), False) + +@test +def test_Group_contains_contains_by_name(): + group = Group('G', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)) + T.assert_is(group.contains('Foo'), True) + +@test +def test_Group_contains_by_regex(): + group = Group('G', set(['Foo', 'Bar']), (re.compile('^.*Baz.*$'),)) + T.assert_is(group.contains('FooBaz'), True) + + +@test +def test_get_groups_from_yaml_smoke(): + # Grapped from sample run + groups_yaml = [ + {'Cheetah': { + 'metrics': [], + 'metric_expressions': ['^.*Cheetah.*$'], + }}, + {'Python': { + 'metrics': [], + 'metric_expressions': ['^.*Python.*$'], + }}, + {'CurseWords': { + 'metrics': [], + 'metric_expressions': ['^TotalCurseWords.*$'], + }}, + {'LinesOfCode': { + 'metrics': [], + 'metric_expressions': ['^TotalLinesOfCode.*$'], + }} + ] + + groups = _get_groups_from_yaml(groups_yaml) + T.assert_equal( + groups, + ( + # Regexes tested below + Group('Cheetah', set([]), (mock.ANY,)), + Group('Python', set([]), (mock.ANY,)), + Group('CurseWords', set([]), (mock.ANY,)), + Group('LinesOfCode', set([]), (mock.ANY,)), + ), + ) + + regexes = [group.metric_expressions[0].pattern for group in groups] + T.assert_equal( + regexes, + [ + '^.*Cheetah.*$', + '^.*Python.*$', + '^TotalCurseWords.*$', + '^TotalLinesOfCode.*$', + ], + ) + +@test +def test_get_groups_from_yaml_no_metrics_provided(): + groups_yaml = [{'G1': {'metric_expressions': ['^Foo.*$']}}] + groups = _get_groups_from_yaml(groups_yaml) + # Regex tested below + T.assert_equal(groups, (Group('G1', set([]), (mock.ANY,)),)) + T.assert_equal(groups[0].metric_expressions[0].pattern, '^Foo.*$') + +@test +def test_get_groups_from_yaml_no_metric_expressions_provided(): + groups_yaml = [{'G1': {'metrics': ['Foo']}}] + groups = _get_groups_from_yaml(groups_yaml) + T.assert_equal(groups, (Group('G1', set(['Foo']), tuple()),))