Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration tests #9

Merged
merged 7 commits into from
Apr 5, 2024
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
5 changes: 4 additions & 1 deletion src/semvergit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ def __init__(self, pull_branch: bool = False) -> None:
logger.info("Pulling...")
pull_remote(self.current_repo)
self.versions = self.get_versions()
self.latest_version = max(self.versions)
if self.versions:
self.latest_version = max(self.versions)
else:
self.latest_version = VersionInfo.parse("0.0.0")

def get_versions(self) -> List[VersionInfo]:
"""Get versions."""
Expand Down
13 changes: 12 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ def caplog(caplog: LogCaptureFixture) -> Generator: # pylint: disable=redefined
https://loguru.readthedocs.io/en/stable/resources/migration.html#making-things-work-with-pytest-and-caplog
"""
handler_id = logger.add(caplog.handler, format="{message}")
print(f"logger handler_id: {handler_id}")
yield caplog
logger.remove(handler_id)
logger.remove()


@pytest.fixture(autouse=True)
Expand Down Expand Up @@ -57,6 +58,16 @@ def get_tags_with_prefix(repo: Repo, prefix: str) -> List[str]: # pylint: disab
monkeypatch.setattr("semvergit.app.get_tags_with_prefix", get_tags_with_prefix)


@pytest.fixture()
def mock_get_tags_empty(monkeypatch: MonkeyPatch) -> None:
"""Mock get_tags_with_prefix with empty list."""

def get_tags_with_prefix(repo: Repo, prefix: str) -> List[str]: # pylint: disable=unused-argument
return []

monkeypatch.setattr("semvergit.app.get_tags_with_prefix", get_tags_with_prefix)


@pytest.fixture(autouse=True)
def mock_pull_remote(monkeypatch: MonkeyPatch) -> None:
"""Mock pull_remote."""
Expand Down
44 changes: 44 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,50 @@ def test_app(pull_branch: bool, expected: VersionInfo) -> None:
assert svg.latest_version == VersionInfo(0, 0, 4)


@mark.parametrize(
"dry_run",
[
True,
False,
],
)
@mark.parametrize(
"bump_type, expected_version",
[
(str(BumpType.MAJOR), VersionInfo(1, 0, 0)),
(str(BumpType.MINOR), VersionInfo(0, 1, 0)),
(str(BumpType.PATCH), VersionInfo(0, 0, 1)),
(str(BumpType.PRERELEASE), VersionInfo(0, 0, 1, "dev.1")),
],
)
@mark.parametrize(
"commit_message, auto_message",
[
("testmessage", False),
(None, True),
(None, False),
],
)
# type: ignore[no-untyped-def]
def test_app_no_versions_update( # pylint: disable=too-many-arguments
bump_type: str,
expected_version: VersionInfo,
dry_run: bool,
commit_message: Optional[str],
auto_message: bool,
mock_get_tags_empty, # pylint: disable=unused-argument
) -> None:
"""Test app with no versions."""
svg = SemverGit()
assert svg is not None
assert svg.branch.name == "test_branch"
assert svg.versions == []
assert svg.latest_version == VersionInfo(0, 0, 0)
new_version = svg.update(bump_type, dry_run=dry_run, commit_message=commit_message, auto_message=auto_message)
expected_tag_str = f"{svg.version_prefix}{str(expected_version)}"
assert new_version == expected_tag_str


def check_substring(substring_match: str, strings_list: List[str]) -> bool:
"""Check if list contains substring."""
for item in strings_list:
Expand Down
136 changes: 136 additions & 0 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
"""Integration tests for the semvergit package."""

import subprocess
import tempfile
from typing import Optional, Tuple


class RunCommandException(Exception):
"""Exception raised when a command fails."""

def __init__(self, message: str) -> None:
"""Initialize the exception."""
super().__init__(message)


def run_command(command: str, cwd: str, validation_string: Optional[str] = None) -> Tuple[str, str]:
"""Run a command in a subprocess and return the output. Raise an exception if the command fails."""
result = subprocess.run(command, capture_output=True, shell=True, text=True, check=False, cwd=cwd)
if result.returncode != 0:
raise RunCommandException(f"Error {result.stderr}, Code: {result.returncode}, Command output: {result.stdout}")
if validation_string:
print(f"[v] {validation_string}")
return (result.stdout, result.stderr)


def add_file_to_repo(filename: str, repodirname: str, content: str) -> None:
"""Add a file to a git repository and commit it."""
with open(repodirname + "/" + filename, "w", encoding="utf-8") as f:
f.write(content)
run_command(f"git add {filename}", repodirname, f"Added {filename} to the index")
run_command(f'git commit -m "Added {filename}"', repodirname, f"Committed {filename}")


def check_git_log(repodirname: str, expected: str) -> None:
"""Check the git log for the last commit."""
result, _ = run_command('git --no-pager log --pretty=format:"%h%d %s [%an]"', repodirname, "Checked the commit log")
print(f"Git Log:\n{result}")
assert expected in result


def update_version(repodirname: str, version_type: str, target_version: str) -> None:
"""Run the semvergit command to update the version."""
result, logs = run_command(f"semvergit -v -t {version_type}", repodirname, "Created a new version")
print(logs, end="")
assert result == target_version


def set_credentials(repodirname: str) -> None:
"""Set the git credentials for the repository."""
run_command("git config user.email 'test@test'", repodirname, "Set user email")
run_command("git config user.name 'Test User'", repodirname, "Set user name")


class TestIntegration:
"""Integration tests for the semvergit package."""

# pylint: disable=attribute-defined-outside-init
def setup_method(self) -> None:
"""Create a git repository and clone it."""
self.tmpdirname = tempfile.mkdtemp()
self.repodirname = self.tmpdirname + "/repo"
run_command(f"mkdir {self.repodirname}", self.tmpdirname, f"Created repo directory: {self.repodirname}")
run_command("git -c init.defaultBranch=master init", self.repodirname, "Initialized git repository")
set_credentials(self.repodirname)
run_command("touch initial.txt", self.repodirname, "Created initial.txt")
run_command("git add .", self.repodirname, "Added initial.txt to the index")
run_command('git commit -m "Initial commit"', self.repodirname, "Committed initial.txt")
check_git_log(self.repodirname, "Initial commit")
self.clonedirname = self.tmpdirname + "/clone"
run_command(
f"git clone {self.repodirname} {self.clonedirname}", self.repodirname, f"Cloned to {self.clonedirname}"
)
set_credentials(self.clonedirname)

def teardown_method(self) -> None:
"""Remove the temporary directory."""
run_command(f"rm -rf {self.tmpdirname}", self.tmpdirname)

def test_integration_patch(self) -> None:
"""Test the integration of the semvergit package with a patch version update."""
add_file_to_repo("test.txt", self.clonedirname, "Hello, World!")
check_git_log(self.clonedirname, "Added test.txt")
update_version(self.clonedirname, "patch", "v0.0.1")
add_file_to_repo("test2.txt", self.clonedirname, "New content")
check_git_log(self.clonedirname, "Added test2.txt")
update_version(self.clonedirname, "patch", "v0.0.2")
check_git_log(self.clonedirname, "v0.0.2")

def test_integration_minor(self) -> None:
"""Test the integration of the semvergit package with a minor version update."""
add_file_to_repo("test.txt", self.clonedirname, "Hello, World!")
check_git_log(self.clonedirname, "Added test.txt")
update_version(self.clonedirname, "minor", "v0.1.0")
add_file_to_repo("test2.txt", self.clonedirname, "New content")
check_git_log(self.clonedirname, "Added test2.txt")
update_version(self.clonedirname, "minor", "v0.2.0")
check_git_log(self.clonedirname, "v0.2.0")

def test_integration_major(self) -> None:
"""Test the integration of the semvergit package with a major version update."""
add_file_to_repo("test.txt", self.clonedirname, "Hello, World!")
check_git_log(self.clonedirname, "Added test.txt")
update_version(self.clonedirname, "major", "v1.0.0")
add_file_to_repo("test2.txt", self.clonedirname, "New content")
check_git_log(self.clonedirname, "Added test2.txt")
update_version(self.clonedirname, "major", "v2.0.0")
check_git_log(self.clonedirname, "v2.0.0")

def test_integration_prerelease(self) -> None:
"""Test the integration of the semvergit package with a prerelease version update."""
add_file_to_repo("test.txt", self.clonedirname, "Hello, World!")
check_git_log(self.clonedirname, "Added test.txt")
update_version(self.clonedirname, "prerelease", "v0.0.1-dev.1")
add_file_to_repo("test2.txt", self.clonedirname, "New content")
check_git_log(self.clonedirname, "Added test2.txt")
update_version(self.clonedirname, "prerelease", "v0.0.1-dev.2")
check_git_log(self.clonedirname, "v0.0.1-dev.2")

def test_integration_stack(self) -> None:
"""Test the integration of the semvergit package with multiple version updates."""
add_file_to_repo("test.txt", self.clonedirname, "Hello, World!")
check_git_log(self.clonedirname, "Added test.txt")
update_version(self.clonedirname, "patch", "v0.0.1")
add_file_to_repo("test2.txt", self.clonedirname, "New content")
check_git_log(self.clonedirname, "Added test2.txt")
update_version(self.clonedirname, "minor", "v0.1.0")
add_file_to_repo("test3.txt", self.clonedirname, "More content")
check_git_log(self.clonedirname, "Added test3.txt")
update_version(self.clonedirname, "major", "v1.0.0")
add_file_to_repo("test4.txt", self.clonedirname, "Even more content")
check_git_log(self.clonedirname, "Added test4.txt")
update_version(self.clonedirname, "minor", "v1.1.0")
add_file_to_repo("test5.txt", self.clonedirname, "Some more content")
check_git_log(self.clonedirname, "Added test5.txt")
update_version(self.clonedirname, "patch", "v1.1.1")
check_git_log(self.clonedirname, "v1.1.1")
Loading