Token导航 LogoToken导航

Agent Skill · 研究检索

test-writer(测试编写者)

用于辅助测试设计、自动化测试、用例整理和回归验证。它适合让 Agent 编写单元测试、端到端测试、测试计划或根据失败日志定位问题。使用时需要确认项目测试框架、运行命令和夹具数据,避免为了通过测试而改坏真实逻辑;涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

test-writer 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证为 MIT,暂无第三方扫描结果,按安装量在研究检索类的 73,675 个 Skill 里排第 68,166。

总安装 235周安装 10GitHub Stars 公开资料未说明下载 82核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:test-writer(测试编写者)
来源仓库:https://github.com/nguyenthienthanh/aura-frog
仓库路径:skills/test-writer
安装命令:
npx skills add nguyenthienthanh/aura-frog --skill "test-writer"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add nguyenthienthanh/aura-frog --skill "test-writer"

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

用于辅助测试设计、自动化测试和用例整理。适合编写单元测试、端到端测试或根据日志定位问题。使用时需确认测试框架、运行命令和夹具数据。避免为了通过测试而破坏真实逻辑。test-writer 属于研究检索类 Skill,可作为该场景下的辅助能力补充。涉及浏览器或外部服务时需区分环境。

适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/test-writer

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add nguyenthienthanh/aura-frog --skill "test-writer";命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

test-writer 怎么安装?

在终端执行 npx skills add nguyenthienthanh/aura-frog --skill "test-writer"。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

test-writer 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

test-writer 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

test-writer 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

test-writer 用的人多吗?

公开数据是累计安装 235 次,近一周安装 10 次,下载 82 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

test-writer 安全吗?

没有查到第三方扫描结果,安全性无法从公开资料判断,安装前请自行审查源码、依赖和命令行为。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 没有第三方扫描结果,安全性只能靠自己读源码判断。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 要求有安全扫描结论才肯安装的团队。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
test-writer

测试编写者 · 本页

235—需要联网MIT未收录

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
test-writer
description
Write tests with TDD. Supports Jest, Cypress, Detox, PHPUnit, PyTest, Go testing.
autoInvoke
true
priority
medium
triggers
allowed-tools
Read, Grep, Glob, Edit, Write, Bash

Aura Frog Test Writer

Priority: MEDIUM - Use for test-related requests Version: 1.0.0


When to Use

USE for:

  • Adding tests to existing code
  • Improving test coverage
  • Creating test suites
  • TDD implementation (Phase 5a)
  • Writing specific test types (unit, integration, E2E)

DON'T use for:

  • Bug fixes without explicit test request → use bugfix-quick
  • Full feature implementation → use workflow-orchestrator

Test Writing Process

1. Analyze Target Code

1. Read file with Read tool
2. Identify testable units:
   - Functions/methods
   - Components
   - API endpoints
   - Data transformations
3. List dependencies to mock

2. Plan Strategy

TypeUse ForScope
UnitIndividual functions/componentsSingle unit, mocked deps
IntegrationModule interactions, API callsMultiple units together
E2EComplete user flowsFull system, real deps

3. Write Tests

For NEW code (TDD - Phase 5a):

1. Write failing tests (RED)
   → Tests MUST fail
   → If they pass, tests are wrong
2. Implement code (GREEN)
   → Minimal code to pass
3. Refactor (REFACTOR)
   → Tests must stay green

For EXISTING code:

1. Write tests that pass (validate current behavior)
2. Add edge case tests
3. Add negative tests (error handling)

4. Verify Coverage

# Check target: 80% or project-specific
npm test -- --coverage          # JavaScript/TypeScript
pytest --cov=. --cov-report=html # Python
./vendor/bin/phpunit --coverage-html coverage # PHP
go test -coverprofile=coverage.out ./... # Go

Framework-Specific Templates

JavaScript/TypeScript - Jest

Unit Test (Function):

describe('calculateDiscount', () => {
  it('should apply 10% discount for orders over $100', () => {
    expect(calculateDiscount(150)).toBe(135);
  });

  it('should return original price for orders under $100', () => {
    expect(calculateDiscount(50)).toBe(50);
  });

  it('should throw error for negative amounts', () => {
    expect(() => calculateDiscount(-10)).toThrow('Invalid amount');
  });
});

Unit Test (React Component):

import { render, fireEvent, screen } from '@testing-library/react';
import { LoginButton } from './LoginButton';

