Repository: zyskarch/pytestarch (language: python)

Issue:
New line character in error message not respected
os.sep does not seem to work


Discussion / hints:

Fix patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 1355528..1623167 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -4,6 +4,9 @@ This project uses semantic versioning and follows [keep a changelog](https://kee
 
 
 ## [Unreleased]
+## [1.1.1] -- 2022-10-04
+### Fixed
+- Line separator for rule violation messages
 
 ## [1.1.0] -- 2022-10-02
 ### Added
diff --git a/pyproject.toml b/pyproject.toml
index fabb34e..4923b3b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "PyTestArch"
-version = "1.1.0"
+version = "1.1.1"
 description = "Test framework for software architecture based on imports between modules"
 authors = ["zyskarch <zyskarch@gmail.com>"]
 maintainers = ["zyskarch <zyskarch@gmail.com>"]


Test patch:
diff --git a/src/pytestarch/query_language/base_language.py b/src/pytestarch/query_language/base_language.py
index 126ae0a..db8a5e8 100644
--- a/src/pytestarch/query_language/base_language.py
+++ b/src/pytestarch/query_language/base_language.py
@@ -1,6 +1,5 @@
 from __future__ import annotations
 
-import os
 from abc import ABC, abstractmethod
 from typing import Callable, Generic, List, Optional, Type, TypeVar, Union
 
@@ -296,4 +295,4 @@ def _create_rule_violation_message(self, rule_violations: RuleViolations) -> str
         single_violation_messages = message_generator.create_rule_violation_messages(
             rule_violations
         )
-        return os.sep.join(single_violation_messages)
+        return "\n".join(single_violation_messages)
diff --git a/src/pytestarch/query_language/message_generator.py b/src/pytestarch/query_language/message_generator.py
index 5fe3890..1094de5 100644
--- a/src/pytestarch/query_language/message_generator.py
+++ b/src/pytestarch/query_language/message_generator.py
@@ -77,15 +77,15 @@ def create_rule_violation_messages(
             rule_violations: to convert to human-readable format
 
         Returns:
-            list of messages, each representing a rule violation
+            set of messages, each representing a rule violation
         """
-        messages = []
+        messages = set()
         for message in self._create_violation_messages(rule_violations):
-            messages.append(
+            messages.add(
                 f"{message.rule_subject} {message.rule_verb} {message.rule_object}."
             )
 
-        return sorted(messages)
+        return sorted(list(messages))
 
     def _create_violation_messages(
         self, rule_violations: RuleViolations
diff --git a/tests/test_integration.py b/tests/test_integration.py
index 94f49a3..b1b2458 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -398,7 +398,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
         .import_modules_that()
         .are_sub_modules_of(B),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC".',
         id="named should only import submodule",
     ),
@@ -420,7 +420,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
         .import_modules_that()
         .are_sub_modules_of(B),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC".',
         id="submodule should only import submodule",
     ),
@@ -602,7 +602,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
         .import_modules_except_modules_that()
         .are_sub_modules_of(B),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC"',
         id="named should not import except submodule",
     ),
@@ -624,7 +624,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
         .import_modules_except_modules_that()
         .are_sub_modules_of(B),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC".',
         id="submodule should not import except submodule",
     ),
@@ -715,7 +715,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
         .should_not()
         .be_imported_by_modules_that()
         .are_named(A),
-        '"src.moduleC.fileC" is imported by "src.moduleA.submoduleA2.fileA2".',
+        '"src.moduleC.fileC" is imported by "src.moduleA.fileA".\n"src.moduleC.fileC" is imported by "src.moduleA.submoduleA2.fileA2"',
         id="named should not be imported by named",
     ),
     pytest.param(
@@ -906,7 +906,7 @@ def test_edges_correctly_calculated_for_level_3_module_path_no_external_dependen
         .be_imported_by_modules_except_modules_that()
         .are_sub_modules_of(FILE_A2),
         '"src.moduleC.fileC" is imported by "src.moduleA.fileA".'
-        + os.sep
+        + "\n"
         + '"src.moduleC.fileC" is imported by "src.moduleA.submoduleA2.fileA2".',
         id="submodule should not be imported by except submodule",
     ),
@@ -982,7 +982,7 @@ def test_rule_violated_raises_proper_error_message(
         .import_modules_that()
         .are_sub_modules_of([B, B2]),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC".',
         id="named should only import submodule",
     ),
@@ -1004,7 +1004,7 @@ def test_rule_violated_raises_proper_error_message(
         .import_modules_that()
         .are_sub_modules_of([B]),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC".',
         id="submodule should only import submodule",
     ),
@@ -1186,7 +1186,7 @@ def test_rule_violated_raises_proper_error_message(
         .import_modules_except_modules_that()
         .are_sub_modules_of([B, B2]),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC"',
         id="named should not import except submodule",
     ),
@@ -1208,7 +1208,7 @@ def test_rule_violated_raises_proper_error_message(
         .import_modules_except_modules_that()
         .are_sub_modules_of([B]),
         '"src.moduleA.fileA" imports "src.moduleC.fileC".'
-        + os.sep
+        + "\n"
         + '"src.moduleA.submoduleA2.fileA2" imports "src.moduleC.fileC".',
         id="submodule should not import except submodule",
     ),
@@ -1299,8 +1299,8 @@ def test_rule_violated_raises_proper_error_message(
         .should_not()
         .be_imported_by_modules_that()
         .are_named([A, FILE_A2]),
-        '"src.moduleC.fileC" is imported by "src.moduleA.submoduleA2.fileA2".'
-        + os.sep
+        '"src.moduleC.fileC" is imported by "src.moduleA.fileA".'
+        + "\n"
         + '"src.moduleC.fileC" is imported by "src.moduleA.submoduleA2.fileA2".',
         id="named should not be imported by named",
     ),
@@ -1492,7 +1492,7 @@ def test_rule_violated_raises_proper_error_message(
         .be_imported_by_modules_except_modules_that()
         .are_sub_modules_of([FILE_A2]),
         '"src.moduleC.fileC" is imported by "src.moduleA.fileA".'
-        + os.sep
+        + "\n"
         + '"src.moduleC.fileC" is imported by "src.moduleA.submoduleA2.fileA2".',
         id="submodule should not be imported by except submodule",
     ),