deb-bootc-image-builder/test/test_flake8.py

367 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Test flake8 compliance for deb-bootc-image-builder.
This module tests code style compliance using flake8,
including:
- PEP 8 compliance
- Code style validation
- Debian-specific style standards
"""
import pytest
import os
import tempfile
import shutil
import subprocess
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TestFlake8Compliance:
"""Test cases for flake8 compliance."""
def test_flake8_installation(self, work_dir):
"""Test that flake8 is available."""
try:
result = subprocess.run(
["flake8", "--version"],
capture_output=True,
text=True,
timeout=10
)
assert result.returncode == 0, "flake8 is not properly installed"
logger.info("flake8 is available")
except FileNotFoundError:
pytest.skip("flake8 not installed")
def test_flake8_basic_usage(self, work_dir):
"""Test basic flake8 functionality."""
# Create a simple test file
test_file = os.path.join(work_dir, "test_flake8.py")
with open(test_file, 'w') as f:
f.write('''#!/usr/bin/env python3
"""
Test file for flake8 validation.
"""
def test_function():
"""Test function for flake8."""
return "test"
if __name__ == "__main__":
print(test_function())
''')
# Run flake8 on the test file
try:
result = subprocess.run(
["flake8", test_file],
capture_output=True,
text=True,
timeout=30
)
# flake8 should run without errors
assert result.returncode == 0, f"flake8 found issues: {result.stdout}"
logger.info("flake8 basic functionality test passed")
except subprocess.TimeoutExpired:
pytest.fail("flake8 test timed out")
except Exception as e:
pytest.fail(f"flake8 test failed: {e}")
def test_pep8_compliance(self, work_dir):
"""Test PEP 8 compliance."""
# Create a test file with various PEP 8 issues
test_file = os.path.join(work_dir, "pep8_test.py")
with open(test_file, 'w') as f:
f.write('''#!/usr/bin/env python3
"""
Test file for PEP 8 compliance.
"""
import os
import sys
# This line is too long and should trigger E501
very_long_line_that_exceeds_the_maximum_line_length_and_should_trigger_a_flake8_error = "test"
def test_function_with_bad_spacing( x,y ):
"""Function with bad spacing."""
if x==y:
return True
else:
return False
class BadClass:
def __init__(self):
pass
def method_with_bad_indentation(self):
return "bad indentation"
# Missing blank line at end of file
''')
# Run flake8 and check for expected errors
try:
result = subprocess.run(
["flake8", test_file],
capture_output=True,
text=True,
timeout=30
)
# Should find PEP 8 violations
assert result.returncode != 0, "flake8 should find PEP 8 violations"
output = result.stdout + result.stderr
# Check for specific error codes
expected_errors = ["E501", "E201", "E202", "E225", "E111", "W292"]
found_errors = []
for error_code in expected_errors:
if error_code in output:
found_errors.append(error_code)
assert len(found_errors) > 0, f"No expected PEP 8 errors found. Output: {output}"
logger.info(f"Found PEP 8 violations: {found_errors}")
except subprocess.TimeoutExpired:
pytest.fail("flake8 PEP 8 test timed out")
except Exception as e:
pytest.fail(f"flake8 PEP 8 test failed: {e}")
def test_debian_specific_style_standards(self, work_dir):
"""Test Debian-specific style standards."""
# Create a test file following Debian style standards
test_file = os.path.join(work_dir, "debian_style_test.py")
with open(test_file, 'w') as f:
f.write('''#!/usr/bin/env python3
"""
Debian-specific test file for flake8 validation.
"""
import os
import subprocess
import logging
from typing import Dict, List, Any, Optional
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class DebianBootcBuilder:
"""Debian bootc image builder class."""
def __init__(self, work_dir: str):
"""Initialize the builder."""
self.work_dir = work_dir
self.packages: List[str] = []
self.release = "trixie"
self.arch = "amd64"
def add_package(self, package: str) -> None:
"""Add a package to the installation list."""
if package not in self.packages:
self.packages.append(package)
logger.info(f"Added package: {package}")
def set_release(self, release: str) -> None:
"""Set the Debian release."""
valid_releases = ["trixie", "bookworm", "bullseye"]
if release in valid_releases:
self.release = release
logger.info(f"Set release to: {release}")
else:
raise ValueError(f"Invalid release: {release}")
def build_image(self) -> Dict[str, Any]:
"""Build the Debian image."""
logger.info("Starting Debian image build")
# Validate configuration
if not self.packages:
raise ValueError("No packages specified")
# Build process would go here
result = {
"status": "success",
"packages": self.packages,
"release": self.release,
"arch": self.arch
}
logger.info("Debian image build completed")
return result
def main() -> None:
"""Main function."""
builder = DebianBootcBuilder("/tmp/test")
builder.add_package("linux-image-amd64")
builder.add_package("systemd")
builder.set_release("trixie")
try:
result = builder.build_image()
print(f"Build result: {result}")
except Exception as e:
logger.error(f"Build failed: {e}")
if __name__ == "__main__":
main()
''')
# Run flake8 on the Debian style file
try:
result = subprocess.run(
["flake8", test_file],
capture_output=True,
text=True,
timeout=30
)
# Should pass flake8 validation
assert result.returncode == 0, f"flake8 found issues in Debian style file: {result.stdout}"
logger.info("Debian-specific style standards test passed")
except subprocess.TimeoutExpired:
pytest.fail("flake8 Debian style test timed out")
except Exception as e:
pytest.fail(f"flake8 Debian style test failed: {e}")
def test_flake8_configuration(self, work_dir):
"""Test flake8 configuration and custom rules."""
# Create a flake8 configuration file
setup_cfg = os.path.join(work_dir, "setup.cfg")
with open(setup_cfg, 'w') as f:
f.write('''[flake8]
# Maximum line length
max-line-length = 120
# Ignore specific error codes
ignore = E203, W503
# Exclude directories
exclude = .git,__pycache__,.venv
# Maximum complexity
max-complexity = 10
''')
# Create a test file that would normally trigger ignored errors
test_file = os.path.join(work_dir, "config_test.py")
with open(test_file, 'w') as f:
f.write('''#!/usr/bin/env python3
"""
Test file for flake8 configuration.
"""
def test_function():
"""Test function for flake8 config."""
# This line is long but should be allowed by config
very_long_line_that_exceeds_normal_pep8_but_is_allowed_by_our_config = "test"
return very_long_line_that_exceeds_normal_pep8_but_is_allowed_by_our_config
if __name__ == "__main__":
print(test_function())
''')
# Run flake8 with custom configuration
try:
result = subprocess.run(
["flake8", "--config", setup_cfg, test_file],
capture_output=True,
text=True,
timeout=30
)
# Should pass with custom configuration
assert result.returncode == 0, f"flake8 with custom config failed: {result.stdout}"
logger.info("flake8 configuration test passed")
except subprocess.TimeoutExpired:
pytest.fail("flake8 configuration test timed out")
except Exception as e:
pytest.fail(f"flake8 configuration test failed: {e}")
def test_flake8_error_codes(self, work_dir):
"""Test specific flake8 error codes."""
# Create a test file with specific error types
test_file = os.path.join(work_dir, "error_codes_test.py")
with open(test_file, 'w') as f:
f.write('''#!/usr/bin/env python3
"""
Test file for specific flake8 error codes.
"""
# E501: Line too long
very_long_line_that_exceeds_the_maximum_line_length_and_should_trigger_a_flake8_error = "test"
# E201: Whitespace after '('
def function_with_bad_spacing( x ):
return x
# E202: Whitespace before ')'
def another_bad_function( y ):
return y
# E225: Missing whitespace around operator
x=1
y=2
z=x+y
# E111: Bad indentation
def bad_indentation():
return "bad"
# W292: No newline at end of file
result = "no newline"
''')
# Run flake8 and check for specific error codes
try:
result = subprocess.run(
["flake8", test_file],
capture_output=True,
text=True,
timeout=30
)
# Should find errors
assert result.returncode != 0, "flake8 should find style errors"
output = result.stdout + result.stderr
# Check for specific error codes
expected_errors = ["E501", "E201", "E202", "E225", "E111", "W292"]
found_errors = []
for error_code in expected_errors:
if error_code in output:
found_errors.append(error_code)
# Should find at least some of the expected errors
assert len(found_errors) >= 3, f"Expected more error codes. Found: {found_errors}"
logger.info(f"Found flake8 error codes: {found_errors}")
except subprocess.TimeoutExpired:
pytest.fail("flake8 error codes test timed out")
except Exception as e:
pytest.fail(f"flake8 error codes test failed: {e}")
if __name__ == "__main__":
pytest.main([__file__])