Skip to content

Migrating from pytest to oxytest

Oxytest is designed as a drop-in replacement for pytest. In most cases, migrating is as simple as changing one line of code.

Quick Migration

1. Install oxytest

pip install oxytest

2. Replace the import

Before (pytest):

import pytest

After (oxytest):

import oxytest as pytest

That's it. Your existing tests should work without changes.

3. Update your CI/CD

Replace pytest with oxytest in your CI configuration:

# GitHub Actions
- name: Run tests
  run: oxytest -v -n auto

4. Update your main.py entry points

# Before
import pytest
pytest.main(["-v", "tests/"])

# After
import oxytest as pytest
pytest.main(["-v", "tests/"])

5. Automated migration with oxytest migrate

Oxytest includes a built-in migration tool that automatically rewrites your imports:

# Preview changes (dry run)
oxytest migrate src/ --dry-run

# Perform migration (pytest → oxytest)
oxytest migrate src/

# Reverse migration (oxytest → pytest)
oxytest migrate src/ --reverse

# Check-only — exits with code 1 if any pytest imports remain
oxytest migrate src/ --check

The tool handles: - import pytest → import oxytest as pytest - from pytest import ... → from oxytest import ... - from pytest import approx, raises → (multi-module imports) - Aliases (import pytest as pt → import oxytest as pt) - Skips comments and strings

What Works Out of the Box

Feature Status
pytest.main() ✅
pytest.approx() ✅
pytest.raises() ✅
pytest.fixture() ✅
pytest.mark.parametrize() ✅
pytest.mark.skip() ✅
pytest.mark.skipif() ✅
pytest.mark.xfail() ✅
pytest.mark.usefixtures() ✅
pytest.skip() ✅
pytest.fail() ✅
pytest.importorskip() ✅
pytest.set_trace() ✅
tmp_path fixture ✅
capsys fixture ✅
capfd fixture ✅
monkeypatch fixture ✅
conftest.py ✅
Test classes ✅
Yield fixtures with teardown ✅
autouse=True fixtures ✅
Assert rewriting with comparison diffs ✅
Plugin system (pytest_addoption, pytest_configure, etc.) ✅
-v, -q, -x flags ✅
-k keyword filter ✅
-n parallel execution (built-in) ✅
JUnit XML output ✅
-s stdout capture control ✅

What's Different

1. Parallel execution is built-in

No need for pytest-xdist:

# pytest (requires plugin)
pip install pytest-xdist
pytest -n 4

# oxytest (built-in)
oxytest -n 4

2. Faster test discovery

Oxytest uses AST (Abstract Syntax Tree) scanning instead of importing modules. This means discovery is 10-100x faster for large codebases. The trade-off is that some dynamic test generation patterns (like __test__ attributes set in __init__) may not be discovered.

3. Coverage support

oxytest has built-in --cov support (requires pip install coverage or pip install oxytest[cov]). Use --cov=SOURCE to measure coverage, or run coverage run -m oxytest for zero-config usage.

CLI Flag Comparison

pytest oxytest Notes
pytest oxytest Same behavior
-v -v ✅
-q -q ✅
-x -x ✅
-k -k ✅
--tb=short --tb=short ✅
--tb=long --tb=long ✅
--tb=native --tb=native ✅
--tb=no --tb=no ✅
--junitxml --junitxml ✅
-s -s ✅
--maxfail --maxfail ✅
-n -n Built-in, no plugin required
--ignore --ignore ✅
--collect-only --collect-only (+ --co) ✅
--durations --durations ✅
-r -r ✅
--showlocals --showlocals ✅
--strict-markers --strict-markers ✅
--rootdir --rootdir ✅
--fixtures --fixtures ✅
--markers --markers ✅
--setup-show --setup-show ✅
--cache-clear --cache-clear ✅
--lf --lf ✅
--ff --ff ✅
-p plugins -p plugins ✅ Built-in, no plugin required
--cov --cov ✅ Requires coverage.py (optional dep)
--pdb --pdb ✅ Also --trace
--cov-report --cov-report ✅
--cov-branch --cov-branch ✅
--cov-fail-under --cov-fail-under ✅

4. VSCode integration

Oxytest includes a built-in VSCode plugin (JSON-RPC 2.0 over named pipe). When VSCode runs -p vscode_pytest, oxytest auto-loads its own implementation. No vscode-pytest plugin needed.

5. Configuration via pyproject.toml

Oxytest reads settings from [tool.oxytest] in pyproject.toml:

[tool.oxytest]
addopts = "-v --tb=short"
testpaths = ["tests/"]

CLI flags take precedence. No separate config file or setup.cfg needed. See Usage for all supported options.

Troubleshooting

Test not found?

Make sure your test files follow the convention: test_*.py or *_test.py.

Fixture not found?

Oxytest supports built-in fixtures (tmp_path, capsys, monkeypatch) and fixtures defined with @pytest.fixture. Ensure your conftest.py is in the correct directory.

Import error?

Oxytest runs tests in the same process. If you have module-level side effects in your test files, they may behave differently. Use conftest.py for shared setup.