承接 chqthomas/approval-tests 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

chqthomas/approval-tests

Composer 安装命令:

composer require chqthomas/approval-tests

包简介

Approval Tests Library for PHP

README 文档

README

A PHP library for approval testing. This approach allows you to verify complex results by comparing them with approved versions, making it ideal for testing outputs that are difficult to assert traditionally (e.g., HTML, JSON, XML, or binary files).

Warning

This library is still in development. It is not recommended for production use. Many features are still missing, and the API may change.

Table of Contents

Installation

Install the library via Composer:

composer require chqthomas/approval-tests

Basic Usage

Simple Test

Verify a simple string output:

use ChqThomas\ApprovalTests\Approvals;

public function testSimpleString(): void 
{
    Approvals::verify("Hello World");
}

The first time this runs, it generates a .received.txt file. Approve it by renaming it to .approved.txt or use auto-approval (see below).

Structured Data Test

Verify complex data structures like arrays or objects:

public function testArray(): void 
{
    $data = [
        'name' => 'John Doe',
        'age' => 30,
        'roles' => ['admin', 'user']
    ];
    Approvals::verify($data);
}

Specialized Verifications

The library supports specific formats with dedicated methods:

HTML

Verify HTML content with automatic formatting:

public function testHtml(): void 
{
    $html = '<div>Hello <span>World</span></div>';
    Approvals::verifyHtml($html);
}

JSON

Verify JSON with pretty-printing and scrubbing:

public function testJson(): void 
{
    $json = '{"name":"John","age":30}';
    Approvals::verifyJson($json); // Automatically formatted
}

XML

Verify XML with formatting:

public function testXml(): void 
{
    $xml = '<?xml version="1.0"?><root><user>John</user></root>';
    Approvals::verifyXml($xml);
}

CSV

Verify CSV content:

public function testCsv(): void 
{
    $csv = "name,age\nJohn,30\nJane,25";
    Approvals::verifyCsv($csv);
}

Binary Files

Verify binary content (e.g., images):

public function testBinaryFile(): void 
{
    Approvals::verifyBinaryFile('path/to/image.png', 'png');
}

Advanced Features

Tests with Data Providers

Use PHPUnit data providers for parameterized tests:

/**
 * @dataProvider provideTestData
 */
public function testWithDataProvider(array $data, string $expected): void 
{
    $result = processData($data);
    Approvals::verify($result);
}

public static function provideTestData(): array
{
    return [
        'case1' => [['input' => 1], 'output1'],
        'case2' => [['input' => 2], 'output2'],
    ];
}

Verify All Combinations

Test all combinations of inputs:

public function testAllCombinations(): void 
{
    $operations = ['+', '-', '*', '/'];
    $numbers = [1, 2, 3];
    
    Approvals::verifyAllCombinations(
        function($op, $a, $b) {
            switch($op) {
                case '+': return $a + $b;
                case '-': return $a - $b;
                case '*': return $a * $b;
                case '/': return $b != 0 ? $a / $b : 'Division by zero';
            }
        },
        [$operations, $numbers, $numbers]
    );
}

Configuration

Customize the library’s behavior via the Configuration class:

PHPUnit Bootstrap Configuration

Create a tests/bootstrap.php file to configure the library globally for all your tests:

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use ChqThomas\ApprovalTests\Configuration;
use ChqThomas\ApprovalTests\Reporter\DiffReporter;
use ChqThomas\ApprovalTests\Formatter\SymfonyObjectFormatter;

// Global configuration
Configuration::getInstance()
    ->setReporter(new DiffReporter())
    ->setObjectFormatter(new SymfonyObjectFormatter())
    ->setAutoApprove(false);

// Configure default scrubbers for specific formats
Configuration::getInstance()
    ->setDefaultScrubber('json', JsonScrubber::create()
        ->scrubMember('password', 'token')
        ->ignoreMember('sensitive_data'))
    ->setDefaultScrubber('xml', XmlScrubber::create()
        ->addScrubber(RegexScrubber::create([
            '/\d{4}-\d{2}-\d{2}/' => '[DATE]'
        ])));

Then reference it in your phpunit.xml:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php">
    <!-- ... -->
</phpunit>

Set a Custom Reporter

Change how differences are reported:

use ChqThomas\ApprovalTests\Configuration;
use ChqThomas\ApprovalTests\Reporter\DiffReporter;

Configuration::getInstance()->setReporter(new DiffReporter());

Use a Custom Object Formatter

Switch between default and Symfony formatters:

use ChqThomas\ApprovalTests\Formatter\SymfonyObjectFormatter;

Configuration::getInstance()->setObjectFormatter(new SymfonyObjectFormatter());

Note: Requires symfony/serializer to be installed for SymfonyObjectFormatter.

Custom Namer

Set a custom namer for file naming:

use ChqThomas\ApprovalTests\Namer\EnvironmentAwareNamer;

Configuration::getInstance()->setNamerClass(EnvironmentAwareNamer::class);

Auto-Approve Snapshots

Automatically approve new or changed snapshots:

Configuration::getInstance()->setAutoApprove(true);

Or use an environment variable:

APPROVE_SNAPSHOTS=true vendor/bin/phpunit

Scrubbers

Scrubbers normalize content before comparison, handling dynamic data like dates or IDs.

JSON Scrubbing

Scrub sensitive or variable data:

