Skip to content
Closed
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
14 changes: 14 additions & 0 deletions .github/linters/.ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Ruff configuration for test fixtures
# This configuration relaxes rules for test fixtures which are
# often using non-standard import orders and mock functionality

extend = "../../pyproject.toml"

[lint]
ignore = [
"E402", # Module level import not at top of file (common in test fixtures)
"F401", # Unused import (needed for test fixtures)
"F811", # Redefinition of unused name (common in test fixtures)
"F821", # Undefined name (often happens with dynamically created objects)
"F841", # Local variable assigned but never used (common in test fixtures)
]
8 changes: 8 additions & 0 deletions .github/workflows/pr-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ jobs:
- name: Run unit tests
run: uv run pytest -m unit -v

- name: Install sbctl
run: |
curl -L -o sbctl.tar.gz "https://github.com/replicatedhq/sbctl/releases/latest/download/sbctl_linux_amd64.tar.gz"
tar xzf sbctl.tar.gz
chmod +x sbctl
sudo mv sbctl /usr/local/bin/
sbctl --version || echo "sbctl installed but version command not available"

- name: Run integration tests
run: uv run pytest -m integration -v

Expand Down
9 changes: 9 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ timeout = 30
[tool.ruff]
line-length = 100
target-version = "py313"
exclude = [
".git",
".github",
"__pycache__",
"build",
"dist",
"*.yml",
"*.yaml",
]

[tool.black]
line-length = 100
Expand Down
2 changes: 1 addition & 1 deletion src/mcp_server_troubleshoot/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def handle_signal(signum: int, frame: Any) -> None:
import shutil

shutil.rmtree(bundle_path)
logger.info(f"Successfully removed bundle directory")
logger.info("Successfully removed bundle directory")
except Exception as e:
logger.error(f"Error removing bundle directory: {e}")
except Exception as e:
Expand Down
5 changes: 5 additions & 0 deletions tests/.ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ruff configuration for tests directory
# This applies more relaxed rules for test files which often use
# non-standard import orders, mocks, and test fixtures

extend = "../.github/linters/.ruff.toml"
24 changes: 12 additions & 12 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ def is_docker_available():
"""Check if Podman is available on the system."""
try:
result = subprocess.run(
["podman", "--version"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
["podman", "--version"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
timeout=5,
check=False
check=False,
)
return result.returncode == 0
except (subprocess.SubprocessError, FileNotFoundError, subprocess.TimeoutExpired):
Expand Down Expand Up @@ -164,7 +164,7 @@ def build_container_image(project_root, use_mock_sbctl=False):
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
timeout=30,
check=False
check=False,
)

# For test mode with mock sbctl, we need to modify the Containerfile
Expand Down Expand Up @@ -222,7 +222,7 @@ def build_container_image(project_root, use_mock_sbctl=False):
stderr=subprocess.PIPE,
text=True,
timeout=300,
check=True
check=True,
)

# Clean up the temporary Containerfile
Expand All @@ -237,7 +237,7 @@ def build_container_image(project_root, use_mock_sbctl=False):
stderr=subprocess.PIPE,
text=True,
timeout=300,
check=True
check=True,
)

return True, result
Expand Down Expand Up @@ -275,15 +275,15 @@ def docker_image(request):
["podman", "image", "exists", "mcp-server-troubleshoot:latest"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False
check=False,
)

# Image exists already, just use it
if image_check.returncode == 0:
print("\nUsing existing Podman image for tests...")
yield "mcp-server-troubleshoot:latest"
return

# Determine if we should use mock sbctl based on markers
use_mock_sbctl = request.node.get_closest_marker("mock_sbctl") is not None

Expand Down Expand Up @@ -316,7 +316,7 @@ def docker_image(request):
stderr=subprocess.PIPE,
text=True,
timeout=10,
check=False
check=False,
)
containers = containers_result.stdout.strip().split("\n") if containers_result.stdout else []

Expand All @@ -328,7 +328,7 @@ def docker_image(request):
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
timeout=10,
check=False
check=False,
)
except Exception:
pass
Expand Down
26 changes: 13 additions & 13 deletions tests/e2e/test_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,12 @@ def test_mcp_protocol(container_setup, docker_image):
["podman", "rm", "-f", container_id],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False
check=False,
)

# Start the container using run instead of Popen
print(f"Starting test container: {container_id}")

