Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计未展示

test-writer测试编写者

Agent Skill

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

总安装

235

周安装

10

GitHub Stars

公开资料未说明

下载量

82
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 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"

简介

用于辅助测试设计、自动化测试和用例整理。

  • 适合编写单元测试、端到端测试或根据日志定位问题。
  • 使用时需确认测试框架、运行命令和夹具数据。
  • 避免为了通过测试而破坏真实逻辑。test-writer 属于研究检索类 Skill,可作为该场景下的辅助能力补充。
  • 涉及浏览器或外部服务时需区分环境。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

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

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

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