Agent skill

Agent-Core Python Testing

by openJiuwen-ai in openJiuwen-ai/agent-core

Pytest patterns for the agent-core codebase: a red-green-refactor workflow, conftest fixtures, custom marks, monkeypatch and patch mocking, and async tests.

Apache-2.0Auto-check passedTesting & QA

Install Agent-Core Python Testing

skills CLI
$ npx skills add openJiuwen-ai/agent-core --skill python-testing -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install openJiuwen-ai/agent-core python-testing --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/openJiuwen-ai/agent-core.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/python-testing .claude/skills/python-testing && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
python-testing
GitHub stars
442
Token cost
~2.3k tokens
SKILL.md length
199 words
Files
1
Skills in repo
10
Repo updated
First seen
Licence
Apache-2.0

At a glance

Pytest patterns for the agent-core codebase: a red-green-refactor workflow, conftest fixtures, custom marks, monkeypatch and patch mocking, and async tests.

  • Works in 3 steps: RED — Write a failing test that… → GREEN — Write the minimal implementation… → REFACTOR — Improve code quality while…
  • Writing tests for agent-core code, starting with a failing test
  • SKILL.md covers TDD Workflow, Fixtures, Pytest Marks and Mocking, plus 3 more sections
  • Calls pytest

What it does

Written for the openJiuwen agent-core repository, the guide has the agent write a failing test first, make the smallest change that passes and then refactor with the tests still green. It shows where fixtures belong, in a project-wide tests conftest file or a module-level one, and gives patterns for parametrized fixtures, factory fixtures and the sparing use of autouse for global resets.

Pytest marks are defined in pyproject.toml, for example a unit mark for fast tests with no I/O, so subsets can be picked with pytest -m. For mocking it prefers monkeypatch for simple cases, uses patch for class methods and recommends autospec so mocks match real signatures. Async tests use the pytest asyncio mark.

When your agent uses it

  • Writing tests for agent-core code, starting with a failing test
  • Organizing shared fixtures in conftest files
  • Choosing between monkeypatch and patch when mocking
  • Splitting fast unit tests from slow or integration tests with pytest marks

Example prompts

  • “Write a failing test for the new ability manager behavior before implementing it.”
  • “Add a factory fixture that builds tool cards with default values.”
  • “Mock the async run step in the agent tests using autospec.”
  • “Define a unit mark in pyproject.toml and run only the fast tests.”

Requirements

  • Python with pytest

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. RED — Write a failing test that describes the desired behavior
  2. GREEN — Write the minimal implementation to make the test pass
  3. REFACTOR — Improve code quality while keeping tests green

What it can do on your machine

Read from SKILL.md and the folder at commit 8345a27. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • pytest

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Agent-Core Python Testing loads about 2.3k tokens when it runs. Until then it costs about 25 tokens; SKILL.md has 199 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~25
When it runs · the whole SKILL.md, loaded when a task matches
~2.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from openJiuwen-ai/agent-core at commit 8345a27, republished under its Apache-2.0 licence (© openJiuwen-ai). 199 words, ~2,268 tokens.