# Use detached mode to run in background
container_start = subprocess.run(
[
Expand All @@ -190,14 +190,14 @@ def test_mcp_protocol(container_setup, docker_image):
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=False
check=False,
)

# Print full container start output for debugging
print(f"Container start stdout: {container_start.stdout}")
print(f"Container start stderr: {container_start.stderr}")
print(f"Container start return code: {container_start.returncode}")

if container_start.returncode != 0:
print(f"Failed to start container: {container_start.stderr}")
pytest.fail(f"Failed to start container: {container_start.stderr}")
Expand All @@ -213,21 +213,21 @@ def test_mcp_protocol(container_setup, docker_image):
stderr=subprocess.PIPE,
text=True,
)

print(f"Container status: {ps_check.stdout}")

# Also get logs in case it failed to start properly
logs_check = subprocess.run(
["podman", "logs", container_id],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=False
check=False,
)

print(f"Container logs stdout: {logs_check.stdout}")
print(f"Container logs stderr: {logs_check.stderr}")

# Check specifically for this container
running_check = subprocess.run(
["podman", "ps", "-q", "-f", f"name={container_id}"],
Expand Down Expand Up @@ -303,7 +303,7 @@ def timeout_handler():
finally:
# Clean up the container
print(f"Cleaning up container: {container_id}")

# Stop and remove the container with a more robust cleanup procedure
try:
# First try a normal removal
Expand All @@ -312,7 +312,7 @@ def timeout_handler():
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False,
timeout=10
timeout=10,
)
except subprocess.TimeoutExpired:
# If that times out, try to kill it first
Expand All @@ -322,7 +322,7 @@ def timeout_handler():
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False,
timeout=5
timeout=5,
)
# Then try removal again
subprocess.run(
Expand Down
4 changes: 3 additions & 1 deletion tests/e2e/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ def test_podman_build():

# Build the image with progress output
print("\nBuilding Podman image...")
output = run_command(f"podman build --progress=plain -t {test_tag} -f Containerfile .", cwd=str(project_dir))
output = run_command(
f"podman build --progress=plain -t {test_tag} -f Containerfile .", cwd=str(project_dir)
)
print(f"\nBuild output:\n{output}\n")

# Check if the image exists
Expand Down
4 changes: 3 additions & 1 deletion tests/e2e/test_podman.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ def test_podman_build():

# Build the image with progress output
print("\nBuilding Podman image...")
output = run_command(f"podman build --progress=plain -t {test_tag} -f Containerfile .", cwd=str(project_dir))
output = run_command(
f"podman build --progress=plain -t {test_tag} -f Containerfile .", cwd=str(project_dir)
)
print(f"\nBuild output:\n{output}\n")

# Check if the image exists
Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/.ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ruff configuration for test fixtures
# Fixtures have special requirements and often use non-standard
# import orders and unconventional patterns for mocking

extend = "../.ruff.toml"
2 changes: 1 addition & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
from unittest.mock import AsyncMock, Mock, patch

# Import TestAssertions class and fixture from unit tests
from tests.unit.conftest import TestAssertions, test_assertions
from tests.unit.conftest import TestAssertions, test_assertions
1 change: 0 additions & 1 deletion tests/integration/test_integration.py

This file was deleted.

13 changes: 13 additions & 0 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""
Integration tests for the complete MCP server integration.

This file provides tests for the complete MCP server integration,
including the FastMCP protocol implementation.
"""

import pytest

# Mark all tests in this file as integration tests
pytestmark = pytest.mark.integration

# Future integration tests will be added here as they are developed
2 changes: 1 addition & 1 deletion tests/integration/test_real_bundle.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Tests for real support bundle integration.

These tests verify the behavior of the MCP server components
These tests verify the behavior of the MCP server components
with actual support bundles, focusing on user-visible behavior
rather than implementation details.
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_stdio_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
async def test_stdio_lifecycle_docstring():
"""
This test exists to document why the stdio lifecycle tests were removed.

The stdio lifecycle functionality is now properly tested in the e2e container
tests which provide a more appropriate environment.
"""
# This is a documentation test only - it doesn't actually test functionality
# It exists to preserve the test file for documentation purposes and to show
# in test collection that the stdio lifecycle tests were intentionally removed
assert True, "This test exists only for documentation purposes"
assert True, "This test exists only for documentation purposes"
Loading
Loading