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 pytestimport oxytest as pytest - from pytest import ...from oxytest import ... - from pytest import approx, raises → (multi-module imports) - Aliases (import pytest as ptimport 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.