Download SKILL.mdSave it as .claude/skills/python-testing/SKILL.md (or your agent's skills folder).
name
python-testing
description
Deep pytest guide for agent-core: fixtures, mocking, async tests, and TDD workflow.

Python Testing

Comprehensive pytest patterns for agent-core. This skill extends .claude/rules/python/testing.md and .claude/rules/testing.md.

TDD Workflow

Write tests before implementation. Follow the red-green-refactor cycle:

  1. RED — Write a failing test that describes the desired behavior
  2. GREEN — Write the minimal implementation to make the test pass
  3. REFACTOR — Improve code quality while keeping tests green

For agent-core, this means:

python
# RED: Write the test first
class TestAbilityManager:
    @pytest.mark.asyncio
    async def test_registers_tool(self):
        manager = AbilityManager()
        card = ToolCard(name="echo", description="echo input", parameters={})

        await manager.register_tool(card, echo_handler)

        assert "echo" in manager.list_tools()

    # GREEN: Minimal implementation
    # ...

    # REFACTOR: Clean up, add edge cases
    @pytest.mark.asyncio
    async def test_raises_on_duplicate_registration(self):
        manager = AbilityManager()
        card = ToolCard(name="echo", description="echo input", parameters={})
        await manager.register_tool(card, echo_handler)

        with pytest.raises(ConfigurationError, match="already registered"):
            await manager.register_tool(card, echo_handler)

Fixtures

conftest.py Organization

Define fixtures in tests/conftest.py for project-wide fixtures, or in tests/unit_tests/<module>/conftest.py for module-specific fixtures.

python
# tests/conftest.py
import pytest
from unittest import mock

@pytest.fixture
def mock_llm_client():
    """Provides a mocked LLM client for all tests."""
    with mock.patch("openjiuwen.core.foundation.LLMClient") as cls:
        instance = mock.MagicMock()
        instance.call.return_value = '{"result": "ok"}'
        cls.return_value = instance
        yield instance

@pytest.fixture(scope="module")
def sample_agent_card():
    """Module-scoped: created once per test module."""
    return AgentCard(id="test-agent", name="TestAgent", version="1.0")

@pytest.fixture
def temp_workspace(tmp_path):
    """Provides a clean temporary directory for each test."""
    workspace = tmp_path / "workspace"
    workspace.mkdir()
    yield workspace
    # Cleanup happens automatically via tmp_path
Parametrized Fixtures
python
@pytest.fixture(params=["haiku", "sonnet", "opus"])
def llm_model(request: pytest.FixtureRequest):
    return request.param

async def test_llm_client(llm_model: str):
    client = LLMClient(model=llm_model)
    result = await client.call("hello")
    assert result is not None
Factory Fixtures
python
@pytest.fixture
def make_tool_card():
    """Factory fixture: creates ToolCards with defaults."""
    def _make(name: str = "test-tool", **kwargs) -> ToolCard:
        defaults = {
            "description": "a test tool",
            "parameters": {},
            "version": "1.0",
        }
        defaults.update(kwargs)
        return ToolCard(name=name, **defaults)
    return _make

async def test_registers_custom_tool(make_tool_card):
    card = make_tool_card(name="custom")
    manager = AbilityManager()
    await manager.register_tool(card, handler)
    assert "custom" in manager.list_tools()
autouse Fixtures

Use autouse sparingly — only for global setup that must happen for every test in the scope:

python
@pytest.fixture(autouse=True)
def reset_global_state():
    """Reset global state before each test to ensure isolation."""
    original = Runner.resource_mgr
    Runner.resource_mgr = ResourceManager()
    yield
    Runner.resource_mgr = original

Pytest Marks

Defining Custom Marks

In pyproject.toml:

toml
[tool.pytest.ini_options]
markers = [
    "unit: fast, deterministic tests with no I/O",
    "integration: tests requiring external services",
    "slow: long-running tests (skipped by default)",
    "e2e: end-to-end workflow tests",
]
Selective Execution
bash
# Run only fast unit tests (skip slow + integration)
pytest -m "unit"

# Run unit + integration, skip slow
pytest -m "not slow"

# Run everything including slow tests
pytest -m ""

# Run only e2e tests
pytest -m "e2e"

Mocking

Monkeypatch

Use monkeypatch for simple cases — prefer it over @patch decorators:

python
def test_reads_config(monkeypatch, tmp_path):
    config_file = tmp_path / "config.json"
    config_file.write_text('{"timeout": 30}')

    monkeypatch.setattr(
        "openjiuwen.core.config.CONFIG_PATH",
        config_file
    )

    config = load_config()
    assert config.timeout == 30
@patch Decorator

Use @patch when mocking class methods or when the mock needs to be accessed inside the test:

python
from unittest import mock

@mock.patch("openjiuwen.harness.DeepAgent._run_step", new_callable=mock.AsyncMock)
async def test_delegates_to_subagent(mock_run_step):
    mock_run_step.return_value = StepResult(
        status="success",
        subagent_called=True,
    )

    agent = DeepAgent()
    result = await agent.run("complex task")

    assert result.subagent_called
    mock_run_step.assert_called_once()
Autospec

Use autospec=True to automatically match the signature of the real method:

python
with mock.patch(
    "openjiuwen.core.foundation.LLMClient.call",
    autospec=True
) as mock_call:
    mock_call.return_value = '{"choices": [{"message": {"content": "ok"}}]}'
    # mock_call.assert_called_once_with("prompt")  # Enforces correct signature
AsyncMock

For async methods:

python
from unittest import mock

with mock.patch(
    "openjiuwen.harness.DeepAgent._run_step",
    new_callable=mock.AsyncMock
) as mock_step:
    mock_step.return_value = StepResult(status="success")
    result = await agent.run("test")
    assert result.status == "success"
Mocking Context Managers
python
from unittest import mock

def test_sandbox_executes_within_scope():
    with mock.patch(
        "openjiuwen.core.sys_operation.sandbox.SandboxedRunner.run"
    ) as mock_run:
        mock_run.return_value = CommandResult(stdout="ok", stderr="", code=0)

        result = sandbox.run("echo hello")
        assert result.stdout == "ok"
        mock_run.assert_called_once_with("echo hello")

Async Testing

pytest-asyncio Configuration

In pyproject.toml:

toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
Async Test Functions
python
@pytest.mark.asyncio
async def test_ability_manager_registers_tool():
    manager = AbilityManager()
    card = ToolCard(name="test", description="test tool", parameters={})

    await manager.register_tool(card, handler)

    tools = manager.list_tools()
    assert "test" in tools
IsolatedAsyncioTestCase

Use unittest.IsolatedAsyncioTestCase for test classes that need strict per-test isolation:

python
from unittest import IsolatedAsyncioTestCase

class TestRunner(IsolatedAsyncioTestCase):
    async def asyncSetUp(self) -> None:
        self.runner = await create_runner()
        self.runner.resource_mgr.clear()

    async def asyncTearDown(self) -> None:
        await self.runner.shutdown()

    async def test_it_executes_task(self) -> None:
        result = await self.runner.execute("test task")
        self.assertEqual(result.status, "success")
tmp_path for File Operations
python
@pytest.mark.asyncio
async def test_saves_session(tmp_path):
    session_dir = tmp_path / "sessions"
    session_dir.mkdir()

    manager = SessionManager(base_dir=session_dir)
    await manager.save(SessionData(id="s1", turns=[]))

    assert (session_dir / "s1.json").exists()

Test Organization

Mirror the source path in test paths:

SourceTest
openjiuwen/harness/deep_agent.pytests/unit_tests/harness/test_deep_agent.py
openjiuwen/core/single_agent/react_agent.pytests/unit_tests/core/single_agent/test_react_agent.py
openjiuwen/core/workflow/engine.pytests/unit_tests/core/workflow/test_engine.py

pytest.ini + pyproject.toml Configuration

ini
# pytest.ini
[pytest]
asyncio_mode = auto
asyncio_default_fixture_loop_scope = function
testpaths = tests/unit_tests tests/system_tests
markers =
    unit: fast deterministic tests, no I/O
    integration: tests requiring external services
    slow: long-running tests, skipped by default
    e2e: end-to-end workflow tests
toml
# pyproject.toml additions
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = [
    "ignore::DeprecationWarning",
]

[tool.coverage.run]
source = ["openjiuwen/"]
omit = [
    "*/tests/*",
    "*/__pycache__/*",
    "*/migrations/*",
]

[tool.coverage.report]
exclude_lines = [
    "pragma: no cover",
    "if TYPE_CHECKING:",
    "raise NotImplementedError",
]
fail_under = 80

© openJiuwen-ai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/python-testing of openJiuwen-ai/agent-core.

Open the folder on GitHubat commit 8345a27

Compare with similar skills

Agent-Core Python Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Agent-Core Python Testing compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Agent-Core Python Testing this skillopenJiuwen-ai/agent-core442—~2.3kAutomated safety check: PassApache-2.0
Python Testingaffaan-m/ECC275k6 repos~4.7kAutomated safety check: PassMIT
Python Testingaffaan-m/ECC275k3 repos~4.2kAutomated safety check: PassMIT
Python Testing Patternsjh941213/my-cc-harness12617 repos~5.4kAutomated safety check: PassNone
Python Testingaffaan-m/ECC275k2 repos~4.3kAutomated safety check: PassMIT
Python Testingaffaan-m/ECC275k1 repos~4.9kAutomated safety check: PassMIT

Similar skills

  • Python Testing

    affaan-m/ECC

    Python testing strategies using pytest, TDD methodology, fixtures, mocking, parametrization, and coverage requirements.

    275k GitHub starsUsed in 6 repos~4.7k tokens
    Testing & QAAuto-check passed
  • Python Testing

    affaan-m/ECC

    使用pytest的Python测试策略,包括TDD方法、夹具、模拟、参数化和覆盖率要求. An agent skill from affaan-m/ECC.

    275k GitHub starsUsed in 3 repos~4.2k tokens
    Testing & QAAuto-check passed
  • Python Testing Patterns

    jh941213/my-cc-harness

    Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development.

    126 GitHub starsUsed in 17 repos~5.4k tokens
    Testing & QAAuto-check passed
  • Python Testing

    affaan-m/ECC

    pytest、TDD手法、フィクスチャ、モック、パラメータ化、カバレッジ要件を使用したPythonテスト戦略. An agent skill from affaan-m/ECC.

    275k GitHub starsUsed in 2 repos~4.3k tokens
    Testing & QAAuto-check passed
  • Python Testing

    affaan-m/ECC

    pytest, TDD metodolojisi, fixture'lar, mocking, parametrizasyon ve coverage gereksinimleri kullanarak Python test stratejileri.

    275k GitHub starsUsed in 1 repo~4.9k tokens
    Testing & QAAuto-check passed
  • TDD Guide

    alirezarezvani/claude-skills

    Test-driven development skill for writing unit tests, generating test fixtures and mocks, analyzing coverage gaps, and guiding red-green-refactor workflows across Jest, Pytest, JUnit, Vitest, and…

    28k GitHub stars~3.4k tokensUpdated 1 mo ago
    Testing & QAAuto-check passed

More from openJiuwen-ai/agent-core

All 10 skills in this repo
  • Skill Safety Evaluator

    openJiuwen-ai/agent-core

    Static safety audit of a SKILL.md that scores five dimensions and acts as a gate: skills below the pass line do not ship, whatever else they score.

    442 GitHub stars~3.5k tokensUpdated today
    Auto-check: warnings
  • Repository Health and Gap Assessor

    openJiuwen-ai/agent-core

    Runs a read-only assessment in one of two modes, a repository health check or a runtime extension gap review, and reports findings as a markdown table.

    442 GitHub stars~613 tokensUpdated today
    Auto-check passed
  • Engineering Communication Rules

    openJiuwen-ai/agent-core

    Chinese-language rules for how an agent writes commit messages, PR descriptions, session journals, handoff issues and requests for help.

    442 GitHub stars~625 tokensUpdated today
    Auto-check passed
  • Python Patterns for agent-core

    openJiuwen-ai/agent-core

    Reference for idiomatic Python in the agent-core codebase: immutability, protocols, exception hierarchies, context managers and async patterns.

    442 GitHub stars~2.1k tokensUpdated today
    Auto-check passed
  • Agent-Core Security Checklist

    openJiuwen-ai/agent-core

    A ten-category security checklist for the agent-core codebase, to run before any security-sensitive change or pull request: secrets, input validation, SQL, access control and prompt injection.

    442 GitHub stars~1.7k tokensUpdated today
    Auto-check: notes
  • Verification Loop

    openJiuwen-ai/agent-core

    Formalizes agent-core's make check/type-check/test/fix pipeline into a structured 6-phase verification skill.

    442 GitHub stars~818 tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Agent-Core Python Testing

What does Agent-Core Python Testing do?

Pytest patterns for the agent-core codebase: a red-green-refactor workflow, conftest fixtures, custom marks, monkeypatch and patch mocking, and async tests. Written for the openJiuwen agent-core repository, the guide has the agent write a failing test first, make the smallest change that passes and then refactor with the tests still green. It shows where fixtures belong, in a project-wide tests conftest file or a module-level one, and gives patterns for parametrized fixtures, factory fixtures and the sparing use of autouse for global resets.

When should I use Agent-Core Python Testing?

Agent-Core Python Testing fits situations like: writing tests for agent-core code, starting with a failing test; organizing shared fixtures in conftest files; choosing between monkeypatch and patch when mocking; splitting fast unit tests from slow or integration tests with pytest marks.

How do I install Agent-Core Python Testing in Claude Code?

Run `npx skills add openJiuwen-ai/agent-core --skill python-testing -a claude-code`. Or copy the skill folder (.claude/skills/python-testing in openJiuwen-ai/agent-core) into .claude/skills/python-testing in your project. Claude Code loads it when a task matches its description.

How do I install Agent-Core Python Testing in Codex?

Run `npx skills add openJiuwen-ai/agent-core --skill python-testing -a codex`. Or copy the skill folder (.claude/skills/python-testing in openJiuwen-ai/agent-core) into .agents/skills/python-testing in your project. Codex loads it when a task matches its description.

Can I use Agent-Core Python Testing in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add openJiuwen-ai/agent-core --skill python-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/python-testing, .gemini/skills/python-testing, .github/skills/python-testing and .opencode/skills/python-testing in your project.

What does Agent-Core Python Testing need to run?

Going by SKILL.md and its folder, Agent-Core Python Testing needs the command-line tools its instructions call (pytest). Our summary lists: Python with pytest.

Does Agent-Core Python Testing access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Agent-Core Python Testing safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Agent-Core Python Testing use?

Agent-Core Python Testing is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Agent-Core Python Testing use?

About 2.3k tokens (SKILL.md is roughly 9.1k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Agent-Core Python Testing?

Skills that share tags, products or a category with Agent-Core Python Testing: Python Testing (affaan-m/ECC, 275k stars), Python Testing (affaan-m/ECC, 275k stars), Python Testing Patterns (jh941213/my-cc-harness, 126 stars) and Python Testing (affaan-m/ECC, 275k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Agent-Core Python Testing?

openJiuwen-ai (a GitHub organization) maintains it in openJiuwen-ai/agent-core, which has 442 GitHub stars. The repository holds 10 skills in this directory. The repository was last updated on October 8, 2026.

Source: openJiuwen-ai/agent-core on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.