Claude-skill-registry add-unit-tests
Guide for adding unit tests to AReaL. Use when user wants to add tests for new functionality or increase test coverage.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/add-unit-tests" ~/.claude/skills/majiayu000-claude-skill-registry-add-unit-tests && rm -rf "$T"
manifest:
skills/data/add-unit-tests/SKILL.mdsource content
Add Unit Tests
Add unit tests to AReaL following the project's testing conventions.
When to Use
This skill is triggered when:
- User asks "how do I add tests?"
- User wants to increase test coverage
- User needs to write tests for new functionality
- User wants to understand AReaL testing patterns
Step-by-Step Guide
Step 1: Understand Test Types
AReaL has two main test categories:
| Test Type | Purpose | Location Pattern | How It Runs |
|---|---|---|---|
| Unit Tests | Test individual functions/modules | | Directly via pytest |
| Distributed Tests | Test distributed/parallel behavior | | Via torchrun (called by pytest subprocess) |
Note: All tests are invoked via pytest. Distributed tests use
torchrun but are
still called from pytest test files.
Step 2: Create Test File Structure
Create test file with naming convention:
test_<module>_<feature>.py
import pytest import torch # Import the module to test from areal.dataset.gsm8k import get_gsm8k_sft_dataset from areal.tests.utils import get_dataset_path # Optional test utilities # For mocking tokenizer: from unittest.mock import MagicMock
Step 3: Write Test Functions
Follow Arrange-Act-Assert pattern:
def test_function_under_condition_returns_expected(): """Test that function returns expected value under condition.""" # Arrange input_data = 5 expected_output = 10 # Act result = function_under_test(input_data) # Assert assert result == expected_output
Step 4: Add Pytest Markers and CI Strategy
Use appropriate pytest markers:
| Marker | When to Use |
|---|---|
| Test takes > 10 seconds (excluded from CI by default) |
| Slow test that must run in CI (use with ) |
| Async test functions |
| Conditional skip |
| Parameterized tests |
CI Test Strategy:
: Excluded from CI by default (CI runs@pytest.mark.slow
)pytest -m "not slow"
+@pytest.mark.slow
: Slow but must run in CI@pytest.mark.ci- No marker: Runs in CI (fast unit tests)
@pytest.mark.asyncio async def test_async_function(): result = await async_function() assert result == expected @pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA not available") def test_gpu_feature(): tensor = torch.tensor([1, 2, 3], device="cuda") # ... assertions @pytest.mark.parametrize("batch_size", [1, 4, 16]) def test_with_parameters(batch_size): # Parameterized test @pytest.mark.slow def test_slow_function(): # Excluded from CI by default @pytest.mark.slow @pytest.mark.ci def test_slow_but_required_in_ci(): # Slow but must run in CI
Step 5: Mock Distributed Environment
For unit tests that need distributed mocks:
import torch.distributed as dist def test_distributed_function(monkeypatch): monkeypatch.setattr(dist, "get_rank", lambda: 0) monkeypatch.setattr(dist, "get_world_size", lambda: 2) result = distributed_function() assert result == expected
Step 6: Handle GPU Dependencies
Always skip gracefully when GPU unavailable:
CUDA_AVAILABLE = torch.cuda.is_available() @pytest.mark.skipif(not CUDA_AVAILABLE, reason="CUDA not available") def test_gpu_function(): tensor = torch.tensor([1, 2, 3], device="cuda") # ... assertions
Key Requirements (Based on testing.md)
Mocking Distributed
- Use
for unit teststorch.distributed.fake_pg - Mock
anddist.get_rank()
explicitlydist.get_world_size() - Don't mock internals of FSDP/DTensor
GPU Test Constraints
- Always skip gracefully when GPU unavailable
- Clean up GPU memory:
in fixturestorch.cuda.empty_cache() - Use smallest possible model/batch for unit tests
Assertions
- Use
for tensor comparisontorch.testing.assert_close() - Specify
/rtol
explicitly for numerical testsatol - Avoid bare
— no useful error messageassert tensor.equal()
Reference Implementations
| Test File | Description | Key Patterns |
|---|---|---|
| Utility function tests | Fixtures, parametrized tests |
| Integration tests with dataset loading | Dataset path resolution, success pattern matching |
| Distributed tests | Torchrun integration |
Common Mistakes
- ❌ Missing test file registration: Ensure file follows
namingtest_*.py - ❌ GPU dependency without skip: Always use
for GPU tests@pytest.mark.skipif - ❌ Incorrect tensor comparisons: Use
nottorch.testing.assert_close()assert tensor.equal() - ❌ Memory leaks in GPU tests: Clean up with
torch.cuda.empty_cache() - ❌ Mocking too much: Don't mock FSDP/DTensor internals
- ❌ Unclear test names: Follow
patterntest_<what>_<condition>_<expected> - ❌ No docstrings: Add descriptive docstrings to test functions
Integration with Other Skills
This skill complements other AReaL development skills:
- After
: Add tests for new dataset loaders/add-dataset - After
: Add tests for new workflows/add-workflow - After
: Add tests for new reward functions/add-reward - With
agent: Reference this skill when planning test implementationplanner
Running Tests
<!-- ================================================================================ MAINTAINER GUIDE ================================================================================ Location: .claude/skills/add-unit-tests/SKILL.md Invocation: /add-unit-tests ## Purpose Step-by-step guide for adding unit tests to AReaL. ## How to Update ### When Testing Conventions Change 1. Update "Key Requirements" section based on `testing.md` 2. Update test examples to match new patterns 3. Update reference implementations ### When Test Types Need Update 1. Update "Understand Test Types" table (currently two main types) 2. Add new examples if needed 3. Update common mistakes ### Integration with Other Skills Ensure references to other skills (`/add-dataset`, `/add-workflow`, `/add-reward`) remain accurate. ================================================================================ --># Run specific test file uv run pytest areal/tests/test_<name>.py # Skip slow tests (CI default) uv run pytest -m "not slow" # Run with verbose output uv run pytest -v # Run distributed tests (requires torchrun) # Note: Usually invoked via pytest test files torchrun --nproc_per_node=2 areal/tests/torchrun/run_<test>.py