Skip to content

Improve testing

Improve testing #1

Workflow file for this run

name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt', '**/setup.py') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install system dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y build-essential
- name: Install system dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install --quiet gcc || true
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -e .
pip install pytest pytest-cov coverage flake8 ruff
- name: Install optional bioinformatics dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
# Try to install optional dependencies, but don't fail if unavailable
pip install pybedtools || echo "pybedtools unavailable, continuing..."
# Note: ViennaRNA and pblat are complex to install in CI, tests handle graceful degradation
- name: Install optional bioinformatics dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
# Try to install optional dependencies, but don't fail if unavailable
pip install pybedtools || echo "pybedtools unavailable, continuing..."
- name: Lint with ruff
run: |
# Stop the build if there are Python syntax errors or undefined names
ruff check baitUtils/ --select=E9,F63,F7,F82 --show-source --statistics
# Exit-zero treats all errors as warnings
ruff check baitUtils/ --exit-zero --statistics
- name: Lint with flake8
run: |
# Stop the build if there are Python syntax errors or undefined names
flake8 baitUtils/ --count --select=E9,F63,F7,F82 --show-source --statistics
# Exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 baitUtils/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test import functionality
run: |
python -c "import baitUtils; print('✓ Main package imports successfully')"
python -c "from baitUtils.sequence_analysis import SequenceAnalyzer; print('✓ Core modules import successfully')"
python -c "from baitUtils.sequence_statistics import SequenceStatsCalculator; print('✓ Statistics modules import successfully')"
python -c "from baitUtils.plotting_utils import StatisticalPlotter; print('✓ Plotting modules import successfully')"
- name: Test CLI help commands
run: |
python -m baitUtils --help
python -m baitUtils stats --help
python -m baitUtils plot --help
python -m baitUtils map --help
python -m baitUtils check --help
python -m baitUtils fill --help
python -m baitUtils evaluate --help
python -m baitUtils compare --help
- name: Run unit tests with pytest
run: |
pytest tests/ -v --tb=short --strict-warnings
- name: Run unit tests with unittest (fallback)
if: failure()
run: |
python -m unittest discover tests/ -v
- name: Test with coverage
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
run: |
coverage run -m pytest tests/
coverage report -m
coverage xml
- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
integration-test:
runs-on: ubuntu-latest
needs: test
if: success()
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Create test data
run: |
mkdir -p test_data
cat > test_data/test_sequences.fasta << 'EOF'
>seq1
ATGCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCG
>seq2
GCTATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGAT
>seq3
CGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATC
EOF
- name: Test stats command
run: |
python -m baitUtils stats -i test_data/test_sequences.fasta -o test_output/
ls -la test_output/
test -f test_output/sequence_statistics.tsv
- name: Test plot command (basic)
run: |
python -m baitUtils plot -i test_output/sequence_statistics.tsv -o test_plots/
ls -la test_plots/
- name: Clean up test data
run: |
rm -rf test_data/ test_output/ test_plots/
security-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install security tools
run: |
python -m pip install --upgrade pip
pip install safety bandit
- name: Run safety check
run: |
pip freeze | safety check --stdin || echo "Safety check completed with warnings"
- name: Run bandit security lint
run: |
bandit -r baitUtils/ -f json -o bandit-report.json || echo "Bandit completed with findings"
bandit -r baitUtils/ || echo "Bandit security check completed"
documentation-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Check README exists
run: |
test -f README.md
echo "✓ README.md exists"
- name: Check CLAUDE.md is up to date
run: |
test -f CLAUDE.md
echo "✓ CLAUDE.md exists"
- name: Check CONTRIBUTING.md exists
run: |
test -f CONTRIBUTING.md
echo "✓ CONTRIBUTING.md exists"
- name: Validate package structure
run: |
python -c "
import os
required_files = [
'baitUtils/__init__.py',
'baitUtils/__main__.py',
'baitUtils/_version.py',
'setup.py',
'requirements.txt'
]
for f in required_files:
assert os.path.exists(f), f'Missing required file: {f}'
print('✓ All required package files exist')
"
- name: Check version consistency
run: |
python -c "
import sys
sys.path.insert(0, '.')
from baitUtils._version import __version__
print(f'Package version: {__version__}')
assert __version__.strip(), 'Version string is empty'
print('✓ Version is properly defined')
"