describe('LoginButton', () => {
  it('should call onLogin when clicked', () => {
    const onLogin = jest.fn();
    render(<LoginButton onLogin={onLogin} />);

    fireEvent.click(screen.getByRole('button', { name: /login/i }));

    expect(onLogin).toHaveBeenCalledTimes(1);
  });

  it('should show loading state', () => {
    render(<LoginButton isLoading={true} />);

    expect(screen.getByTestId('loading-spinner')).toBeVisible();
  });

  it('should be disabled when loading', () => {
    render(<LoginButton isLoading={true} />);

    expect(screen.getByRole('button')).toBeDisabled();
  });
});

React Native - Jest + React Native Testing Library

Component Test:

import { render, fireEvent } from '@testing-library/react-native';
import { PaymentCard } from './PaymentCard';

describe('PaymentCard', () => {
  it('should display amount in correct format', () => {
    const { getByTestId } = render(<PaymentCard amount={1500.50} />);

    expect(getByTestId('amount-display')).toHaveTextContent('$1,500.50');
  });

  it('should call onPay when pay button pressed', () => {
    const onPay = jest.fn();
    const { getByTestId } = render(<PaymentCard onPay={onPay} />);

    fireEvent.press(getByTestId('pay-button'));

    expect(onPay).toHaveBeenCalledTimes(1);
  });
});

React Native - Detox E2E

E2E Test:

describe('Login Flow', () => {
  beforeAll(async () => {
    await device.launchApp();
  });

  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('should login successfully with valid credentials', async () => {
    await element(by.id('email-input')).typeText(' [email protected] ');
    await element(by.id('password-input')).typeText('securePassword123');
    await element(by.id('login-button')).tap();

    await expect(element(by.id('home-screen'))).toBeVisible();
    await expect(element(by.text('Welcome'))).toBeVisible();
  });

  it('should show error for invalid credentials', async () => {
    await element(by.id('email-input')).typeText(' [email protected] ');
    await element(by.id('password-input')).typeText('wrongpass');
    await element(by.id('login-button')).tap();

    await expect(element(by.text('Invalid credentials'))).toBeVisible();
  });
});

PHP - PHPUnit

Unit Test:

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use App\Services\OrderCalculator;

class OrderCalculatorTest extends TestCase
{
    private OrderCalculator $calculator;

    protected function setUp(): void
    {
        $this->calculator = new OrderCalculator();
    }

    public function test_calculates_subtotal_correctly(): void
    {
        $items = [
            ['price' => 100, 'quantity' => 2],
            ['price' => 50, 'quantity' => 1],
        ];

        $result = $this->calculator->calculateSubtotal($items);

        $this->assertEquals(250, $result);
    }

    public function test_applies_discount_percentage(): void
    {
        $result = $this->calculator->applyDiscount(100, 10);

        $this->assertEquals(90, $result);
    }

    public function test_throws_exception_for_negative_discount(): void
    {
        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Discount cannot be negative');

        $this->calculator->applyDiscount(100, -5);
    }
}

Laravel Feature Test:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

class AuthenticationTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_can_login_with_correct_credentials(): void
    {
        $user = User::factory()->create([
            'email' => ' [email protected] ',
            'password' => bcrypt('password123'),
        ]);

        $response = $this->postJson('/api/login', [
            'email' => ' [email protected] ',
            'password' => 'password123',
        ]);

        $response->assertStatus(200)
                 ->assertJsonStructure(['token', 'user']);
    }

    public function test_user_cannot_login_with_wrong_password(): void
    {
        $user = User::factory()->create([
            'email' => ' [email protected] ',
            'password' => bcrypt('password123'),
        ]);

        $response = $this->postJson('/api/login', [
            'email' => ' [email protected] ',
            'password' => 'wrongpassword',
        ]);

        $response->assertStatus(401)
                 ->assertJson(['message' => 'Invalid credentials']);
    }
}

Python - PyTest

Unit Test:

import pytest
from app.services.calculator import OrderCalculator


class TestOrderCalculator:
    @pytest.fixture
    def calculator(self):
        return OrderCalculator()

    def test_calculate_subtotal(self, calculator):
        items = [
            {"price": 100, "quantity": 2},
            {"price": 50, "quantity": 1},
        ]

        result = calculator.calculate_subtotal(items)

        assert result == 250

    def test_apply_discount_percentage(self, calculator):
        result = calculator.apply_discount(100, 10)

        assert result == 90

    def test_raises_error_for_negative_discount(self, calculator):
        with pytest.raises(ValueError, match="Discount cannot be negative"):
            calculator.apply_discount(100, -5)

    @pytest.mark.parametrize("amount,discount,expected", [
        (100, 0, 100),
        (100, 10, 90),
        (100, 50, 50),
        (100, 100, 0),
    ])
    def test_discount_edge_cases(self, calculator, amount, discount, expected):
        assert calculator.apply_discount(amount, discount) == expected

