Add comprehensive test suite with GitHub Actions CI/CD

- Refactor code into testable bot.py module with MastodonRSSBot class
- Create 20+ unit tests covering core functionality and edge cases
- Create 10+ integration tests for RSS parsing and Mastodon posting
- Add GitHub Actions workflow for automated testing
  - Unit tests on Python 3.10, 3.11, 3.12
  - Integration tests with mocked external services
  - Code quality checks (flake8, black, mypy)
  - Docker build validation
- Configure pytest with 80% minimum coverage requirement
- Add test dependencies in requirements-test.txt
- Update .gitignore to exclude test artifacts
- Add comprehensive TESTING.md documentation
- Add test status badge to README
- Maintain full backward compatibility with existing setup
This commit is contained in:
aserper
2025-12-12 23:30:38 -05:00
parent 70a23fdb75
commit c8618ec3b7
11 changed files with 1624 additions and 78 deletions

162
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,162 @@
name: Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
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 -r requirements-test.txt
- name: Run unit tests
run: |
pytest test_bot.py -m "not integration" --cov=bot --cov=main --cov-report=xml --cov-report=term
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-${{ matrix.python-version }}
fail_ci_if_error: false
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
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 -r requirements-test.txt
- name: Run integration tests
run: |
pytest test_integration.py --cov=bot --cov-report=xml --cov-report=term
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: integration
name: codecov-integration-${{ matrix.python-version }}
fail_ci_if_error: false
code-quality:
name: Code Quality
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.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-test.txt
- name: Run flake8
run: |
flake8 bot.py main.py --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 bot.py main.py --count --max-complexity=10 --max-line-length=127 --statistics
- name: Run black check
run: |
black --check bot.py main.py test_bot.py test_integration.py
- name: Run mypy
run: |
mypy bot.py main.py --ignore-missing-imports
continue-on-error: true
docker-build-test:
name: Docker Build Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: masto-rss:test
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test Docker image structure
run: |
docker run --rm masto-rss:test python --version
docker run --rm masto-rss:test pip list | grep feedparser
docker run --rm masto-rss:test pip list | grep Mastodon
all-tests-pass:
name: All Tests Passed
needs: [unit-tests, integration-tests, code-quality, docker-build-test]
runs-on: ubuntu-latest
if: always()
steps:
- name: Check test results
run: |
if [ "${{ needs.unit-tests.result }}" != "success" ]; then
echo "Unit tests failed"
exit 1
fi
if [ "${{ needs.integration-tests.result }}" != "success" ]; then
echo "Integration tests failed"
exit 1
fi
if [ "${{ needs.code-quality.result }}" != "success" ]; then
echo "Code quality checks failed"
exit 1
fi
if [ "${{ needs.docker-build-test.result }}" != "success" ]; then
echo "Docker build test failed"
exit 1
fi
echo "All tests passed successfully!"