Agent Skillsareal-project/AReaL › add-unit-tests

add-unit-tests

GitHub

指导在AReaL项目中添加单元测试,涵盖测试类型区分、文件命名规范、Arrange-Act-Assert编写模式及Pytest标记策略,适用于新增功能测试或提升覆盖率场景。

.claude/skills/add-unit-tests/SKILL.md areal-project/AReaL

Trigger Scenarios

用户询问如何添加测试 用户希望增加测试覆盖率 用户需要为新功能编写测试 用户想了解AReaL的测试模式

Install

npx skills add areal-project/AReaL --skill add-unit-tests -g -y
More Options

Non-standard path

npx skills add https://github.com/areal-project/AReaL/tree/main/.claude/skills/add-unit-tests -g -y

Use without installing

npx skills use areal-project/AReaL@add-unit-tests

指定 Agent (Claude Code)

npx skills add areal-project/AReaL --skill add-unit-tests -a claude-code -g -y

安装 repo 全部 skill

npx skills add areal-project/AReaL --all -g -y

预览 repo 内 skill

npx skills add areal-project/AReaL --list

SKILL.md

Frontmatter
{
    "name": "add-unit-tests",
    "description": "Guide for adding unit tests to AReaL. Use when user wants to add tests for new functionality or increase test coverage."
}

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 tests/test_<module>_<feature>.py Directly via pytest
Distributed Tests Test distributed/parallel behavior tests/torchrun/run_*.py 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 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
@pytest.mark.slow Test takes > 10 seconds (excluded from CI by default)
@pytest.mark.ci Slow test that must run in CI (use with @pytest.mark.slow)
@pytest.mark.asyncio Async test functions
@pytest.mark.skipif(cond, reason=...) Conditional skip
@pytest.mark.parametrize(...) Parameterized tests

CI Test Strategy:

  • @pytest.mark.slow: Excluded from CI by default (CI runs pytest -m "not slow")
  • @pytest.mark.slow + @pytest.mark.ci: Slow but must run in 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 torch.distributed.fake_pg for unit tests
  • Mock dist.get_rank() and dist.get_world_size() explicitly
  • Don't mock internals of FSDP/DTensor

GPU Test Constraints

  • Always skip gracefully when GPU unavailable
  • Clean up GPU memory: torch.cuda.empty_cache() in fixtures
  • Use smallest possible model/batch for unit tests

Assertions

  • Use torch.testing.assert_close() for tensor comparison
  • Specify rtol/atol explicitly for numerical tests
  • Avoid bare assert tensor.equal() - no useful error message

Reference Implementations

Test File Description Key Patterns
tests/test_utils.py Utility function tests Fixtures, parametrized tests
tests/test_examples.py Integration tests with dataset loading Dataset path resolution, success pattern matching
tests/test_fsdp_engine_nccl.py Distributed tests Torchrun integration

Common Mistakes

  • Missing test file registration: Ensure file follows test_*.py naming
  • GPU dependency without skip: Always use @pytest.mark.skipif for GPU tests
  • Incorrect tensor comparisons: Use torch.testing.assert_close() not 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 test_<what>_<condition>_<expected> pattern
  • No docstrings: Add descriptive docstrings to test functions

Integration with Other Skills

This skill complements other AReaL development skills:

  • After /add-dataset: Add tests for new dataset loaders
  • After /add-workflow: Add tests for new workflows
  • After /add-reward: Add tests for new reward functions
  • With planner agent: Reference this skill when planning test implementation

Running Tests

# First check GPU availability (many tests require GPU)
python -c "import torch; print('GPU available:', torch.cuda.is_available())"

# Run specific test file
uv run pytest 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 and multi-GPU)
# Note: Usually invoked via pytest test files
torchrun --nproc_per_node=2 tests/torchrun/run_<test>.py

Version History

  • d99124e Current 2026-07-05 09:13

Same Skill Collection

.agents/skills/add-archon-model/SKILL.md
.agents/skills/add-dataset/SKILL.md
.agents/skills/add-reward/SKILL.md
.agents/skills/add-unit-tests/SKILL.md
.agents/skills/add-workflow/SKILL.md
.agents/skills/commit-conventions/SKILL.md
.agents/skills/create-pr/SKILL.md
.agents/skills/debug-distributed/SKILL.md
.agents/skills/review-pr/SKILL.md
.agents/skills/translate-doc-zh/SKILL.md
.agents/skills/upgrade-deps/SKILL.md
.claude/skills/add-archon-model/SKILL.md
.claude/skills/add-dataset/SKILL.md
.claude/skills/add-reward/SKILL.md
.claude/skills/add-workflow/SKILL.md
.claude/skills/commit-conventions/SKILL.md
.claude/skills/debug-distributed/SKILL.md
.opencode/skills/add-archon-model/SKILL.md
.opencode/skills/add-dataset/SKILL.md
.opencode/skills/add-reward/SKILL.md
.opencode/skills/add-unit-tests/SKILL.md
.opencode/skills/add-workflow/SKILL.md
.opencode/skills/commit-conventions/SKILL.md
.opencode/skills/debug-distributed/SKILL.md

Metadata

Files
0
Version
d99124e
Hash
389834b7
Indexed
2026-07-05 09:13

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-05 20:46
浙ICP备14020137号-1 $방문자$