public function testJsonScrubbing(): void 
{
    $json = <<<JSON
{
    "user": "John",
    "password": "secret123",
    "timestamp": "2024-01-01T12:00:00",
    "id": "550e8400-e29b-41d4-a716-446655440000"
}
JSON;

    // Default scrubbers automatically handle:
    // - GUIDs (replaced with Guid_1, Guid_2, etc.)
    // - Dates (replaced with DateTimeOffset_1, etc.)
    Approvals::verifyJson($json);
}

Ignore JSON Members

Remove specific members:

public function testJsonIgnoreMember(): void 
{
    $json = <<<JSON
{
    "user": "John",
    "sensitive": {
        "password": "secret123",
        "token": "abc123"
    }
}
JSON;

    Approvals::verifyJson($json, JsonScrubber::create()
        ->ignoreMember('sensitive')); // Member will be removed
}

Scrub JSON Members

Replace members with a placeholder:

public function testJsonScrubMember(): void 
{
    $json = <<<JSON
{
    "user": "John",
    "password": "secret123",
    "api_key": "xyz789"
}
JSON;

    Approvals::verifyJson($json, JsonScrubber::create()
        ->scrubMember('password', 'api_key')); // Members will be replaced with "[scrubbed]"
}

XML Scrubbing

Custom scrubbing for XML:

public function testXmlScrubbing(): void 
{
    $xml = <<<XML
<?xml version="1.0"?>
<user>
    <name>John</name>
    <created>2024-01-01T12:00:00</created>
    <id>550e8400-e29b-41d4-a716-446655440000</id>
</user>
XML;

    // Custom scrubber for XML
    Approvals::verifyXml($xml, XmlScrubber::create()
        ->addScrubber(fn($content) => preg_replace('/John/', '[NAME]', $content)));
}

Regex Scrubbing

Use regular expressions for generic scrubbing:

public function testRegexScrubbing(): void 
{
    $json = <<<JSON
{
  "nodes": [
    {"id": "ABC123", "name": "Node1"},
    {"id": "DEF456", "name": "Node2"},
    {"id": "GHI789", "name": "Node3"}
  ]
}
JSON;

    Approvals::verifyJson($json, JsonScrubber::create()
        ->addScrubber(RegexScrubber::create(['/"id": "([A-Z]{3}\d{3})"/' => '"id": "MATCHED"'])));
}

Custom Scrubber

Create a custom scrubber for any content:

use ChqThomas\ApprovalTests\Scrubber\AbstractScrubber;

class MyScrubber extends AbstractScrubber
{
    public function scrub(string $content): string
    {
        // Apply base scrubbers first (GUIDs, dates)
        $content = $this->scrubGuids($content);
        $content = $this->scrubDates($content);
        
        // Add your custom rules
        $content = preg_replace('/secret-\d+/', '[SECRET]', $content);
        
        // Apply additional scrubbers
        return $this->applyAdditionalScrubbers($content);
    }
}

// Usage
public function testWithCustomScrubber(): void 
{
    $content = "ID: secret-123\nDate: 2024-01-01";
    
    Approvals::verifyWithExtension(
        $content,
        "txt",
        MyScrubber::create()
            ->addScrubber(fn($text) => str_replace('ID:', 'Reference:', $text))
    );
}

Maintenance

Cleanup Received Files

Remove redundant .received files:

use ChqThomas\ApprovalTests\ApprovalMaintenance;

ApprovalMaintenance::cleanUpReceivedFiles(__DIR__ . '/tests/approvals');

Detect Orphaned Files

Find .approved files without associated tests:

$orphanedFiles = ApprovalMaintenance::findOrphanedApprovedFiles(__DIR__ . '/tests');

Reporters

Customize how differences are reported:

CLI Reporter

Default reporter for terminal output:

use ChqThomas\ApprovalTests\Reporter\CliReporter;

Configuration::getInstance()->setReporter(new CliReporter());

Diff Reporter

Show differences using a diff format:

use ChqThomas\ApprovalTests\Reporter\DiffReporter;

Configuration::getInstance()->setReporter(new DiffReporter());

Composite Reporter

Combine multiple reporters:

use ChqThomas\ApprovalTests\Reporter\CompositeReporter;

$reporter = new CompositeReporter([
    new CliReporter(),
    new DiffReporter()
]);
Configuration::getInstance()->setReporter($reporter);

Symfony Integration

Use with Symfony’s DomCrawler for web testing:

use ChqThomas\ApprovalTests\Symfony\ApprovalCrawlerAssertionsTrait;

class MyWebTest extends WebTestCase
{
use ApprovalCrawlerAssertionsTrait;

    public function testPageContent(): void
    {
        $client = static::createClient();
        $client->request('GET', '/');
        self::verifySelectorHtml('#main-content');
    }
}

Best Practices

  1. Store .approved files in version control.
  2. Use scrubbers for variable data (e.g., dates, IDs).
  3. Regularly clean up .received files.
  4. Check for orphaned .approved files.
  5. Use descriptive test names for clear file naming.

Contributing

Contributions are welcome! To contribute:

  1. Fork the project.
  2. Create a feature branch.
  3. Submit a pull request.

License

MIT License

chqthomas/approval-tests 适用场景与选型建议

chqthomas/approval-tests 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.03k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 02 月 16 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 chqthomas/approval-tests 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 chqthomas/approval-tests 我们能提供哪些服务?
定制开发 / 二次开发

基于 chqthomas/approval-tests 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2.03k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-02-16