Skip to content

Commit

Permalink
Merge pull request #600 from gauge-sh/e2e-tests-2-6-25
Browse files Browse the repository at this point in the history
Add a couple E2E on example directory using many features
  • Loading branch information
emdoyle authored Feb 6, 2025
2 parents 2f5798b + 4877e83 commit f9fe73e
Show file tree
Hide file tree
Showing 32 changed files with 249 additions and 0 deletions.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# tach-ignore
from module1.submodule1.api import Api

from module1.submodule1.api import OtherApi
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# tach-ignore
from module2.service import Module2Service
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[root]
depends_on = []
layer = "mid"

[[interfaces]]
expose = []
from = ["<domain_root>"]
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
OTHER_FIELD = "value"

INSTALLED_APPS = [
"module1",
"module3",
"module5",
]
3 changes: 3 additions & 0 deletions python/tests/example/many_features/real_src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# tach-ignore

from external import something
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .api import MyApi

from module3 import content

from module3 import anything
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from module5 import something


class MyModel:
field = ForeignKey("module3.content")
field2 = ForeignKey("module3.anything")
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[root]
depends_on = ["api", "//module5"]
layer = "mid"

[[modules]]
path = "api"
depends_on = ["submodule1"]
layer = "mid"

[[modules]]
path = "submodule1"
depends_on = []
layer = "mid"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import module3
import module4
import module1
import module1.submodule1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import outer_module
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import module1

from .submodule1.api import Api
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[root]
depends_on = []
layer = "low"

[[modules]]
path = "submodule1"
depends_on = []
layer = "low"
utility = true

[[interfaces]]
expose = ["content"]
from = ["<domain_root>"]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import module2
1 change: 1 addition & 0 deletions python/tests/example/many_features/src/no.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalidsyntax...
Empty file.
Empty file.
Empty file.
37 changes: 37 additions & 0 deletions python/tests/example/many_features/tach.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
exclude = ["src", "**/tests"]
exact = true
forbid_circular_dependencies = true

source_roots = [
"real_src",
"other_src_root"
]

layers = [
"high",
"mid",
"low",
"lowest",
"hightest"
]

[[modules]]
path = "module4"
depends_on = []
layer = "hightest"

[[modules]]
path = "module2"
depends_on = []
layer = "high"

[[modules]]
path = "outer_module"
unchecked = true

[rules]
unused_ignore_directives = "error"
require_ignore_directive_reasons = "warn"

[plugins.django]
settings_module = "django_settings"
94 changes: 94 additions & 0 deletions python/tests/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,97 @@ def test_distributed_config_example_dir(example_dir, capfd):
in captured.err
)
assert "project/top_level.py" in captured.err


def _check_expected_messages(section_text: str, expected_messages: list[tuple]) -> None:
"""Helper to verify all expected messages appear in a section of output text.
Args:
section_text: The text section to check
expected_messages: List of tuples containing substrings that should appear together in a line
"""
lines = iter(section_text.split("\n"))
substrs = iter(expected_messages)
current_substrs = next(substrs, None)

for line in lines:
if not current_substrs:
break

if all(substr.lower() in line.lower() for substr in current_substrs):
current_substrs = next(substrs, None)

assert current_substrs is None, (
f"Not all expected messages were found: {list(substrs)} in section: {section_text}"
)


def test_many_features_example_dir(example_dir, capfd):
project_root = example_dir / "many_features"
project_config = parse_project_config(root=project_root)
assert project_config is not None

with pytest.raises(SystemExit) as exc_info:
tach_check(
project_root=project_root,
project_config=project_config,
exclude_paths=project_config.exclude,
)
assert exc_info.value.code == 1

captured = capfd.readouterr()
general_header = captured.err.index("General\n")
interfaces_header = captured.err.index("Interfaces\n")
dependencies_header = captured.err.index("Internal Dependencies\n")

general_section = captured.err[general_header:interfaces_header]
interfaces_section = captured.err[interfaces_header:dependencies_header]
dependencies_section = captured.err[dependencies_header:]

expected_general = [
(
"[WARN]",
"other_src_root/module1/api.py",
"ignore directive",
"missing a reason",
),
(
"[WARN]",
"other_src_root/module4/service.py",
"ignore directive",
"missing a reason",
),
("[WARN]", "real_src/main.py", "ignore directive", "missing a reason"),
("[FAIL]", "other_src_root/module1/api.py", "ignore directive", "unused"),
("[FAIL]", "real_src/main.py", "ignore directive", "unused"),
]

expected_interfaces = [
(
"[FAIL]",
"real_src/module1/__init__.py",
"module3.anything",
"public interface",
),
(
"[FAIL]",
"real_src/module1/controller.py",
"module5.something",
"public interface",
),
(
"[FAIL]",
"real_src/module1/controller.py",
"module3.anything",
"public interface",
),
]

expected_dependencies = [
("[FAIL]", "real_src/module2/service.py", "outer_module", "module2"),
("[FAIL]", "real_src/module3/__init__.py", "'low'", "lower than", "'mid'"),
]

_check_expected_messages(general_section, expected_general)
_check_expected_messages(interfaces_section, expected_interfaces)
_check_expected_messages(dependencies_section, expected_dependencies)
48 changes: 48 additions & 0 deletions python/tests/test_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,51 @@ def test_distributed_config_dir(example_dir, capfd):
"project.module_two",
"project.module_one",
}


def test_many_features_example_dir(example_dir, capfd):
project_root = example_dir / "many_features"

with tempfile.TemporaryDirectory() as temp_dir:
temp_project_root = Path(temp_dir) / "many_features"
shutil.copytree(project_root, temp_project_root)

project_config = parse_project_config(root=temp_project_root)
assert project_config is not None

with pytest.raises(SystemExit) as exc_info:
tach_sync(
project_root=temp_project_root,
project_config=project_config,
exclude_paths=project_config.exclude,
)

assert exc_info.value.code == 0
captured = capfd.readouterr()
assert "✅" in captured.out # success state

project_config = parse_project_config(root=temp_project_root)
assert project_config is not None

modules = project_config.filtered_modules([])
assert len(modules) == 9

module2 = next(module for module in modules if module.path == "module2")
assert set(map(lambda dep: dep.path, module2.depends_on)) == {"outer_module"}

module3 = next(module for module in modules if module.path == "module3")
assert set(map(lambda dep: dep.path, module3.depends_on)) == {"module1"}

assert (
'"//module1"'
in (
temp_project_root / "real_src" / "module3" / "tach.domain.toml"
).read_text()
)

assert (
'"<domain_root>"'
in (
temp_project_root / "real_src" / "module3" / "tach.domain.toml"
).read_text()
)

0 comments on commit f9fe73e

Please sign in to comment.