FastAPI Integration Test:

import pytest
from fastapi.testclient import TestClient
from app.main import app
from app.models import User


@pytest.fixture
def client():
    return TestClient(app)


@pytest.fixture
def test_user(db_session):
    user = User(email=" [email protected] ", password="hashed_password")
    db_session.add(user)
    db_session.commit()
    return user


class TestAuthenticationAPI:
    def test_login_success(self, client, test_user):
        response = client.post("/api/login", json={
            "email": " [email protected] ",
            "password": "password123"
        })

        assert response.status_code == 200
        assert "token" in response.json()
        assert "user" in response.json()

    def test_login_wrong_password(self, client, test_user):
        response = client.post("/api/login", json={
            "email": " [email protected] ",
            "password": "wrongpassword"
        })

        assert response.status_code == 401
        assert response.json()["detail"] == "Invalid credentials"

    def test_login_missing_fields(self, client):
        response = client.post("/api/login", json={})

        assert response.status_code == 422

Go - Go Testing

Unit Test:

package calculator

import (
    "testing"
)

func TestCalculateSubtotal(t *testing.T) {
    calc := NewOrderCalculator()
    items := []Item{
        {Price: 100, Quantity: 2},
        {Price: 50, Quantity: 1},
    }

    result := calc.CalculateSubtotal(items)

    if result != 250 {
        t.Errorf("Expected 250, got %d", result)
    }
}

func TestApplyDiscount(t *testing.T) {
    calc := NewOrderCalculator()

    result := calc.ApplyDiscount(100, 10)

    if result != 90 {
        t.Errorf("Expected 90, got %d", result)
    }
}

func TestApplyDiscountNegative(t *testing.T) {
    calc := NewOrderCalculator()

    defer func() {
        if r := recover(); r == nil {
            t.Errorf("Expected panic for negative discount")
        }
    }()

    calc.ApplyDiscount(100, -5)
}

// Table-driven test
func TestApplyDiscountEdgeCases(t *testing.T) {
    calc := NewOrderCalculator()

    tests := []struct {
        name     string
        amount   int
        discount int
        expected int
    }{
        {"no discount", 100, 0, 100},
        {"10% discount", 100, 10, 90},
        {"50% discount", 100, 50, 50},
        {"full discount", 100, 100, 0},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := calc.ApplyDiscount(tt.amount, tt.discount)
            if result != tt.expected {
                t.Errorf("Expected %d, got %d", tt.expected, result)
            }
        })
    }
}

Coverage Targets

TypeTargetRationale
Critical paths100%Auth, payment, security
Business logic90%Core domain logic
UI/Utilities80%User-facing components
Overall80%Project minimum (or custom)

Test File Naming Conventions

FrameworkTest FileLocation
Jest*.test.ts, *.spec.ts__tests__/ or alongside
PHPUnit*Test.phptests/Unit/, tests/Feature/
PyTesttest_*.py, *_test.pytests/
Go*_test.goSame package
Detox*.e2e.tse2e/
Cypress*.cy.tscypress/e2e/

Running Tests by Framework

# JavaScript/TypeScript (Jest)
npm test
npm test -- --coverage
npm test -- --watch

# PHP (PHPUnit)
./vendor/bin/phpunit
./vendor/bin/phpunit --coverage-html coverage
./vendor/bin/phpunit --filter TestClassName

# Python (PyTest)
pytest
pytest --cov=. --cov-report=html
pytest -k "test_function_name"

# Go
go test ./...
go test -v ./...
go test -coverprofile=coverage.out ./...

# React Native (Detox)
detox test --configuration ios.sim.debug
detox test --configuration android.emu.debug

Remember:

  • Tests are documentation - write clear, maintainable tests
  • Follow AAA pattern: Arrange, Act, Assert
  • One assertion concept per test (can have multiple expects)
  • Test behavior, not implementation
  • Mock external dependencies

平台分布

OpenCode

30.17%
按下载量换算25

Claude Code

21.48%
按下载量换算18

windsurf

18.85%
按下载量换算15

cline

13.48%
按下载量换算11

Codex

7.4%
按下载量换算6

Antigravity

3.67%
按下载量换算3

安全审计

暂无安全审计结果可展示。

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills