Provides Perl testing patterns with Test2::V0, Test::More, and TDD practices.

Install

mkdir -p .claude/skills/perl-testing && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14921" && unzip -o skill.zip -d .claude/skills/perl-testing && rm skill.zip

Installs to .claude/skills/perl-testing

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

使用Test2::V0、Test::More、prove runner、模拟、Devel::Cover覆盖率和TDD方法的Perl测试模式。
70 charsno explicit “when” trigger
Intermediate

Key capabilities

  • Implement Test-Driven Development (TDD) workflow
  • Write unit tests using Test::More
  • Utilize Test2::V0 for modern Perl testing
  • Organize test files and run them with `prove`
  • Mock external dependencies using Test::MockModule
  • Analyze test coverage with Devel::Cover

How it works

The skill guides through a TDD workflow using Perl testing modules like Test::More and Test2::V0, emphasizing writing failing tests first, then minimal implementation, and finally refactoring. It also covers test organization, execution with `prove`, mocking, and coverage analysis.

Inputs & outputs

You give it
Perl code, test files
You get back
Test results, coverage reports, refactored code

When to use perl-testing

  • Write unit tests for Perl
  • Migrate to Test2::V0
  • Improve code coverage
  • Perform TDD in Perl

About this skill

Perl 测试模式

使用 Test2::V0、Test::More、prove 和 TDD 方法论为 Perl 应用程序提供全面的测试策略。

何时激活

  • 编写新的 Perl 代码(遵循 TDD:红、绿、重构)
  • 为 Perl 模块或应用程序设计测试套件
  • 审查 Perl 测试覆盖率
  • 设置 Perl 测试基础设施
  • 将测试从 Test::More 迁移到 Test2::V0
  • 调试失败的 Perl 测试

TDD 工作流程

始终遵循 RED-GREEN-REFACTOR 循环。

# Step 1: RED — Write a failing test
# t/unit/calculator.t
use v5.36;
use Test2::V0;

use lib 'lib';
use Calculator;

subtest 'addition' => sub {
    my $calc = Calculator->new;
    is($calc->add(2, 3), 5, 'adds two numbers');
    is($calc->add(-1, 1), 0, 'handles negatives');
};

done_testing;

# Step 2: GREEN — Write minimal implementation
# lib/Calculator.pm
package Calculator;
use v5.36;
use Moo;

sub add($self, $a, $b) {
    return $a + $b;
}

1;

# Step 3: REFACTOR — Improve while tests stay green
# Run: prove -lv t/unit/calculator.t

Test::More 基础

标准的 Perl 测试模块 —— 广泛使用,随核心发行。

基本断言

use v5.36;
use Test::More;

# Plan upfront or use done_testing
# plan tests => 5;  # Fixed plan (optional)

# Equality
is($result, 42, 'returns correct value');
isnt($result, 0, 'not zero');

# Boolean
ok($user->is_active, 'user is active');
ok(!$user->is_banned, 'user is not banned');

# Deep comparison
is_deeply(
    $got,
    { name => 'Alice', roles => ['admin'] },
    'returns expected structure'
);

# Pattern matching
like($error, qr/not found/i, 'error mentions not found');
unlike($output, qr/password/, 'output hides password');

# Type check
isa_ok($obj, 'MyApp::User');
can_ok($obj, 'save', 'delete');

done_testing;

SKIP 和 TODO

use v5.36;
use Test::More;

# Skip tests conditionally
SKIP: {
    skip 'No database configured', 2 unless $ENV{TEST_DB};

    my $db = connect_db();
    ok($db->ping, 'database is reachable');
    is($db->version, '15', 'correct PostgreSQL version');
}

# Mark expected failures
TODO: {
    local $TODO = 'Caching not yet implemented';
    is($cache->get('key'), 'value', 'cache returns value');
}

done_testing;

Test2::V0 现代框架

Test2::V0 是 Test::More 的现代替代品 —— 更丰富的断言、更好的诊断和可扩展性。

为什么选择 Test2?

  • 使用哈希/数组构建器进行卓越的深层比较
  • 失败时提供更好的诊断输出
  • 具有更清晰作用域的子测试
  • 可通过 Test2::Tools::* 插件扩展
  • 与 Test::More 测试向后兼容

使用构建器进行深层比较

use v5.36;
use Test2::V0;

# Hash builder — check partial structure
is(
    $user->to_hash,
    hash {
        field name  => 'Alice';
        field email => match(qr/\@example\.com$/);
        field age   => validator(sub { $_ >= 18 });
        # Ignore other fields
        etc();
    },
    'user has expected fields'
);

# Array builder
is(
    $result,
    array {
        item 'first';
        item match(qr/^second/);
        item DNE();  # Does Not Exist — verify no extra items
    },
    'result matches expected list'
);

# Bag — order-independent comparison
is(
    $tags,
    bag {
        item 'perl';
        item 'testing';
        item 'tdd';
    },
    'has all required tags regardless of order'
);

子测试

use v5.36;
use Test2::V0;

subtest 'User creation' => sub {
    my $user = User->new(name => 'Alice', email => '[email protected]');
    ok($user, 'user object created');
    is($user->name, 'Alice', 'name is set');
    is($user->email, '[email protected]', 'email is set');
};

subtest 'User validation' => sub {
    my $warnings = warns {
        User->new(name => '', email => 'bad');
    };
    ok($warnings, 'warns on invalid data');
};

done_testing;

使用 Test2 进行异常测试

use v5.36;
use Test2::V0;

# Test that code dies
like(
    dies { divide(10, 0) },
    qr/Division by zero/,
    'dies on division by zero'
);

# Test that code lives
ok(lives { divide(10, 2) }, 'division succeeds') or note($@);

# Combined pattern
subtest 'error handling' => sub {
    ok(lives { parse_config('valid.json') }, 'valid config parses');
    like(
        dies { parse_config('missing.json') },
        qr/Cannot open/,
        'missing file dies with message'
    );
};

done_testing;

测试组织与 prove

目录结构

t/
├── 00-load.t              # 验证模块编译
├── 01-basic.t             # 核心功能
├── unit/
│   ├── config.t           # 按模块划分的单元测试
│   ├── user.t
│   └── util.t
├── integration/
│   ├── database.t
│   └── api.t
├── lib/
│   └── TestHelper.pm      # 共享测试工具
└── fixtures/
    ├── config.json        # 测试数据文件
    └── users.csv

prove 命令

# Run all tests
prove -l t/

# Verbose output
prove -lv t/

# Run specific test
prove -lv t/unit/user.t

# Recursive search
prove -lr t/

# Parallel execution (8 jobs)
prove -lr -j8 t/

# Run only failing tests from last run
prove -l --state=failed t/

# Colored output with timer
prove -l --color --timer t/

# TAP output for CI
prove -l --formatter TAP::Formatter::JUnit t/ > results.xml

.proverc 配置

-l
--color
--timer
-r
-j4
--state=save

夹具与设置/拆卸

子测试隔离

use v5.36;
use Test2::V0;
use File::Temp qw(tempdir);
use Path::Tiny;

subtest 'file processing' => sub {
    # Setup
    my $dir = tempdir(CLEANUP => 1);
    my $file = path($dir, 'input.txt');
    $file->spew_utf8("line1\nline2\nline3\n");

    # Test
    my $result = process_file("$file");
    is($result->{line_count}, 3, 'counts lines');

    # Teardown happens automatically (CLEANUP => 1)
};

共享测试助手

将可重用的助手放在 t/lib/TestHelper.pm 中,并通过 use lib 't/lib' 加载。通过 Exporter 导出工厂函数,例如 create_test_db()create_temp_dir()fixture_path()

模拟

Test::MockModule

use v5.36;
use Test2::V0;
use Test::MockModule;

subtest 'mock external API' => sub {
    my $mock = Test::MockModule->new('MyApp::API');

    # Good: Mock returns controlled data
    $mock->mock(fetch_user => sub ($self, $id) {
        return { id => $id, name => 'Mock User', email => '[email protected]' };
    });

    my $api = MyApp::API->new;
    my $user = $api->fetch_user(42);
    is($user->{name}, 'Mock User', 'returns mocked user');

    # Verify call count
    my $call_count = 0;
    $mock->mock(fetch_user => sub { $call_count++; return {} });
    $api->fetch_user(1);
    $api->fetch_user(2);
    is($call_count, 2, 'fetch_user called twice');

    # Mock is automatically restored when $mock goes out of scope
};

# Bad: Monkey-patching without restoration
# *MyApp::API::fetch_user = sub { ... };  # NEVER — leaks across tests

对于轻量级的模拟对象,使用 Test::MockObject 创建可注入的测试替身,使用 ->mock() 并验证调用 ->called_ok()

使用 Devel::Cover 进行覆盖率分析

运行覆盖率分析

# Basic coverage report
cover -test

# Or step by step
perl -MDevel::Cover -Ilib t/unit/user.t
cover

# HTML report
cover -report html
open cover_db/coverage.html

# Specific thresholds
cover -test -report text | grep 'Total'

# CI-friendly: fail under threshold
cover -test && cover -report text -select '^lib/' \
  | perl -ne 'if (/Total.*?(\d+\.\d+)/) { exit 1 if $1 < 80 }'

集成测试

对数据库测试使用内存中的 SQLite,对 API 测试模拟 HTTP::Tiny。

