This directory contains GitHub Actions workflows for automated testing and code quality checks.
Triggers:
- Push to
main,master, ordevelopbranches - Pull requests to
main,master, ordevelopbranches - Manual workflow dispatch
Features:
- ✅ Multi-OS testing: Ubuntu, Windows, macOS
- ✅ Multi-Python version: 3.9, 3.10, 3.11, 3.12
- ✅ Test execution: Runs all pytest tests with verbose output
- ✅ Coverage reporting: Generates coverage reports and uploads to Codecov
- ✅ Code linting: Checks code quality with flake8, black, and isort
Matrix Strategy:
- Tests run on 3 operating systems × 4 Python versions = 12 test jobs
- Continues even if one job fails (
fail-fast: false)
Linting Checks:
- black: Code formatting
- isort: Import sorting
- flake8: Code style and syntax errors
Triggers:
- Push to
mainormasterbranches - Pull requests to
mainormasterbranches
Features:
- ✅ Single environment: Ubuntu with Python 3.11
- ✅ Fast execution: Quick feedback for basic testing
- ✅ Coverage report: Generates HTML coverage report
- ✅ Artifact upload: Coverage report available for download
Use case: Lightweight testing for quick validation
Add these badges to your README.md to show workflow status:
[](https://codecov.io/gh/YOUR_USERNAME/two_particles_MD)GitHub Actions are automatically enabled for public repositories. For private repositories:
- Go to repository Settings → Actions → General
- Enable "Allow all actions and reusable workflows"
For coverage reporting with tests.yml:
- Sign up at codecov.io with your GitHub account
- Add your repository to Codecov
- Get your Codecov token
- Add it as a repository secret:
- Go to Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
CODECOV_TOKEN - Value: Your Codecov token
Edit the workflow files to match your needs:
Change trigger branches:
on:
push:
branches: [ main, develop, feature/* ] # Add your branchesChange Python versions:
matrix:
python-version: ['3.9', '3.10', '3.11'] # Remove or add versionsChange operating systems:
matrix:
os: [ubuntu-latest, windows-latest] # Remove macOS if not needed- Go to the Actions tab in your repository
- Click on a workflow run to see details
- Click on individual jobs to see logs
- Download artifacts (coverage reports) from the workflow summary
Run the same commands that GitHub Actions uses:
# Install dependencies
pip install -r requirements.txt
# Run tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=src --cov-report=term --cov-report=html- Check for path separator issues (
/vs\) - Use
os.path.join()for cross-platform paths - Check line ending differences (CRLF vs LF)
- Check for version-specific syntax or features
- Review deprecation warnings
- Update dependencies in
requirements.txt
# Fix formatting with black
black src/ tests/
# Fix import sorting with isort
isort src/ tests/
# Check flake8 issues
flake8 src/ tests/ --max-line-length=100- Keep workflows fast: Use caching for dependencies
- Test on multiple platforms: Catch platform-specific bugs early
- Use matrix strategy: Test multiple Python versions efficiently
- Monitor coverage: Aim for >80% code coverage
- Fix linting issues: Maintain consistent code style
- Review failed runs: Don't ignore CI failures
.github/
└── workflows/
├── README.md # This file
├── tests.yml # Comprehensive test suite
└── tests-simple.yml # Simple test suite
When you push code, GitHub Actions will:
- ✅ Checkout your code
- ✅ Set up Python environment
- ✅ Install dependencies from
requirements.txt - ✅ Run all tests with pytest
- ✅ Generate coverage report
- ✅ Upload coverage to Codecov (if configured)
- ✅ Run linting checks (tests.yml only)
- ✅ Report results with ✅ or ❌
You'll receive email notifications for failed runs (configurable in GitHub settings).
This section documents CI test failures encountered and their solutions for future reference.
Date: 2024-11-27
Affected Tests:
test_run_button_clicktest_simulation_produces_resultstest_session_state_stores_simulation
Error:
RuntimeError: AppTest script run timed out after 3(s)
Root Cause:
The Streamlit AppTest framework has a default 3-second timeout. Running MD simulations with 100 steps exceeded this timeout in CI environments.
Solution:
Modified tests/test_streamlit_app.py:
- Reduced simulation steps from 100 to 10
- Increased timeout to 10 seconds
# Before
at.number_input[5].set_value(100).run()
at.button[0].click().run()
# After
at.number_input[5].set_value(10).run() # Minimal steps for fast test
at.button[0].click().run(timeout=10) # Increased timeoutCommit: 94a1e59
Date: 2024-11-27
Platform: macOS runners
Error:
Abort trap: 6
Root Cause:
Matplotlib attempted to use an interactive backend (e.g., TkAgg, Qt5Agg) in a headless CI environment without a display server, causing a segmentation fault.
Solution:
Added MPLBACKEND=Agg environment variable to force matplotlib to use the non-interactive Agg backend.
Modified .github/workflows/tests.yml:
- name: Run tests with pytest
env:
MPLBACKEND: Agg # Force non-interactive backend
run: |
pytest tests/ -v --tb=short
- name: Run tests with coverage
env:
MPLBACKEND: Agg # Force non-interactive backend
run: |
pytest tests/ --cov=src --cov-report=xml --cov-report=termCommit: bf367c7
Date: 2024-11-27
Platform: Windows runners
Error:
Windows fatal exception: code 0x80000003
Stack Trace:
Crash occurred during pytest teardown phase after test_simulation_produces_results, indicating improper cleanup of matplotlib figures.
Root Cause:
Matplotlib figures were not being properly closed after tests, causing memory/resource issues during teardown on Windows.
Solution:
Modified tests/test_streamlit_app.py:
- Set Agg backend at module level (before any matplotlib imports):
import matplotlib
matplotlib.use('Agg') # Use non-interactive backend for CI
import matplotlib.pyplot as plt- Added pytest fixture for automatic cleanup:
@pytest.fixture(autouse=True)
def cleanup_matplotlib():
"""Ensure all matplotlib figures are closed after each test."""
yield
plt.close('all')Why Both Changes?
matplotlib.use('Agg'): Prevents interactive backend issuesplt.close('all'): Ensures proper cleanup even if tests create figures
Commit: e99c813
| Issue | Platform | Solution | Files Modified |
|---|---|---|---|
| Test Timeout | Linux | Reduce steps, increase timeout | tests/test_streamlit_app.py |
| Abort Trap | macOS | Set MPLBACKEND=Agg env var |
.github/workflows/tests.yml |
| Fatal Exception | Windows | Agg backend + cleanup fixture | tests/test_streamlit_app.py |
- Always use non-interactive backends in CI: Set
MPLBACKEND=Aggormatplotlib.use('Agg') - Clean up resources: Use pytest fixtures with
autouse=Truefor automatic cleanup - Adjust timeouts for CI: CI environments are slower than local machines
- Test locally on multiple platforms: Use VMs or containers to catch platform-specific issues
- Keep test data minimal: Use the smallest dataset that validates functionality
For any project using matplotlib in CI, add these safeguards:
In workflow file:
env:
MPLBACKEND: AggIn test file:
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
@pytest.fixture(autouse=True)
def cleanup_matplotlib():
yield
plt.close('all')Problem: remote rejected error when pushing workflows
Solution: Use SSH instead of HTTPS for authentication
# Check current remote URL
git remote -v
# If using HTTPS (https://github.com/...)
origin https://github.com/username/repo.git (fetch)
origin https://github.com/username/repo.git (push)
# Switch to SSH (git@github.com:...)
git remote set-url origin git@github.com:username/repo.git
# Verify the change
git remote -v
origin git@github.com:username/repo.git (fetch)
origin git@github.com:username/repo.git (push)
# Now push works without OAuth scope issues
git push origin mainWhy? GitHub requires the workflow scope for OAuth tokens when modifying files in .github/workflows/. SSH authentication bypasses this requirement.
If you're on Windows, here's how to switch between different shells:
# Launch Git Bash
"C:\Program Files\Git\bin\bash.exe"
# Or just click Git Bash icon in Start menupowershellcmdcmdpowershellGit Bash (MINGW64):
user@COMPUTER MINGW64 /d/project/repo (main)
$PowerShell:
PS D:\project\repo>CMD:
D:\project\repo>- Check that workflow file is in
.github/workflows/ - Verify YAML syntax (use a YAML validator)
- Ensure you pushed to the correct branch
- Check repository settings → Actions → Allow all actions
- Check Python version differences
- Verify all dependencies in
requirements.txt - Check for OS-specific issues (paths, line endings)
- Review workflow logs for detailed error messages
- Wait a few minutes for cache to clear
- Hard refresh browser (Ctrl+F5)
- Verify badge URL matches your username/repo
- Check that workflow has run at least once
- GitHub Actions Documentation
- pytest Documentation
- Codecov Documentation
- GitHub Actions Marketplace
- Git SSH Setup Guide
Last Updated: 2024-11-27