From 2f129af4ecf462132247a93d3be0896a3074a2ea Mon Sep 17 00:00:00 2001 From: meek Date: Wed, 13 Mar 2024 23:15:40 +0100 Subject: [PATCH 1/7] Fix in SLT --- microfreshener/core/analyser/sniffer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/microfreshener/core/analyser/sniffer.py b/microfreshener/core/analyser/sniffer.py index 9413587..3a779d4 100644 --- a/microfreshener/core/analyser/sniffer.py +++ b/microfreshener/core/analyser/sniffer.py @@ -111,7 +111,7 @@ def _not_internally_linked(self, node): for link in (node.interactions + node.incoming_interactions): source_squad = self.micro_model.squad_of(link.source) target_squad = self.micro_model.squad_of(link.target) - if (link.source is not node and source_squad is same_squad) or (link.target is not node and target_squad is same_squad): + if (link.target is node and source_squad is same_squad) or (link.source is node and target_squad is same_squad): return False return True @@ -125,7 +125,8 @@ def snif(self, group: Team) -> SingleLayerTeamsSmell: target_node = relationship.target source_squad = self.micro_model.squad_of(source_node) target_squad = self.micro_model.squad_of(target_node) - if (target_squad is not None and + if (source_squad is not None and + target_squad is not None and source_squad != target_squad and isinstance(source_node, Service) and not isinstance(target_node, Service) and From e01f937966d69033e340bb5b97d9402de8417ad6 Mon Sep 17 00:00:00 2001 From: meek Date: Thu, 14 Mar 2024 13:43:47 +0100 Subject: [PATCH 2/7] SLT fixed and Unit Tests created --- data/tests/test_sniffer_ctdm.yml | 41 ------ data/tests/test_sniffer_slt.yml | 169 ++++++++++++++++++++++++ microfreshener/core/analyser/sniffer.py | 7 +- tests/test_analyser/test_sniffer_slt.py | 82 +++++++++--- 4 files changed, 240 insertions(+), 59 deletions(-) delete mode 100644 data/tests/test_sniffer_ctdm.yml create mode 100644 data/tests/test_sniffer_slt.yml diff --git a/data/tests/test_sniffer_ctdm.yml b/data/tests/test_sniffer_ctdm.yml deleted file mode 100644 index 1f2f549..0000000 --- a/data/tests/test_sniffer_ctdm.yml +++ /dev/null @@ -1,41 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_1 - -description: For testing the Cross Team Data Managment - -imports: - - micro: ../../data/micro-tosca-types.yml - -topology_template: - node_templates: - s1: - type: micro.nodes.Service - requirements: - - interaction: db1 - - interaction: db2 - - interaction: db3 - s2: - type: micro.nodes.Service - requirements: - - interaction: db2 - - interaction: db3 - s3: - type: micro.nodes.Service - requirements: - - interaction: db3 - db1: - type: micro.nodes.Datastore - db2: - type: micro.nodes.Datastore - db3: - type: micro.nodes.Datastore - - groups: - team1: - type: micro.groups.Team - members: [s1, db1] - team2: - type: micro.groups.Team - members: [s2, db2] - team3: - type: micro.groups.Team - members: [s3, db3] diff --git a/data/tests/test_sniffer_slt.yml b/data/tests/test_sniffer_slt.yml new file mode 100644 index 0000000..e402ef0 --- /dev/null +++ b/data/tests/test_sniffer_slt.yml @@ -0,0 +1,169 @@ +tosca_definitions_version: tosca_simple_yaml_1.1 +description: For testing the Single Layer Teams sniffer +imports: +- micro: https://di-unipi-socc.github.io/microTOSCA/1.1/microTOSCA.yaml +topology_template: + node_templates: + st1: + type: micro.nodes.Service + requirements: + - interaction: dt1 + dt1: + type: micro.nodes.Datastore + s1t2: + type: micro.nodes.Service + requirements: + - interaction: dt2 + s2t2: + type: micro.nodes.Service + requirements: + - interaction: dt2 + dt2: + type: micro.nodes.Datastore + st3: + type: micro.nodes.Service + requirements: + - interaction: dt3 + dt3: + type: micro.nodes.Datastore + st4: + type: micro.nodes.Service + requirements: + - interaction: mrt4 + mrt4: + type: micro.nodes.MessageRouter + st5: + type: micro.nodes.Service + requirements: + - interaction: mbt5 + mbt5: + type: micro.nodes.MessageBroker + s1t6: + type: micro.nodes.Service + requirements: + - interaction: mrt6 + s2t6: + type: micro.nodes.Service + requirements: + - interaction: mrt6 + mrt6: + type: micro.nodes.MessageRouter + s1t7: + type: micro.nodes.Service + requirements: + - interaction: mbt7 + s2t7: + type: micro.nodes.Service + requirements: + - interaction: mbt7 + mbt7: + type: micro.nodes.MessageBroker + st8: + type: micro.nodes.Service + requirements: + - interaction: mr1t8 + mr1t8: + type: micro.nodes.MessageRouter + requirements: + - interaction: mr2t8 + mr2t8: + type: micro.nodes.MessageRouter + groups: + t1t1: + type: micro.groups.Team + members: + - st1 + t2t1: + type: micro.groups.Team + members: + - dt1 + t1t2: + type: micro.groups.Team + members: + - s1t2 + t2t2: + type: micro.groups.Team + members: + - dt2 + - s2t2 + tt3: + type: micro.groups.Team + members: + - st3 + t1t4: + type: micro.groups.Team + members: + - st4 + t2t4: + type: micro.groups.Team + members: + - mrt4 + t1t5: + type: micro.groups.Team + members: + - st5 + t2t5: + type: micro.groups.Team + members: + - mbt5 + t1t6: + type: micro.groups.Team + members: + - s1t6 + t2t6: + type: micro.groups.Team + members: + - mrt6 + - s2t6 + t1t7: + type: micro.groups.Team + members: + - s1t7 + t2t7: + type: micro.groups.Team + members: + - mbt7 + - s2t7 + t1t8: + type: micro.groups.Team + members: + - st8 + t2t8: + type: micro.groups.Team + members: + - mr1t8 + - mr2t8 + relationship_templates: + t: + type: micro.relationships.InteractsWith + properties: + timeout: true + c: + type: micro.relationships.InteractsWith + properties: + circuit_breaker: true + d: + type: micro.relationships.InteractsWith + properties: + dynamic_discovery: true + tc: + type: micro.relationships.InteractsWith + properties: + timeout: true + circuit_breaker: true + td: + type: micro.relationships.InteractsWith + properties: + timeout: true + dynamic_discovery: true + cd: + type: micro.relationships.InteractsWith + properties: + circuit_breaker: true + dynamic_discovery: true + tcd: + type: micro.relationships.InteractsWith + properties: + timeout: true + circuit_breaker: true + dynamic_discovery: true diff --git a/microfreshener/core/analyser/sniffer.py b/microfreshener/core/analyser/sniffer.py index 3a779d4..e1777c1 100644 --- a/microfreshener/core/analyser/sniffer.py +++ b/microfreshener/core/analyser/sniffer.py @@ -106,12 +106,13 @@ class SingleLayerTeamsSmellSniffer(GroupSmellSniffer): def __str__(self): return 'SingleLayerTeamsSmellSniffer({})'.format(super(GroupSmellSniffer, self).__str__()) - def _not_internally_linked(self, node): + def _not_internally_linked_to_service(self, node): same_squad = self.micro_model.squad_of(node) for link in (node.interactions + node.incoming_interactions): source_squad = self.micro_model.squad_of(link.source) target_squad = self.micro_model.squad_of(link.target) - if (link.target is node and source_squad is same_squad) or (link.source is node and target_squad is same_squad): + # Check for a link to/from a service within the same team + if ((link.target is node and source_squad is same_squad) or (link.source is node and target_squad is same_squad)) and (isinstance(link.source, Service) or isinstance(link.target, Service)): return False return True @@ -130,7 +131,7 @@ def snif(self, group: Team) -> SingleLayerTeamsSmell: source_squad != target_squad and isinstance(source_node, Service) and not isinstance(target_node, Service) and - (isinstance(target_node, Datastore) or self._not_internally_linked(target_node))): + (isinstance(target_node, Datastore) or self._not_internally_linked_to_service(target_node))): smell.addLinkCause(relationship) return smell diff --git a/tests/test_analyser/test_sniffer_slt.py b/tests/test_analyser/test_sniffer_slt.py index ba2f9e8..a4816f5 100644 --- a/tests/test_analyser/test_sniffer_slt.py +++ b/tests/test_analyser/test_sniffer_slt.py @@ -3,27 +3,79 @@ from microfreshener.core.importer import YMLImporter from microfreshener.core.analyser.sniffer import SingleLayerTeamsSmellSniffer from microfreshener.core.analyser.smell import SingleLayerTeamsSmell -from microfreshener.core.model.groups import Edge class TestSingleLayerTeamsSmell(TestCase): @classmethod def setUpClass(self): - file = 'data/tests/test_sniffer_ctdm.yml' + file = 'data/tests/test_sniffer_slt.yml' loader = YMLImporter() self.micro_model = loader.Import(file) - self.ctdmSniffer = SingleLayerTeamsSmellSniffer( - self.micro_model) - - def test_ctdm(self): - team1 = self.micro_model.get_group("team1") - smell = self.ctdmSniffer.snif(team1) - self.assertIsInstance(smell, SingleLayerTeamsSmellSmell) - self.assertFalse(smell.isEmpty()) - self.assertEqual(len(smell.getLinkCause()), 2) - - def test_(self): - team3 = self.micro_model.get_group("team3") - smell = self.ctdmSniffer.snif(team3) + self.sltSniffer = SingleLayerTeamsSmellSniffer(self.micro_model) + + def test_yes_slt_with_db(self): + team1 = self.micro_model.get_group("t1t1") + smell1 = self.sltSniffer.snif(team1) + self.assertIsInstance(smell1, SingleLayerTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t1") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_yes_slt_with_db_used_by_dbteam(self): + team1 = self.micro_model.get_group("t1t2") + smell1 = self.sltSniffer.snif(team1) + self.assertIsInstance(smell1, SingleLayerTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t2") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_no_slt_with_db_not_in_team(self): + team = self.micro_model.get_group("tt3") + smell = self.sltSniffer.snif(team) self.assertTrue(smell.isEmpty()) + + def test_yes_slt_with_mr_not_internally_linked(self): + team1 = self.micro_model.get_group("t1t4") + smell1 = self.sltSniffer.snif(team1) + self.assertIsInstance(smell1, SingleLayerTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t4") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_yes_slt_with_mb_not_internally_linked(self): + team1 = self.micro_model.get_group("t1t5") + smell1 = self.sltSniffer.snif(team1) + self.assertIsInstance(smell1, SingleLayerTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t5") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_no_slt_with_mr_internally_linked(self): + team1 = self.micro_model.get_group("t1t6") + smell1 = self.sltSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t6") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_no_slt_with_mb_internally_linked(self): + team1 = self.micro_model.get_group("t1t7") + smell1 = self.sltSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t7") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_yes_slt_with_mr_internally_linked_to_mr(self): + team1 = self.micro_model.get_group("t1t8") + smell1 = self.sltSniffer.snif(team1) + self.assertIsInstance(smell1, SingleLayerTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t8") + smell2 = self.sltSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) \ No newline at end of file From f3e84a11e6b005110bd72f4a43ec5ef015ee66b8 Mon Sep 17 00:00:00 2001 From: meek Date: Thu, 14 Mar 2024 14:14:20 +0100 Subject: [PATCH 3/7] Unit tests and test data for TCT added --- data/tests/test_sniffer_tct.yml | 161 ++++++++++++++++++++++++ tests/test_analyser/test_sniffer_tct.py | 82 ++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 data/tests/test_sniffer_tct.yml create mode 100644 tests/test_analyser/test_sniffer_tct.py diff --git a/data/tests/test_sniffer_tct.yml b/data/tests/test_sniffer_tct.yml new file mode 100644 index 0000000..d4c20db --- /dev/null +++ b/data/tests/test_sniffer_tct.yml @@ -0,0 +1,161 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +description: For testing the Tightly Coupled Teams smell +imports: +- micro: https://di-unipi-socc.github.io/microTOSCA/1.1/microTOSCA.yaml +topology_template: + node_templates: + s1t1: + type: micro.nodes.Service + s2t1: + type: micro.nodes.Service + requirements: + - interaction: s1t1 + - interaction: s3t1 + s3t1: + type: micro.nodes.Service + requirements: + - interaction: s1t1 + s1t2: + type: micro.nodes.Service + requirements: + - interaction: s2t2 + s2t2: + type: micro.nodes.Service + requirements: + - interaction: d1t2 + d1t2: + type: micro.nodes.Datastore + mrt3: + type: micro.nodes.MessageRouter + requirements: + - interaction: s1t3 + - interaction: s2t3 + s1t3: + type: micro.nodes.Service + requirements: + - interaction: s2t3 + s2t3: + type: micro.nodes.Service + s1t4: + type: micro.nodes.Service + requirements: + - interaction: s3t4 + s2t4: + type: micro.nodes.Service + requirements: + - interaction: s1t4 + s3t4: + type: micro.nodes.Service + mbt5: + type: micro.nodes.MessageBroker + st5: + type: micro.nodes.Service + requirements: + - interaction: mbt5 + st6: + type: micro.nodes.Service + requirements: + - interaction: mrt6 + mrt6: + type: micro.nodes.MessageRouter + st7: + type: micro.nodes.Service + requirements: + - interaction: dt7 + dt7: + type: micro.nodes.Datastore + groups: + t1t1: + type: micro.groups.Team + members: + - s1t1 + t2t1: + type: micro.groups.Team + members: + - s2t1 + - s3t1 + t1t2: + type: micro.groups.Team + members: + - s1t2 + t2t2: + type: micro.groups.Team + members: + - s2t2 + - d1t2 + t1t3: + type: micro.groups.Team + members: + - mrt3 + t2t3: + type: micro.groups.Team + members: + - s1t3 + - s2t3 + t1t4: + type: micro.groups.Team + members: + - s1t4 + t2t4: + type: micro.groups.Team + members: + - s2t4 + - s3t4 + t1t5: + type: micro.groups.Team + members: + - mbt5 + t2t5: + type: micro.groups.Team + members: + - st5 + t1t6: + type: micro.groups.Team + members: + - st6 + t2t6: + type: micro.groups.Team + members: + - mrt6 + t1t7: + type: micro.groups.Team + members: + - st7 + t2t7: + type: micro.groups.Team + members: + - dt7 + relationship_templates: + t: + type: micro.relationships.InteractsWith + properties: + timeout: true + c: + type: micro.relationships.InteractsWith + properties: + circuit_breaker: true + d: + type: micro.relationships.InteractsWith + properties: + dynamic_discovery: true + tc: + type: micro.relationships.InteractsWith + properties: + timeout: true + circuit_breaker: true + td: + type: micro.relationships.InteractsWith + properties: + timeout: true + dynamic_discovery: true + cd: + type: micro.relationships.InteractsWith + properties: + circuit_breaker: true + dynamic_discovery: true + tcd: + type: micro.relationships.InteractsWith + properties: + timeout: true + circuit_breaker: true + dynamic_discovery: true diff --git a/tests/test_analyser/test_sniffer_tct.py b/tests/test_analyser/test_sniffer_tct.py new file mode 100644 index 0000000..7f77194 --- /dev/null +++ b/tests/test_analyser/test_sniffer_tct.py @@ -0,0 +1,82 @@ +from unittest import TestCase + +from microfreshener.core.importer import YMLImporter +from microfreshener.core.analyser.sniffer import TightlyCoupledTeamsSmellSniffer +from microfreshener.core.analyser.smell import TightlyCoupledTeamsSmell + + +class TestTightlyCoupledTeamsSmell(TestCase): + + @classmethod + def setUpClass(self): + file = 'data/tests/test_sniffer_tct.yml' + loader = YMLImporter() + self.micro_model = loader.Import(file) + self.tctSniffer = TightlyCoupledTeamsSmellSniffer(self.micro_model) + + def test_tct_simple(self): + team1 = self.micro_model.get_group("t1t1") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t1") + smell2 = self.tctSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_tct_service_with_db(self): + team1 = self.micro_model.get_group("t1t2") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t2") + smell2 = self.tctSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_tct_with_mr(self): + team1 = self.micro_model.get_group("t1t3") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t3") + smell2 = self.tctSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_tct_both(self): + team1 = self.micro_model.get_group("t1t4") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t4") + smell2 = self.tctSniffer.snif(team2) + self.assertIsInstance(smell2, TightlyCoupledTeamsSmell) + self.assertFalse(smell2.isEmpty()) + + def test_tct_with_mb_both(self): + team1 = self.micro_model.get_group("t1t5") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t5") + smell2 = self.tctSniffer.snif(team2) + self.assertIsInstance(smell2, TightlyCoupledTeamsSmell) + self.assertFalse(smell2.isEmpty()) + + def test_tct_with_mr_both(self): + team1 = self.micro_model.get_group("t1t6") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t6") + smell2 = self.tctSniffer.snif(team2) + self.assertIsInstance(smell2, TightlyCoupledTeamsSmell) + self.assertFalse(smell2.isEmpty()) + + def test_tct_with_db_both(self): + team1 = self.micro_model.get_group("t1t7") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t7") + smell2 = self.tctSniffer.snif(team2) + self.assertIsInstance(smell2, TightlyCoupledTeamsSmell) + self.assertFalse(smell2.isEmpty()) \ No newline at end of file From 053e3d06c81ecc694fc1fdae9a9e5873b6d37ff4 Mon Sep 17 00:00:00 2001 From: meek Date: Thu, 14 Mar 2024 15:15:27 +0100 Subject: [PATCH 4/7] TCT Unit Test enhanced --- data/tests/test_sniffer_tct.yml | 15 ++++++++++++++- tests/test_analyser/test_sniffer_tct.py | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/data/tests/test_sniffer_tct.yml b/data/tests/test_sniffer_tct.yml index d4c20db..782f5f1 100644 --- a/data/tests/test_sniffer_tct.yml +++ b/data/tests/test_sniffer_tct.yml @@ -1,5 +1,5 @@ tosca_definitions_version: tosca_simple_yaml_1_1 -description: For testing the Tightly Coupled Teams smell +description: For testing the Wobbly Service Interaction Smell imports: - micro: https://di-unipi-socc.github.io/microTOSCA/1.1/microTOSCA.yaml topology_template: @@ -64,6 +64,15 @@ topology_template: - interaction: dt7 dt7: type: micro.nodes.Datastore + s1t8: + type: micro.nodes.Service + requirements: + - interaction: s2t8 + - interaction: s3t8 + s2t8: + type: micro.nodes.Service + s3t8: + type: micro.nodes.Service groups: t1t1: type: micro.groups.Team @@ -125,6 +134,10 @@ topology_template: type: micro.groups.Team members: - dt7 + tt8: + type: micro.groups.Team + members: + - s1t8 relationship_templates: t: type: micro.relationships.InteractsWith diff --git a/tests/test_analyser/test_sniffer_tct.py b/tests/test_analyser/test_sniffer_tct.py index 7f77194..1a108fd 100644 --- a/tests/test_analyser/test_sniffer_tct.py +++ b/tests/test_analyser/test_sniffer_tct.py @@ -79,4 +79,19 @@ def test_tct_with_db_both(self): team2 = self.micro_model.get_group("t2t7") smell2 = self.tctSniffer.snif(team2) self.assertIsInstance(smell2, TightlyCoupledTeamsSmell) - self.assertFalse(smell2.isEmpty()) \ No newline at end of file + self.assertFalse(smell2.isEmpty()) + + def test_tct_with_db_both(self): + team1 = self.micro_model.get_group("t1t7") + smell1 = self.tctSniffer.snif(team1) + self.assertIsInstance(smell1, TightlyCoupledTeamsSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t7") + smell2 = self.tctSniffer.snif(team2) + self.assertIsInstance(smell2, TightlyCoupledTeamsSmell) + self.assertFalse(smell2.isEmpty()) + + def test_tct_with_db_both(self): + team1 = self.micro_model.get_group("tt8") + smell1 = self.tctSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) \ No newline at end of file From e26156fef1230d26aceba8da64a914b0dd3dd15a Mon Sep 17 00:00:00 2001 From: meek Date: Thu, 14 Mar 2024 15:26:22 +0100 Subject: [PATCH 5/7] Unit test for Shared Bounded Context sniffer added --- data/tests/test_sniffer_sbc.yml | 113 ++++++++++++++++++++++++ tests/test_analyser/test_sniffer_sbc.py | 50 +++++++++++ 2 files changed, 163 insertions(+) create mode 100644 data/tests/test_sniffer_sbc.yml create mode 100644 tests/test_analyser/test_sniffer_sbc.py diff --git a/data/tests/test_sniffer_sbc.yml b/data/tests/test_sniffer_sbc.yml new file mode 100644 index 0000000..78cadec --- /dev/null +++ b/data/tests/test_sniffer_sbc.yml @@ -0,0 +1,113 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +description: For testing the Shared Bounded Context smell +imports: +- micro: https://di-unipi-socc.github.io/microTOSCA/1.1/microTOSCA.yaml +topology_template: + node_templates: + d1t1: + type: micro.nodes.Datastore + s1t1: + type: micro.nodes.Service + requirements: + - interaction: d1t1 + s2t1: + type: micro.nodes.Service + requirements: + - interaction: d1t1 + s2t2: + type: micro.nodes.Service + requirements: + - interaction: dt2 + dt2: + type: micro.nodes.Datastore + s1t2: + type: micro.nodes.Service + requirements: + - interaction: dt2 + st3: + type: micro.nodes.Service + requirements: + - interaction: dt3 + dt3: + type: micro.nodes.Datastore + dbt4: + type: micro.nodes.Datastore + s2t4: + type: micro.nodes.Service + requirements: + - interaction: dbt4 + s1t4: + type: micro.nodes.Service + requirements: + - interaction: dbt4 + groups: + Edge: + type: micro.groups.Edge + members: [] + t1t1: + type: micro.groups.Team + members: + - s1t1 + t2t1: + type: micro.groups.Team + members: + - d1t1 + - s2t1 + t2t2: + type: micro.groups.Team + members: + - dt2 + t1t2: + type: micro.groups.Team + members: + - s1t2 + t1t3: + type: micro.groups.Team + members: + - st3 + t2t3: + type: micro.groups.Team + members: + - dt3 + t1t4: + type: micro.groups.Team + members: + - s1t4 + t2t4: + type: micro.groups.Team + members: + - s2t4 + relationship_templates: + t: + type: micro.relationships.InteractsWith + properties: + timeout: true + c: + type: micro.relationships.InteractsWith + properties: + circuit_breaker: true + d: + type: micro.relationships.InteractsWith + properties: + dynamic_discovery: true + tc: + type: micro.relationships.InteractsWith + properties: + timeout: true + circuit_breaker: true + td: + type: micro.relationships.InteractsWith + properties: + timeout: true + dynamic_discovery: true + cd: + type: micro.relationships.InteractsWith + properties: + circuit_breaker: true + dynamic_discovery: true + tcd: + type: micro.relationships.InteractsWith + properties: + timeout: true + circuit_breaker: true + dynamic_discovery: true diff --git a/tests/test_analyser/test_sniffer_sbc.py b/tests/test_analyser/test_sniffer_sbc.py new file mode 100644 index 0000000..322bcb6 --- /dev/null +++ b/tests/test_analyser/test_sniffer_sbc.py @@ -0,0 +1,50 @@ +from unittest import TestCase + +from microfreshener.core.importer import YMLImporter +from microfreshener.core.analyser.sniffer import SharedBoundedContextSmellSniffer +from microfreshener.core.analyser.smell import SharedBoundedContextSmell + + +class TestTightlyCoupledTeamsSmell(TestCase): + + @classmethod + def setUpClass(self): + file = 'data/tests/test_sniffer_sbc.yml' + loader = YMLImporter() + self.micro_model = loader.Import(file) + self.sbcSniffer = SharedBoundedContextSmellSniffer(self.micro_model) + + def test_yes_sbc(self): + team1 = self.micro_model.get_group("t1t1") + smell1 = self.sbcSniffer.snif(team1) + self.assertIsInstance(smell1, SharedBoundedContextSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t1") + smell2 = self.sbcSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_no_sbc_with_external_service(self): + team1 = self.micro_model.get_group("t1t2") + smell1 = self.sbcSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t2") + smell2 = self.sbcSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_no_sbc_if_no_other_db_user(self): + team1 = self.micro_model.get_group("t1t3") + smell1 = self.sbcSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t3") + smell2 = self.sbcSniffer.snif(team2) + self.assertTrue(smell2.isEmpty()) + + def test_yes_sbc_db_without_team(self): + team1 = self.micro_model.get_group("t1t4") + smell1 = self.sbcSniffer.snif(team1) + self.assertIsInstance(smell1, SharedBoundedContextSmell) + self.assertFalse(smell1.isEmpty()) + team2 = self.micro_model.get_group("t2t4") + smell2 = self.sbcSniffer.snif(team2) + self.assertIsInstance(smell2, SharedBoundedContextSmell) + self.assertFalse(smell2.isEmpty()) From 7f925cd982df39572b00edcda88826777c8cd112 Mon Sep 17 00:00:00 2001 From: meek Date: Thu, 14 Mar 2024 15:36:37 +0100 Subject: [PATCH 6/7] SBC sniffer and test fixes --- microfreshener/core/analyser/sniffer.py | 19 ++++++------------- tests/test_analyser/test_sniffer_sbc.py | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/microfreshener/core/analyser/sniffer.py b/microfreshener/core/analyser/sniffer.py index e1777c1..6304550 100644 --- a/microfreshener/core/analyser/sniffer.py +++ b/microfreshener/core/analyser/sniffer.py @@ -197,16 +197,11 @@ class SharedBoundedContextSmellSniffer(GroupSmellSniffer): def __str__(self): return 'SharedBoundedContextSmellSniffer({})'.format(super(GroupSmellSniffer, self).__str__()) - def _is_datastore_linked_to_other_squads(self, node, nsquads, *args, **kwargs): - squads = [] + def _is_datastore_linked_to_other_squads(self, node, allowedSquad): for link in node.incoming_interactions: - source_node = link.source - source_squad = self.micro_model.squad_of(source_node) - if source_squad is not None: - if source_squad not in squads and source_squad not in kwargs.get('exclude', []): - squads.append(source_squad) - if len(squads) > nsquads: - return True + source_squad = self.micro_model.squad_of(link.source) + if source_squad is not None and source_squad is not allowedSquad: + return True return False @visitor(Team) @@ -219,8 +214,6 @@ def snif(self, group: Team) -> SharedBoundedContextSmell: elif(isinstance(node, Service)): for relationship in node.interactions: target_node = relationship.target - if isinstance(target_node, Datastore): - target_squad = self.micro_model.squad_of(target_node) - if target_squad is not group and self._is_datastore_linked_to_other_squads(target_node, 1, exclude=group): - smell.addLinkCause(relationship) + if isinstance(target_node, Datastore) and self._is_datastore_linked_to_other_squads(target_node, group): + smell.addLinkCause(relationship) return smell diff --git a/tests/test_analyser/test_sniffer_sbc.py b/tests/test_analyser/test_sniffer_sbc.py index 322bcb6..7f1efc9 100644 --- a/tests/test_analyser/test_sniffer_sbc.py +++ b/tests/test_analyser/test_sniffer_sbc.py @@ -5,7 +5,7 @@ from microfreshener.core.analyser.smell import SharedBoundedContextSmell -class TestTightlyCoupledTeamsSmell(TestCase): +class TestSharedBoundedContextSmell(TestCase): @classmethod def setUpClass(self): From 525df4df1d8610ae8d71d3c12b1ac71cd915273a Mon Sep 17 00:00:00 2001 From: meek Date: Fri, 5 Apr 2024 22:20:58 +0200 Subject: [PATCH 7/7] Smell detection aligned with latest definitions --- data/tests/test_sniffer_sbc.yml | 11 +++++ data/tests/test_sniffer_slt.yml | 54 ++++++++++++++++++++++++ microfreshener/core/analyser/costants.py | 4 +- microfreshener/core/analyser/smell.py | 8 ++-- microfreshener/core/analyser/sniffer.py | 31 +++++++------- tests/test_analyser/test_sniffer_sbc.py | 27 ++++++++---- tests/test_analyser/test_sniffer_slt.py | 20 ++++++++- tests/test_analyser/test_sniffer_tct.py | 3 +- 8 files changed, 125 insertions(+), 33 deletions(-) diff --git a/data/tests/test_sniffer_sbc.yml b/data/tests/test_sniffer_sbc.yml index 78cadec..b0e5a34 100644 --- a/data/tests/test_sniffer_sbc.yml +++ b/data/tests/test_sniffer_sbc.yml @@ -40,6 +40,12 @@ topology_template: type: micro.nodes.Service requirements: - interaction: dbt4 + st5: + type: micro.nodes.Service + requirements: + - interaction: dbt5 + dbt5: + type: micro.nodes.Datastore groups: Edge: type: micro.groups.Edge @@ -77,6 +83,11 @@ topology_template: type: micro.groups.Team members: - s2t4 + tt5: + type: micro.groups.Team + members: + - st5 + - dbt5 relationship_templates: t: type: micro.relationships.InteractsWith diff --git a/data/tests/test_sniffer_slt.yml b/data/tests/test_sniffer_slt.yml index e402ef0..a093582 100644 --- a/data/tests/test_sniffer_slt.yml +++ b/data/tests/test_sniffer_slt.yml @@ -68,7 +68,34 @@ topology_template: - interaction: mr2t8 mr2t8: type: micro.nodes.MessageRouter + st9: + type: micro.nodes.Service + requirements: + - interaction: d2t9 + d1t9: + type: micro.nodes.Datastore + d2t9: + type: micro.nodes.Datastore + mr1t10: + type: micro.nodes.MessageRouter + mr2t10: + type: micro.nodes.MessageRouter + st10: + type: micro.nodes.Service + requirements: + - interaction: mr2t10 + st11: + type: micro.nodes.Service + requirements: + - interaction: mb2t11 + mb1t11: + type: micro.nodes.MessageBroker + mb2t11: + type: micro.nodes.MessageBroker groups: + Edge: + type: micro.groups.Edge + members: [] t1t1: type: micro.groups.Team members: @@ -133,6 +160,33 @@ topology_template: members: - mr1t8 - mr2t8 + t1t9: + type: micro.groups.Team + members: + - d1t9 + - st9 + t2t9: + type: micro.groups.Team + members: + - d2t9 + t1t11: + type: micro.groups.Team + members: + - mb1t11 + - st11 + t2t11: + type: micro.groups.Team + members: + - mb2t11 + t1t10: + type: micro.groups.Team + members: + - mr1t10 + - st10 + t2t10: + type: micro.groups.Team + members: + - mr2t10 relationship_templates: t: type: micro.relationships.InteractsWith diff --git a/microfreshener/core/analyser/costants.py b/microfreshener/core/analyser/costants.py index 1f6a2c5..9dd2fe6 100644 --- a/microfreshener/core/analyser/costants.py +++ b/microfreshener/core/analyser/costants.py @@ -1,5 +1,5 @@ SMELLS_NAME = SMELL_ENDPOINT_BASED_SERVICE_INTERACTION, SMELL_WOBBLY_SERVICE_INTERACTION_SMELL, SMELL_SHARED_PERSISTENCY, SMELL_NO_API_GATEWAY, SMELL_SINGLE_LAYER_TEAMS, SMELL_MULTIPLE_SERVICES_IN_ONE_CONTAINER, SMELL_ESB_MISUSE, SMELL_TIGHTLY_COUPLED_TEAMS, SMELL_SHARED_BOUNDED_CONTEXT =\ "Endpoint-based-service-interaction", "Wobbly-service-interaction", "Shared-persistency", "No-api-gateway", "Single-layer-teams", "Multiple-services-in-one-container", "ESB-misuse", "Tightly-coupled-teams", "Shared-bounded-context" -REFACTORING_NAMES = REFACTORING_ADD_SERVICE_DISCOVERY, REFACTORING_ADD_MESSAGE_ROUTER, REFACTORING_ADD_MESSAGE_BROKER, REFACTORING_ADD_CIRCUIT_BREAKER, REFACTORING_USE_TIMEOUT, REFACTORING_MERGE_SERVICES, REFACTORING_SPLIT_DATABASE, REFACTORING_ADD_DATA_MANAGER, REFACTORING_ADD_API_GATEWAY, REFACTORING_SPLIT_SERVICES, REFACTORING_SPLIT_TEAMS_BY_SERVICE, REFACTORING_SPLIT_TEAMS_BY_COUPLING, REFACTORING_MERGE_TEAMS =\ - "Add-service-discovery", "Add-message-router", "Add-message-broker", "Add-circuit-breaker", "Use-timeout", "Merge-service", "Split-Datastore", "Add-data-manager", "Add-api-gateway", "Split-service-in-two-pods", "Split-teams-by-service", "Split-teams-by-coupling", "Merge-teams" +REFACTORING_NAMES = REFACTORING_ADD_SERVICE_DISCOVERY, REFACTORING_ADD_MESSAGE_ROUTER, REFACTORING_ADD_MESSAGE_BROKER, REFACTORING_ADD_CIRCUIT_BREAKER, REFACTORING_USE_TIMEOUT, REFACTORING_MERGE_SERVICES, REFACTORING_SPLIT_DATABASE, REFACTORING_ADD_DATA_MANAGER, REFACTORING_ADD_API_GATEWAY, REFACTORING_SPLIT_SERVICES, REFACTORING_SPLIT_TEAMS_BY_MICROSERVICE, REFACTORING_SPLIT_TEAMS_BY_COUPLING, REFACTORING_REORGANIZE_TEAMS_BY_BOUNDED_CONTEXT, REFACTORING_SPLIT_BOUNDED_CONTEXT_BY_TEAMS =\ + "Add-service-discovery", "Add-message-router", "Add-message-broker", "Add-circuit-breaker", "Use-timeout", "Merge-service", "Split-Datastore", "Add-data-manager", "Add-api-gateway", "Split-service-in-two-pods", "Split-teams-by-microservice", "Split-teams-by-coupling", "Reorganize-teams-by-bounded-contexts", "Split-bounded-context-by-teams" diff --git a/microfreshener/core/analyser/smell.py b/microfreshener/core/analyser/smell.py index 93e30d7..7af818f 100644 --- a/microfreshener/core/analyser/smell.py +++ b/microfreshener/core/analyser/smell.py @@ -1,7 +1,7 @@ from ..model import Relationship from ..model import nodes from .costants import SMELL_ENDPOINT_BASED_SERVICE_INTERACTION, SMELL_NO_API_GATEWAY, SMELL_SHARED_PERSISTENCY, SMELL_WOBBLY_SERVICE_INTERACTION_SMELL, SMELL_SINGLE_LAYER_TEAMS, SMELL_MULTIPLE_SERVICES_IN_ONE_CONTAINER, SMELL_TIGHTLY_COUPLED_TEAMS, SMELL_SHARED_BOUNDED_CONTEXT -from .costants import REFACTORING_ADD_SERVICE_DISCOVERY, REFACTORING_ADD_MESSAGE_ROUTER, REFACTORING_ADD_MESSAGE_BROKER, REFACTORING_ADD_CIRCUIT_BREAKER, REFACTORING_USE_TIMEOUT, REFACTORING_MERGE_SERVICES, REFACTORING_SPLIT_DATABASE, REFACTORING_ADD_DATA_MANAGER, REFACTORING_ADD_API_GATEWAY, REFACTORING_SPLIT_SERVICES, REFACTORING_SPLIT_TEAMS_BY_SERVICE, REFACTORING_SPLIT_TEAMS_BY_COUPLING, REFACTORING_MERGE_TEAMS +from .costants import REFACTORING_ADD_SERVICE_DISCOVERY, REFACTORING_ADD_MESSAGE_ROUTER, REFACTORING_ADD_MESSAGE_BROKER, REFACTORING_ADD_CIRCUIT_BREAKER, REFACTORING_USE_TIMEOUT, REFACTORING_MERGE_SERVICES, REFACTORING_SPLIT_DATABASE, REFACTORING_ADD_DATA_MANAGER, REFACTORING_ADD_API_GATEWAY, REFACTORING_SPLIT_SERVICES, REFACTORING_SPLIT_TEAMS_BY_MICROSERVICE, REFACTORING_SPLIT_TEAMS_BY_COUPLING, REFACTORING_REORGANIZE_TEAMS_BY_BOUNDED_CONTEXT, REFACTORING_SPLIT_BOUNDED_CONTEXT_BY_TEAMS class Smell(object): def __init__(self, name): @@ -143,7 +143,7 @@ def __str__(self): def to_dict(self): sup_dict = super(SingleLayerTeamsSmell, self).to_dict() return {**sup_dict, **{"refactorings": [ - {"name": REFACTORING_SPLIT_TEAMS_BY_SERVICE, "description": "Split the teams by service."}, + {"name": REFACTORING_SPLIT_TEAMS_BY_MICROSERVICE, "description": "Split the teams by microservice."}, ]}} class MultipleServicesInOneContainerSmell(NodeSmell): @@ -188,6 +188,6 @@ def __str__(self): def to_dict(self): sup_dict = super(SharedBoundedContextSmell, self).to_dict() return {**sup_dict, **{"refactorings": [ - {"name": REFACTORING_SPLIT_DATABASE, "description": "Split the database among the user teams."}, - {"name": REFACTORING_MERGE_TEAMS, "description": "Merge the teams."}, + {"name": REFACTORING_REORGANIZE_TEAMS_BY_BOUNDED_CONTEXT, "description": "Move the bounded context inside team borders."}, + {"name": REFACTORING_SPLIT_BOUNDED_CONTEXT_BY_TEAMS, "description": "Split bounded context among teams."}, ]}} \ No newline at end of file diff --git a/microfreshener/core/analyser/sniffer.py b/microfreshener/core/analyser/sniffer.py index 6304550..1772271 100644 --- a/microfreshener/core/analyser/sniffer.py +++ b/microfreshener/core/analyser/sniffer.py @@ -106,6 +106,12 @@ class SingleLayerTeamsSmellSniffer(GroupSmellSniffer): def __str__(self): return 'SingleLayerTeamsSmellSniffer({})'.format(super(GroupSmellSniffer, self).__str__()) + def _team_not_containing_type(self, group: Team, type): + for node in group.members: + if isinstance(node, type): + return False + return True + def _not_internally_linked_to_service(self, node): same_squad = self.micro_model.squad_of(node) for link in (node.interactions + node.incoming_interactions): @@ -116,7 +122,6 @@ def _not_internally_linked_to_service(self, node): return False return True - @visitor(Team) def snif(self, group: Team) -> SingleLayerTeamsSmell: smell = SingleLayerTeamsSmell(group) @@ -126,11 +131,8 @@ def snif(self, group: Team) -> SingleLayerTeamsSmell: target_node = relationship.target source_squad = self.micro_model.squad_of(source_node) target_squad = self.micro_model.squad_of(target_node) - if (source_squad is not None and - target_squad is not None and - source_squad != target_squad and - isinstance(source_node, Service) and - not isinstance(target_node, Service) and + if ((source_squad is not None and target_squad is not None and source_squad != target_squad) and + (isinstance(source_node, Service) and not isinstance(target_node, Service) and self._team_not_containing_type(source_squad, type(target_node))) and (isinstance(target_node, Datastore) or self._not_internally_linked_to_service(target_node))): smell.addLinkCause(relationship) return smell @@ -197,23 +199,20 @@ class SharedBoundedContextSmellSniffer(GroupSmellSniffer): def __str__(self): return 'SharedBoundedContextSmellSniffer({})'.format(super(GroupSmellSniffer, self).__str__()) - def _is_datastore_linked_to_other_squads(self, node, allowedSquad): - for link in node.incoming_interactions: - source_squad = self.micro_model.squad_of(link.source) - if source_squad is not None and source_squad is not allowedSquad: - return True - return False - @visitor(Team) def snif(self, group: Team) -> SharedBoundedContextSmell: smell = SharedBoundedContextSmell(group) for node in group.members: if(isinstance(node, Datastore)): - if self._is_datastore_linked_to_other_squads(node, 2): - smell.addLinkCause(relationship) + for relationship in node.incoming_interactions: + source_node = relationship.source + source_squad = self.micro_model.squad_of(source_node) + if (source_squad is not None and source_squad is not group): + smell.addLinkCause(relationship) elif(isinstance(node, Service)): for relationship in node.interactions: target_node = relationship.target - if isinstance(target_node, Datastore) and self._is_datastore_linked_to_other_squads(target_node, group): + target_squad = self.micro_model.squad_of(target_node) + if (isinstance(target_node, Datastore) and target_squad is not group): smell.addLinkCause(relationship) return smell diff --git a/tests/test_analyser/test_sniffer_sbc.py b/tests/test_analyser/test_sniffer_sbc.py index 7f1efc9..27c5f6f 100644 --- a/tests/test_analyser/test_sniffer_sbc.py +++ b/tests/test_analyser/test_sniffer_sbc.py @@ -4,12 +4,13 @@ from microfreshener.core.analyser.sniffer import SharedBoundedContextSmellSniffer from microfreshener.core.analyser.smell import SharedBoundedContextSmell +import os class TestSharedBoundedContextSmell(TestCase): @classmethod def setUpClass(self): - file = 'data/tests/test_sniffer_sbc.yml' + file = os.getcwd() + '/data/tests/test_sniffer_sbc.yml' loader = YMLImporter() self.micro_model = loader.Import(file) self.sbcSniffer = SharedBoundedContextSmellSniffer(self.micro_model) @@ -21,23 +22,28 @@ def test_yes_sbc(self): self.assertFalse(smell1.isEmpty()) team2 = self.micro_model.get_group("t2t1") smell2 = self.sbcSniffer.snif(team2) - self.assertTrue(smell2.isEmpty()) + self.assertIsInstance(smell2, SharedBoundedContextSmell) + self.assertFalse(smell2.isEmpty()) - def test_no_sbc_with_external_service(self): + def test_yes_sbc_with_external_service(self): team1 = self.micro_model.get_group("t1t2") smell1 = self.sbcSniffer.snif(team1) - self.assertTrue(smell1.isEmpty()) + self.assertIsInstance(smell1, SharedBoundedContextSmell) + self.assertFalse(smell1.isEmpty()) team2 = self.micro_model.get_group("t2t2") smell2 = self.sbcSniffer.snif(team2) - self.assertTrue(smell2.isEmpty()) + self.assertIsInstance(smell2, SharedBoundedContextSmell) + self.assertFalse(smell2.isEmpty()) - def test_no_sbc_if_no_other_db_user(self): + def test_yes_sbc_if_no_other_db_user(self): team1 = self.micro_model.get_group("t1t3") smell1 = self.sbcSniffer.snif(team1) - self.assertTrue(smell1.isEmpty()) + self.assertIsInstance(smell1, SharedBoundedContextSmell) + self.assertFalse(smell1.isEmpty()) team2 = self.micro_model.get_group("t2t3") smell2 = self.sbcSniffer.snif(team2) - self.assertTrue(smell2.isEmpty()) + self.assertIsInstance(smell2, SharedBoundedContextSmell) + self.assertFalse(smell2.isEmpty()) def test_yes_sbc_db_without_team(self): team1 = self.micro_model.get_group("t1t4") @@ -48,3 +54,8 @@ def test_yes_sbc_db_without_team(self): smell2 = self.sbcSniffer.snif(team2) self.assertIsInstance(smell2, SharedBoundedContextSmell) self.assertFalse(smell2.isEmpty()) + + def test_no_sbc_same_team(self): + team1 = self.micro_model.get_group("tt5") + smell1 = self.sbcSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) diff --git a/tests/test_analyser/test_sniffer_slt.py b/tests/test_analyser/test_sniffer_slt.py index a4816f5..e948b02 100644 --- a/tests/test_analyser/test_sniffer_slt.py +++ b/tests/test_analyser/test_sniffer_slt.py @@ -4,12 +4,13 @@ from microfreshener.core.analyser.sniffer import SingleLayerTeamsSmellSniffer from microfreshener.core.analyser.smell import SingleLayerTeamsSmell +import os class TestSingleLayerTeamsSmell(TestCase): @classmethod def setUpClass(self): - file = 'data/tests/test_sniffer_slt.yml' + file = os.getcwd() + '/data/tests/test_sniffer_slt.yml' loader = YMLImporter() self.micro_model = loader.Import(file) self.sltSniffer = SingleLayerTeamsSmellSniffer(self.micro_model) @@ -78,4 +79,19 @@ def test_yes_slt_with_mr_internally_linked_to_mr(self): self.assertFalse(smell1.isEmpty()) team2 = self.micro_model.get_group("t2t8") smell2 = self.sltSniffer.snif(team2) - self.assertTrue(smell2.isEmpty()) \ No newline at end of file + self.assertTrue(smell2.isEmpty()) + + def test_no_slt_with_owned_db(self): + team1 = self.micro_model.get_group("t1t9") + smell1 = self.sltSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) + + def test_no_slt_with_owned_mr(self): + team1 = self.micro_model.get_group("t1t10") + smell1 = self.sltSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) + + def test_no_slt_with_owned_mb(self): + team1 = self.micro_model.get_group("t1t11") + smell1 = self.sltSniffer.snif(team1) + self.assertTrue(smell1.isEmpty()) \ No newline at end of file diff --git a/tests/test_analyser/test_sniffer_tct.py b/tests/test_analyser/test_sniffer_tct.py index 1a108fd..16aa379 100644 --- a/tests/test_analyser/test_sniffer_tct.py +++ b/tests/test_analyser/test_sniffer_tct.py @@ -4,12 +4,13 @@ from microfreshener.core.analyser.sniffer import TightlyCoupledTeamsSmellSniffer from microfreshener.core.analyser.smell import TightlyCoupledTeamsSmell +import os class TestTightlyCoupledTeamsSmell(TestCase): @classmethod def setUpClass(self): - file = 'data/tests/test_sniffer_tct.yml' + file = os.getcwd() + '/data/tests/test_sniffer_tct.yml' loader = YMLImporter() self.micro_model = loader.Import(file) self.tctSniffer = TightlyCoupledTeamsSmellSniffer(self.micro_model)