use v5.36;
use Test2::V0;
use DBI;

subtest 'database integration' => sub {
    my $dbh = DBI->connect('dbi:SQLite:dbname=:memory:', '', '', {
        RaiseError => 1,
    });
    $dbh->do('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');

    $dbh->prepare('INSERT INTO users (name) VALUES (?)')->execute('Alice');
    my $row = $dbh->selectrow_hashref('SELECT * FROM users WHERE name = ?', undef, 'Alice');
    is($row->{name}, 'Alice', 'inserted and retrieved user');
};

done_testing;

最佳实践

应做事项

  • 遵循 TDD:在实现之前编写测试(红-绿-重构)
  • 使用 Test2::V0:现代断言,更好的诊断
  • 使用子测试:分组相关断言,隔离状态
  • 模拟外部依赖:网络、数据库、文件系统
  • 使用 prove -l:始终将 lib/ 包含在 @INC
  • 清晰命名测试'user login with invalid password fails'
  • 测试边界情况:空字符串、undef、零、边界值
  • 目标 80%+ 覆盖率:专注于业务逻辑路径
  • 保持测试快速:模拟 I/O,使用内存数据库

禁止事项

  • 不要测试实现:测试行为和输出,而非内部细节
  • 不要在子测试之间共享状态:每个子测试都应是独立的
  • 不要跳过 done_testing:确保所有计划的测试都已运行
  • 不要过度模拟:仅模拟边界,而非被测试的代码
  • 不要在新项目中使用 Test::More:首选 Test2::V0
  • 不要忽略测试失败:所有测试必须在合并前通过
  • 不要测试 CPAN 模块:相信库能正常工作
  • 不要编写脆弱的测试:避免过度具体的字符串匹配

快速参考

任务命令 / 模式
运行所有测试prove -lr t/
详细运行单个测试prove -lv t/unit/user.t
并行测试运行prove -lr -j8 t/
覆盖率报告cover -test && cover -report html
测试相等性is($got, $expected, 'label')
深层比较is($got, hash { field k => 'v'; etc() }, 'label')
测试异常like(dies { ... }, qr/msg/, 'label')
测试无异常ok(lives { ... }, 'label')
模拟一个方法Test::MockModule->new('Pkg')->mock(m => sub { ... })
跳过测试SKIP: { skip 'reason', $count unless $cond; ... }
TODO 测试TODO: { local $TODO = 'reason'; ... }

常见陷阱

忘记 done_testing

# Bad: Test file runs but doesn't verify all tests executed
use Test2::V0;
is(1, 1, 'works');
# Missing done_testing — silent bugs if test code is skipped

# Good: Always end with done_testing
use Test2::V0;
is(1, 1, 'works');
done_testing;

缺少 -l 标志

# Bad: Modules in lib/ not found
prove t/unit/user.t
# Can't locate MyApp/User.pm in @INC

# Good: Include lib/ in @INC
prove -l t/unit/user.t

过度模拟

模拟依赖项,而非被测试的代码。如果你的测试只验证模拟返回了你告诉它的内容,那么它什么也没测试。

测试污染

在子测试内部使用 my 变量 —— 永远不要用 our —— 以防止状态在测试之间泄漏。

记住:测试是你的安全网。保持它们快速、专注和独立。新项目使用 Test2::V0,运行使用 prove,问责使用 Devel::Cover。

When not to use it

  • When testing non-Perl applications

Limitations

  • Specific to Perl testing
  • Test::MockModule is used for mocking

How it compares

This skill provides a structured TDD methodology for Perl, integrating modern testing frameworks and tools like Test2::V0 and Devel::Cover, which offers a more systematic and reliable approach to testing than basic script execution.

Compared to similar skills

perl-testing side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
perl-testing (this skill)03moReviewIntermediate
webapp-testing3533moReviewIntermediate
ui-ux-expert-skill919moReviewAdvanced
skill-creator1283moReviewAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

webapp-testing

anthropics

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

353585

ui-ux-expert-skill

fercracix33

Technical workflow for implementing accessible React user interfaces with shadcn/ui, Tailwind CSS, and TanStack Query. Includes 6-phase process with mandatory Style Guide compliance, Context7 best practices consultation, Chrome DevTools validation, and WCAG 2.1 AA accessibility standards. Use after Test Agent, Implementer, and Supabase agents complete their work.

91244

skill-creator

anthropics

Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.

128200

python-testing-patterns

wshobson

Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.

77204

dependency-upgrade

wshobson

Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.

26240

playwright-mcp

sfc-gh-dflippo

Browser testing, web scraping, and UI validation using Playwright MCP. Use this skill when you need to test Streamlit apps, validate web interfaces, test responsive design, check accessibility, or automate browser interactions through MCP tools.

33197

Search skills

Search the agent skills registry