Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Run test targets
run: |
bazel run --lockfile_mode=error //:ide_support
bazel test --lockfile_mode=error //src/... //score_pytest/...
bazel test --lockfile_mode=error //...

- name: Prepare bundled consumer report
if: always()
Expand Down
181 changes: 152 additions & 29 deletions scripts_bazel/tests/generate_sourcelinks_cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,63 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

# β•“ β•–
# β•‘ Some parts are generated by Gemini β•‘
# β•™ β•œ

"""Tests for generate_sourcelinks_cli.py"""

import json
import subprocess
import sys
from pathlib import Path

import pytest

import scripts_bazel.generate_sourcelinks_cli
from src.extensions.score_source_code_linker.needlinks import is_metadata

_MY_PATH = Path(__file__).parent


def test_generate_sourcelinks_cli_basic(tmp_path: Path) -> None:
def assert_json_internal_types(input: list[dict[str, str | int]]):
for entry in input:
assert "file" in entry
assert "line" in entry
assert "tag" in entry
assert "need" in entry
assert "full_line" in entry

assert isinstance(entry["file"], str)
assert isinstance(entry["line"], int)
assert isinstance(entry["tag"], str)
assert isinstance(entry["need"], str)
assert isinstance(entry["full_line"], str)


# Unit test generated by Gemini.
@pytest.mark.parametrize(
"input_path, expected_output",
[
# Case 1: Path starts with "external/" and has a project name
(Path("external/score_docs_as_code+/docs/index.md"), Path("docs/index.md")),
# Case 2: Path does NOT start with "external/"
(Path("src/main.py"), Path("src/main.py")),
# Case 3: Path has "external" elsewhere in the string (should not be removed)
(Path("my_external_data/file.txt"), Path("my_external_data/file.txt")),
# Case 4: Deeply nested path inside an external prefix
(Path("external/repo/subfolder/file.py"), Path("subfolder/file.py")),
# Case 5: Path is exactly "external/" (edge case, returns empty path based on split logic)
(Path("external/"), Path("external")),
],
)
def test_clean_external_prefix(input_path: Path, expected_output: Path):
output = scripts_bazel.generate_sourcelinks_cli.clean_external_prefix(input_path)
assert output == expected_output


def test_generate_sourcelinks_cli_basic(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Test basic functionality of generate_sourcelinks_cli."""
# Create a test source file with a traceability tag
test_file = tmp_path / "test_source.py"
Expand All @@ -36,39 +82,116 @@ def some_function():

output_file = tmp_path / "output.json"

# Execute the script
result = subprocess.run(
[
sys.executable,
_MY_PATH.parent / "generate_sourcelinks_cli.py",
"--output",
str(output_file),
str(test_file),
],
)

assert result.returncode == 0
assert output_file.exists()
test_args: list[Path | str] = [
_MY_PATH.parent
/ "generate_sourcelinks_cli.py", # sys.argv[0] is always the script name
"--output",
str(output_file),
str(test_file),
]
monkeypatch.setattr(sys, "argv", test_args)
result = scripts_bazel.generate_sourcelinks_cli.main()
assert result == 0

# Check the output content
with open(output_file) as f:
data: list[dict[str, str | int]] = json.load(f)
assert isinstance(data, list)
assert len(data) > 0
# The first dictionary has to be metadata
assert len(data) == 2
assert is_metadata(data[0])
assert data[0]["repo_name"] == "local_repo"
# hash & url can not be set in this script therefore HAVE to be empty
assert data[0]["hash"] == ""
assert data[0]["url"] == ""

# Verify schema of each entry
for entry in data:
assert "file" in entry
assert "line" in entry
assert "tag" in entry
assert "need" in entry
assert "full_line" in entry
assert_json_internal_types(data[1:])

# Verify types
assert isinstance(entry["file"], str)
assert isinstance(entry["line"], int)
assert isinstance(entry["tag"], str)
assert isinstance(entry["need"], str)
assert isinstance(entry["full_line"], str)
assert data[1]["need"] == "tool_req__docs_arch_types"

assert any(entry["need"] == "tool_req__docs_arch_types" for entry in data)

def test_generate_sourcelinks_cli_parse_external_module(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems fine, for the future: using fakefs would make the test slightly more readable, and a lot more self-contained

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have not thought about that but yes that could be a good improvement

):
# 1. Create the 'external' directory inside the temp path
external_root = tmp_path / "external"
external_root.mkdir()

# 2. Create your file inside that 'external' directory
test_file = external_root / "score_baselibs+" / "src" / "source_file1.py"
test_file.parent.mkdir(parents=True)
test_file.write_text("content")

# 3. Create the path relative to tmp_path so it starts with 'external/'
# Use .relative_to(tmp_path) to get 'external/score_docs_as_code+/...'
test_file.write_text(
"""
# Some code here
# req-Id: tool_req__docs_arch_types
def some_function():
pass
"""
)
output_file = tmp_path / "output.json"
monkeypatch.chdir(tmp_path)
relative_test_file = test_file.relative_to(tmp_path)
test_args: list[Path | str] = [
_MY_PATH.parent
/ "generate_sourcelinks_cli.py", # sys.argv[0] is always the script name
"--output",
str(output_file),
str(relative_test_file),
]
monkeypatch.setattr(sys, "argv", test_args)
result = scripts_bazel.generate_sourcelinks_cli.main()
assert result == 0
with open(output_file) as f:
data: list[dict[str, str | int]] = json.load(f)
assert isinstance(data, list)
assert len(data) == 2
# The first dictionary has to be metadata
assert is_metadata(data[0])
assert data[0]["repo_name"] == "score_baselibs"
# hash & url can not be set in this script therefore HAVE to be empty
assert data[0]["hash"] == ""
assert data[0]["url"] == ""

# Verify schema of each entry
assert_json_internal_types(data[1:])


def test_generate_sourcelinks_cli_file_not_exists(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
):
external_root = tmp_path / "external"
external_root.mkdir()

# 2. Create your file inside that 'external' directory
test_file = external_root / "score_baselibs+" / "src" / "source_file1.py"
test_file.parent.mkdir(parents=True)
test_file.write_text("content")

# 3. Create the path relative to tmp_path so it starts with 'external/'
# Use .relative_to(tmp_path) to get 'external/score_docs_as_code+/...'
test_file.write_text(
"""
# Some code here
# req-Id: tool_req__docs_arch_types
def some_function():
pass
"""
)
output_file = tmp_path / "output.json"
# BY not changing directory (like above) we can FORCE the file to not exists
relative_test_file = test_file.relative_to(tmp_path)
test_args: list[Path | str] = [
_MY_PATH.parent
/ "generate_sourcelinks_cli.py", # sys.argv[0] is always the script name
"--output",
str(output_file),
str(relative_test_file),
]
monkeypatch.setattr(sys, "argv", test_args)
with pytest.raises(AssertionError):
scripts_bazel.generate_sourcelinks_cli.main()
Loading
Loading