agentsclimarketplace

Bio applied testing cicd

Skill Pavel-Kravchenko/Bioinformatics/Skills/bio-applied-testing-cicd

208 bioinformatics skills for Claude Code — NGS, single-cell, metagenomics, structural biology, algorithms, AI for science

Install
npx -y skills add Pavel-Kravchenko/Bioinformatics --skill bio-applied-testing-cicd

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Write pytest tests/fixtures for bio functions and GitHub Actions CI with pytest-cov, ruff, black, mypy. Use when adding tests to a bio tool, writing conftest.py fixtures, or building tests.yml/lint.yml CI workflows.

SKILL.md

7.7 KB, as published. Nobody here has run it

Testing and CI/CD for Bioinformatics

When to Use

  • Adding unit tests to a bioinformatics module (sequence parsing, coordinate math, scoring functions)
  • Writing conftest.py fixtures for temp FASTA/VCF files or shared test data
  • Setting up GitHub Actions to run pytest + coverage on every push/PR
  • Adding lint/type-check CI (ruff, black, mypy) alongside tests
  • Deciding what edge cases to test for biological data (0-based vs 1-based coords, IUPAC ambiguity codes, strand)

Version Compatibility

pytest ≥7.4, pytest-cov ≥4.1, Python ≥3.10, GitHub Actions actions/checkout@v4, actions/setup-python@v5, codecov/codecov-action@v4.

Prerequisites

pip install pytest pytest-cov ruff black isort mypy

Assumes a package layout with src/<pkg>/ and tests/ (see Project Structure below), and basic familiarity with Python functions/classes.

Goal: Test bioinformatics functions correctly, including the biology-specific edge cases that plain "does it run" tests miss.

Approach: Write the module, then a TestClass per function plus @pytest.mark.parametrize for the same assertion across many sequences.

## bio_utils.py
def gc_content(sequence: str) -> float:
    """Calculate GC content as a percentage (0-100). Empty input -> 0.0."""
    if not sequence:
        return 0.0
    seq = sequence.upper()
    gc = seq.count('G') + seq.count('C')
    return (gc / len(seq)) * 100


def reverse_complement(sequence: str) -> str:
    """Return the reverse complement of a DNA sequence; unknown bases -> 'N'."""
    complement = {'A': 'T', 'T': 'A', 'G': 'C', 'C': 'G', 'N': 'N',
                  'a': 't', 't': 'a', 'g': 'c', 'c': 'g', 'n': 'n'}
    return ''.join(complement.get(base, 'N') for base in reversed(sequence))


def find_motif(sequence: str, motif: str) -> list:
    """Find all 1-based, overlap-inclusive start positions of motif in sequence."""
    positions, start = [], 0
    while True:
        pos = sequence.find(motif, start)
        if pos == -1:
            break
        positions.append(pos + 1)  # 1-based
        start = pos + 1
    return positions
## test_bio_utils.py
import pytest
from bio_utils import gc_content, reverse_complement, find_motif


class TestGCContent:
    def test_balanced(self):
        assert gc_content("ATGC") == 50.0

    def test_empty_sequence(self):
        """Empty sequence must return 0.0, not raise."""
        assert gc_content("") == 0.0

    def test_lowercase(self):
        assert gc_content("atgc") == 50.0

    def test_with_n_bases(self):
        """N counts toward length but not toward GC."""
        assert gc_content("GCNN") == 50.0


class TestReverseComplement:
    def test_palindromic_site(self):
        """EcoRI site GAATTC is its own reverse complement."""
        assert reverse_complement("GAATTC") == "GAATTC"

    def test_handles_n(self):
        assert reverse_complement("ATNG") == "CNAT"


class TestFindMotif:
    def test_overlapping_occurrences(self):
        """Overlapping matches must all be reported."""
        assert find_motif("AAAA", "AA") == [1, 2, 3]

    def test_not_found(self):
        assert find_motif("ATGC", "GGG") == []


