Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions .github/workflows/test_be.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ jobs:
uses: styfle/[email protected]

- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for git diff

- name: 🥚 Install Hatch
uses: pypa/hatch@install
Expand All @@ -119,23 +121,33 @@ jobs:
python-version: ${{ matrix.python-version }}

# Test with base dependencies
- name: Test with base dependencies
- name: Test changed with base dependencies
if: ${{ matrix.dependencies == 'core' }}
run: |
# On PRs, compare against base branch; on main, compare against HEAD~1
CHANGED_FROM="${{ github.base_ref && format('origin/{0}', github.base_ref) || 'HEAD~1' }}"
hatch run +py=${{ matrix.python-version }} test:test tests/ \
-v \
-k "not test_cli" \
--durations=10 \
-p packages.pytest_changed --changed-from=$CHANGED_FROM \
--picked=first

# Test with optional dependencies
- name: Test with optional dependencies
- name: Test changed with optional dependencies
if: ${{ matrix.dependencies == 'core,optional' }}
# Include all tests on 3.13 or main
run: |
INCLUDE_UNCHANGED=${{ matrix.python-version == '3.13' }} || ${{ github.ref == 'refs/heads/main' }}
# On PRs, compare against base branch; on main, compare against HEAD~1
CHANGED_FROM="${{ github.base_ref && format('origin/{0}', github.base_ref) || 'HEAD~1' }}"

hatch run +py=${{ matrix.python-version }} test-optional:test tests/ \
-v \
-k "not test_cli" \
--durations=10 \
-p packages.pytest_changed --changed-from=$CHANGED_FROM \
--include-unchanged=$INCLUDE_UNCHANGED \
--picked=first

# Test with minimal dependencies using lowest resolution
Expand All @@ -144,11 +156,14 @@ jobs:
- name: Test with minimal dependencies (lowest resolution)
if: ${{ matrix.dependencies == 'minimal' }}
run: |
# On PRs, compare against base branch; on main, compare against HEAD~1
CHANGED_FROM="${{ github.base_ref && format('origin/{0}', github.base_ref) || 'HEAD~1' }}"
hatch run +py=${{ matrix.python-version }} test:test tests/ \
-v \
-k "not test_cli" \
--durations=10 \
--picked=first
--picked=first \
-p packages.pytest_changed --changed-from=$CHANGED_FROM
env:
UV_RESOLUTION: lowest

Expand Down Expand Up @@ -177,8 +192,13 @@ jobs:

- name: Test with optional dependencies
run: |
hatch run +py=3.12 test-optional:test -v tests/ -k "not test_cli" --durations=10 \
--cov=marimo --cov-report=xml --junitxml=junit.xml -o junit_family=legacy
hatch run +py=3.12 test-optional:test \
-v \
tests/ \
-k "not test_cli" \
--durations=10 \
--picked=first \
--cov=marimo --cov-report=xml --junitxml=junit.xml -o junit_family=legacy

# Only upload coverage on `main` so it is not blocking
# and only on `3.12`, `ubuntu-latest`, with optional deps since it is mostly duplicate
Expand Down
2 changes: 1 addition & 1 deletion marimo/_data/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class DataTableColumn(BaseStruct):
sample_values: list[Any]

def __post_init__(self) -> None:
# Sometimes like pandas, sqlalchemy or ibis may return column names as objects
# Sometimes libraries (like pandas, sqlalchemy or ibis) may return column names as objects
# instead of strings, although their type hints are str
# Instead of trying to track this down each time, just convert to string
self.name = str(self.name)
Expand Down
70 changes: 70 additions & 0 deletions packages/pytest_changed/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# pytest-changed Plugin

A pytest plugin that uses `ruff analyze graph` to intelligently discover and run only the tests affected by code changes.

## Overview

This plugin analyzes your git changes and uses Ruff's dependency graph analysis to determine which tests need to be run. It performs a search through the dependency graph to find all files affected by your changes, then runs only the tests that could be impacted.

## Usage

**Run only tests affected by changes from main branch:**

```bash
pytest -p packages.pytest_changed --changed-from=main
```

**Using Hatch:**

```bash
hatch run +py=3.12 test:test -p packages.pytest_changed --changed-from=main tests/
```

### Compare Against Different References

```bash
# Compare against HEAD (staged changes)
pytest -p packages.pytest_changed --changed-from=HEAD

# Compare against origin/main
pytest -p packages.pytest_changed --changed-from=origin/main
```

### Preview What Would Be Run

Use `--collect-only` to see which tests would be selected without running them:

```bash
pytest -p packages.pytest_changed --changed-from=main --collect-only tests/
```

### Include Unchanged Tests

Run affected tests plus all other tests:

```bash
pytest -p packages.pytest_changed --changed-from=main --include-unchanged tests/
```

### Run Specific Test Directories

The plugin respects pytest's normal path filtering:

```bash
pytest -p packages.pytest_changed --changed-from=main tests/_runtime/
```

## How It Works

1. **Find Changes**: Uses `git diff --name-only <ref>` to find Python files that have changed
2. **Build Graph**: Runs `ruff analyze graph --direction dependents` to build a dependency graph
3. **Graph Traversal**: Performs BFS from changed files to find all affected files
4. **Filter Tests**: Identifies which affected files are test files
5. **Run Tests**: Only runs pytest on the affected test files

## Configuration Options

### Command Line Options

- `--changed-from=<ref>`: Git reference to compare against (required to activate plugin)
- `--include-unchanged`: Also run tests that haven't changed (optional)
Loading
Loading