diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml new file mode 100644 index 0000000..5576d51 --- /dev/null +++ b/.github/workflows/test-suite.yml @@ -0,0 +1,104 @@ +name: Test Suite + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + test: + name: Test Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.11', '3.12', '3.13'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest pytest-cov pytest-asyncio pytest-mock + if [ -f pr_review/requirements.txt ]; then pip install -r pr_review/requirements.txt; fi + if [ -f discord_bot/requirements.txt ]; then pip install -r discord_bot/requirements.txt; fi + + - name: Run unit tests + run: | + pytest -m "unit" --cov --cov-report=xml --cov-report=term + continue-on-error: true + + - name: Run integration tests + run: | + pytest -m "integration" --cov --cov-append --cov-report=xml --cov-report=term + continue-on-error: true + + - name: Upload coverage to Codecov + if: matrix.python-version == '3.13' + uses: codecov/codecov-action@v4 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + fail_ci_if_error: false + + - name: Generate coverage report + if: always() + run: | + if [ -f coverage.xml ]; then + echo "Coverage report generated successfully" + pytest --cov --cov-report=term-missing || true + else + echo "No coverage data available" + fi + + lint: + name: Lint and Format Check + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' + + - name: Install linting tools + run: | + python -m pip install --upgrade pip + pip install black flake8 isort mypy bandit + + - name: Check code formatting with Black + run: black --check --line-length=100 . + continue-on-error: true + + - name: Check import sorting with isort + run: isort --check-only --profile black --line-length 100 . + continue-on-error: true + + - name: Lint with flake8 + run: flake8 . --max-line-length=100 --extend-ignore=E203,W503 --count --statistics + continue-on-error: true + + - name: Security check with bandit + run: bandit -r . -f json -o bandit-report.json || true + continue-on-error: true + + - name: Upload bandit report + if: always() + uses: actions/upload-artifact@v4 + with: + name: bandit-security-report + path: bandit-report.json diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..c2a0921 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,60 @@ +[pytest] +# Test discovery patterns +python_files = test_*.py *_test.py +python_classes = Test* +python_functions = test_* + +# Test paths +testpaths = tests pr_review/tests discord_bot/tests + +# Output options +addopts = + -v + --strict-markers + --tb=short + --cov=pr_review + --cov=discord_bot + --cov-report=term-missing + --cov-report=html + --cov-report=xml + --cov-fail-under=60 + --maxfail=5 + --durations=10 + +# Markers for test categorization +markers = + unit: Unit tests + integration: Integration tests + slow: Slow running tests + discord: Discord bot related tests + github: GitHub integration tests + ai: AI/ML related tests + requires_api: Tests requiring external API access + +# Coverage options +[coverage:run] +source = pr_review,discord_bot +omit = + */tests/* + */test_*.py + */__pycache__/* + */venv/* + */env/* + */config/* + */deployment/* + +[coverage:report] +precision = 2 +show_missing = True +skip_covered = False +exclude_lines = + pragma: no cover + def __repr__ + raise AssertionError + raise NotImplementedError + if __name__ == .__main__.: + if TYPE_CHECKING: + @abstractmethod + +[coverage:html] +directory = htmlcov