Skip to content

Testing

Running tests

bash
uv run poe test                  # Unit tests (no QEMU needed)
uv run poe test:integration      # Integration tests (needs QEMU + images)
uv run poe ci                    # Full CI: check + test

# Specific file or test
uv run pytest tests/unit/test_core_config.py
uv run pytest tests/unit/test_core_config.py::test_default_config -v

Writing a unit test

Unit tests go in tests/unit/. They don't need QEMU. Mock dependencies as needed.

python
def test_my_feature():
    from quicksand_core import SandboxConfig
    config = SandboxConfig(image="ubuntu", memory="1G")  # SandboxConfig for internal/unit testing
    assert config.memory == "1G"

Writing an integration test

Integration tests go in tests/integration/. They boot real VMs.

python
import pytest

@pytest.mark.integration
async def test_my_feature(tmp_dir):
    async with Sandbox(image="ubuntu") as sb:
        result = await sb.execute("echo hello")
        assert result.exit_code == 0
        assert "hello" in result.stdout

Markers

MarkerUse when
@pytest.mark.integrationTest needs QEMU — skipped by poe test
@pytest.mark.slowTest takes significant time
@pytest.mark.dockerTest needs Docker daemon

Skip conditions (skip_no_qemu, skip_no_docker, skip_no_mke2fs) are in tests/conftest.py.

Streaming stdin integration

The stdin integration tests exercise both virtio-serial and HTTP. They require an image rebuilt with a guest agent that advertises stdin_streaming; older images skip these cases. To use a local save containing the updated agent:

bash
QUICKSAND_STDIN_TEST_IMAGE=/path/to/updated-save \
  uv run pytest tests/integration/execution/test_stdin.py -v