@pytest.mark.parametrize("seq,expected", [
    ("GGGG", 100.0), ("AAAA", 0.0), ("ATGC", 50.0), ("GC", 100.0),
])
def test_gc_content_parametrized(seq, expected):
    assert gc_content(seq) == expected

Goal: Reuse temp files and biological test data across many tests without duplicating setup.

Approach: Put shared fixtures in conftest.py; use the built-in tmp_path fixture for real files on disk.

## conftest.py
import pytest


@pytest.fixture
def sample_fasta_content():
    """Two-record FASTA string for parser tests."""
    return (
        ">gene1 beta-globin\n"
        "ATGGTGCACCTGACTCCTGAGGAGAAGTCTGCCGTTACTGCCCTGTGGGGCAAGGTGAAC\n"
        ">gene2 alpha-globin\n"
        "ATGGTGCTGTCTCCTGCCGACAAGACCAACGTCAAGGCCGCCTGGGGTAAGGTCGGCGCG\n"
    )


@pytest.fixture
def sample_fasta_file(tmp_path, sample_fasta_content):
    """Write sample_fasta_content to a real temp file and return its path."""
    fasta_path = tmp_path / "test.fasta"
    fasta_path.write_text(sample_fasta_content)
    return fasta_path


def test_parse_fasta(sample_fasta_content):
    from io import StringIO
    from Bio import SeqIO
    records = list(SeqIO.parse(StringIO(sample_fasta_content), "fasta"))
    assert len(records) == 2
    assert records[0].id == "gene1"


def test_fasta_file_exists(sample_fasta_file):
    assert sample_fasta_file.exists()
    assert sample_fasta_file.suffix == ".fasta"

pytest Commands

pytest -v                                  # verbose, one line per test
pytest test_bio_utils.py::TestGCContent    # run one class
pytest -x                                  # stop at first failure
pytest -k "gc or reverse"                  # keyword filter
pytest --cov=bio_utils --cov-report=html   # coverage report

GitHub Actions CI

## .github/workflows/tests.yml
name: Tests
on:
  push: { branches: [main] }
  pull_request: { branches: [main] }
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12"]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "${{ matrix.python-version }}" }
      - run: pip install pytest pytest-cov && pip install -r requirements.txt
      - run: pytest --cov=src --cov-report=xml --cov-report=term-missing
      - uses: codecov/codecov-action@v4
        with: { file: coverage.xml, fail_ci_if_error: false }
## .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.11" }
      - run: pip install ruff black isort mypy
      - run: black --check src/ tests/
      - run: ruff check src/ tests/
      - run: mypy src/ --ignore-missing-imports

Project Structure

my_tool/
├── .github/workflows/{tests.yml, lint.yml}
├── src/my_tool/{__init__.py, io.py, analysis.py, utils.py}
├── tests/{conftest.py, test_io.py, test_analysis.py, data/}
├── pyproject.toml
└── requirements.txt

Bioinformatics Testing Checklist

CategoryWhat to test
Edge casesEmpty, single-base, very long sequences
Case handlingLowercase, uppercase, mixed
Ambiguous basesN, R, Y, other IUPAC codes
Coordinates0-based vs 1-based, inclusive vs exclusive
StrandForward, reverse, reverse complement
File formatsMalformed, empty, compressed
NumericFloat comparisons with tolerance (pytest.approx)

Pitfalls

  • Coordinate systems: BED is 0-based half-open; VCF/GFF is 1-based inclusive — mixing them causes off-by-one variant/interval errors
  • Float comparison: never use == on p-values or scores; use pytest.approx()
  • Test data size: commit small synthetic files to tests/data/, never full genomes/BAMs
  • Fixture scope: default fixture scope is per-function; use scope="module" only for expensive, read-only setup to avoid state leaking between tests
  • CI matrix drift: pin the same Python versions in tests.yml that you claim to support in pyproject.toml

See Also

  • bio-workflow-management-snakemake-workflows
  • bio-workflow-management-nextflow-pipelines
  • bio-reporting-automated-qc-reports
  • bio-sequence-io-read-sequences

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.