Skip to content

Fix linting

Fix linting #13

name: Comprehensive Testing Suite
on:
push:
branches: [ main, develop, v0.2.0 ]
pull_request:
branches: [ main, develop ]
schedule:
# Run nightly benchmarks at 2 AM UTC
- cron: '0 2 * * *'
env:
PYTHONUNBUFFERED: 1
PYTEST_ADDOPTS: --color=yes
jobs:
# Fast smoke tests for quick feedback
smoke-tests:
name: Smoke Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Validate installation
run: |
python -c "import preprimer; print(f'PrePrimer version: {preprimer.__version__ if hasattr(preprimer, \"__version__\") else \"development\"}')"
python -c "from preprimer.parsers.varvamp_parser import VarVAMPParser; print('VarVAMP parser imported successfully')"
- name: Run core tests (fast subset)
run: |
python -m pytest tests/test_core_interfaces.py tests/test_core_config.py -v --tb=short
# Comprehensive test suite
comprehensive-tests:
name: Full Test Suite (${{ matrix.os }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
needs: smoke-tests
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.11", "3.12", "3.13"]
# No additional includes needed - all versions covered in matrix
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run comprehensive test suite
run: |
python -m pytest tests/ \
--cov=preprimer \
--cov-report=xml \
--cov-report=term-missing \
--cov-report=html \
--tb=short \
-x
- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
- name: Upload coverage artifacts
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
uses: actions/upload-artifact@v4
with:
name: coverage-reports
path: |
coverage.xml
htmlcov/
retention-days: 7
# Property-based testing
property-testing:
name: Property-Based Testing
runs-on: ubuntu-latest
needs: smoke-tests
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run property-based tests
run: |
python -m pytest tests/test_property_based.py -v \
--hypothesis-max-examples=1000 \
--hypothesis-show-statistics \
--tb=short
- name: Upload Hypothesis database
if: always()
uses: actions/upload-artifact@v4
with:
name: hypothesis-database
path: .hypothesis/
retention-days: 7
# Security testing
security-testing:
name: Security Testing
runs-on: ubuntu-latest
needs: smoke-tests
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install bandit safety
- name: Run security validation tests
run: |
python -m pytest tests/test_security.py -v --tb=short
- name: Run bandit security linter
run: |
bandit -r preprimer/ -f json -o bandit-report.json || true
bandit -r preprimer/ -f txt
- name: Check dependencies for known vulnerabilities
run: |
safety check --json --output safety-report.json || true
safety check
- name: Upload security reports
if: always()
uses: actions/upload-artifact@v4
with:
name: security-reports
path: |
bandit-report.json
safety-report.json
retention-days: 30
# Performance benchmarking
performance-benchmarks:
name: Performance Benchmarks
runs-on: ubuntu-latest
needs: smoke-tests
if: github.event_name == 'schedule' || contains(github.event.head_commit.message, '[benchmark]')
steps:
- uses: actions/checkout@v4
with:
# Fetch history for performance comparison
fetch-depth: 0
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run performance benchmarks
run: |
python -m pytest tests/test_benchmarks.py -v \
--benchmark-only \
--benchmark-json=benchmark-results.json \
--benchmark-save=benchmark-$(date +%Y%m%d-%H%M%S) \
--benchmark-sort=mean
- name: Upload benchmark results
uses: actions/upload-artifact@v4
with:
name: benchmark-results
path: |
benchmark-results.json
.benchmarks/
retention-days: 30
- name: Comment PR with benchmark results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
try {
const results = JSON.parse(fs.readFileSync('benchmark-results.json', 'utf8'));
const benchmarks = results.benchmarks;
let comment = '## 🚀 Performance Benchmark Results\n\n';
comment += '| Benchmark | Mean Time | Operations/sec |\n';
comment += '|-----------|-----------|---------------|\n';
benchmarks.slice(0, 10).forEach(bench => {
const name = bench.name.replace('test_', '').replace('_benchmark', '');
const mean = bench.stats.mean;
const ops = (1 / mean).toExponential(2);
comment += `| ${name} | ${mean.toFixed(6)}s | ${ops} |\n`;
});
comment += `\n**Total benchmarks:** ${benchmarks.length}`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
} catch (error) {
console.log('Could not parse benchmark results:', error.message);
}
# Integration testing
integration-testing:
name: Integration Testing
runs-on: ${{ matrix.os }}
needs: comprehensive-tests
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run integration tests
run: |
python -m pytest tests/test_integration.py -v --tb=short
- name: Test CLI functionality
run: |
# Test CLI installation and basic functionality
python -c "import preprimer; print('✅ PrePrimer module imported successfully')"
# Test with small dataset
python -m pytest tests/test_data/datasets/small/ -k "not test_" --collect-only || true
echo "✅ Test data structure validation passed"
# Mutation testing (weekly)
mutation-testing:
name: Mutation Testing
runs-on: ubuntu-latest
needs: comprehensive-tests
if: github.event_name == 'schedule' || contains(github.event.head_commit.message, '[mutation]')
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run mutation testing
run: |
# Run on core modules only to manage time
python scripts/run_mutation_tests.py --paths preprimer/core/ preprimer/parsers/varvamp_parser.py
- name: Upload mutation test results
if: always()
uses: actions/upload-artifact@v4
with:
name: mutation-test-results
path: mutation_results/
retention-days: 30
# Code quality and linting
code-quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install pre-commit
- name: Run code formatting check
run: |
black --check --diff preprimer/ tests/ examples/ scripts/
- name: Run import sorting check
run: |
isort --check-only --diff preprimer/ tests/ examples/ scripts/
- name: Run linting
run: |
flake8 preprimer/ tests/ examples/ scripts/ --max-line-length=88 --extend-ignore=E203,W503
- name: Run type checking
run: |
mypy preprimer/ --ignore-missing-imports --no-strict-optional
- name: Run pre-commit hooks
run: |
pre-commit run --all-files || true
# Deployment readiness check
deployment-check:
name: Deployment Readiness
runs-on: ubuntu-latest
needs: [comprehensive-tests, security-testing, code-quality]
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/v0.2.0'
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'
cache-dependency-path: 'pyproject.toml'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install build twine
- name: Build package
run: |
python -m build
- name: Check package
run: |
python -m twine check dist/*
- name: Test package installation
run: |
pip install dist/*.whl
python -c "import preprimer; print('✅ Package installation successful')"
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: package-build
path: dist/
retention-days: 7
# Summary report
test-summary:
name: Test Summary
runs-on: ubuntu-latest
needs: [comprehensive-tests, property-testing, security-testing, integration-testing, code-quality]
if: always()
steps:
- name: Check test results
run: |
echo "## 📊 Test Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Comprehensive Tests**: ${{ needs.comprehensive-tests.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Property-Based Testing**: ${{ needs.property-testing.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Security Testing**: ${{ needs.security-testing.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Integration Testing**: ${{ needs.integration-testing.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Code Quality**: ${{ needs.code-quality.result }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Overall Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY