0

0

如何解决PHPUnit测试中数据提供者重复冗余的问题,使用ergebnis/data-provider让你的测试代码更优雅高效

WBOY

WBOY

发布时间:2025-08-27 13:10:43

|

456人浏览过

|

来源于php中文网

原创

可以通过一下地址学习composer学习地址

作为一名php开发者,我们深知单元测试的重要性。而phpunit作为事实上的标准测试框架,其数据提供者(data provider)功能更是让我们能够用一套测试逻辑覆盖多种输入场景,极大地提高了测试效率。然而,在实际项目中,我却常常被一个问题困扰:为各种常见数据类型(比如空字符串、空白字符串、负数、零、布尔值等)编写数据提供者时,总是不得不一遍又一遍地重复编写相似的代码。

想象一下,你正在测试一个用户注册功能,需要验证用户名不能是空字符串或只包含空格。你可能会写出这样的代码:

expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Value can not be an empty or blank string.');

        UserName::fromString($value);
    }

    public static function provideInvalidUserNames(): array
    {
        return [
            'empty string' => [''],
            'blank string with space' => [' '],
            'blank string with tab' => ["\t"],
            'blank string with newline' => ["\n"],
        ];
    }
}

// 假设有一个这样的 UserName 类
final class UserName
{
    private string $value;

    private function __construct(string $value)
    {
        $this->value = $value;
    }

    public static function fromString(string $value): self
    {
        if (trim($value) === '') {
            throw new \InvalidArgumentException('Value can not be an empty or blank string.');
        }

        return new self($value);
    }
}

这看起来没问题,对吧?但如果你的项目中还有十几个、几十个地方需要验证“非空非空白字符串”的逻辑呢?你就会发现自己不得不复制粘贴,或者为每个模块都创建一套几乎相同的数据提供者。这不仅导致了大量的样板代码,让测试文件变得臃肿不堪,而且一旦需要调整某个“空白字符串”的定义(比如增加一个Unicode空白字符),你就得在所有地方手动修改,维护成本极高,也容易出错。这种重复劳动,简直是开发者的噩梦!

正当我为此头疼不已时,我偶然发现了

ergebnis/data-provider
这个 Composer 包。它就像一道曙光,彻底解决了我在 PHPUnit 测试中数据提供者重复冗余的问题,让我的测试代码变得前所未有的优雅和高效。

ergebnis/data-provider
提供了一系列预定义的、通用的数据提供者,涵盖了 PHP 中最常用的数据类型,例如布尔值、浮点数、整数、null、对象、资源、字符串以及 UUID。这意味着,你不再需要为这些常见类型的数据编写自己的数据提供者,只需简单引用即可。

立即学习PHP免费学习笔记(深入)”;

使用

ergebnis/data-provider
非常简单,首先通过 Composer 安装:

Munch
Munch

AI营销分析工具,长视频中提取出最具吸引力的短片

下载
composer require ergebnis/data-provider

安装完成后,你就可以在你的 PHPUnit 测试中直接引用它提供的各种数据提供者了。让我们回到之前那个“用户名不能是空字符串或空白字符串”的例子,使用

ergebnis/data-provider
后,代码会变得异常简洁:

value = $value;
    }

    public static function fromString(string $value): self
    {
        if (trim($value) === '') {
            throw new InvalidArgumentException('Value can not be an empty or blank string.');
        }

        return new self($value);
    }
}

final class ExampleTest extends Framework\TestCase
{
    /**
     * @dataProvider \Ergebnis\DataProvider\StringProvider::blank()
     * @dataProvider \Ergebnis\DataProvider\StringProvider::empty()
     */
    public function testFromNameRejectsInvalidValueWithAnnotation(string $value): void
    {
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Value can not be an empty or blank string.');

        UserName::fromString($value);
    }

    // 如果你使用 PHP 8+ 的 Attribute,也可以这样写:
    #[Framework\DataProviderExternal(DataProvider\StringProvider::class, 'blank')]
    #[Framework\DataProviderExternal(DataProvider\StringProvider::class, 'empty')]
    public function testFromNameRejectsInvalidValueWithAttribute(string $value): void
    {
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Value can not be an empty or blank string.');

        UserName::fromString($value);
    }
}

看到了吗?我们完全移除了

provideInvalidUserNames()
这个方法!取而代之的是直接引用
Ergebnis\DataProvider\StringProvider
中的
blank()
empty()
方法。这两个方法分别提供了只包含空白字符的字符串和空字符串作为测试数据。代码瞬间变得清晰、精简,且易于理解。

ergebnis/data-provider
提供了非常丰富的通用数据提供者,涵盖了你可能遇到的大部分场景:

  • Ergebnis\DataProvider\BoolProvider
    : 提供
    true
    false
    或任意布尔值(
    arbitrary()
    )。
  • Ergebnis\DataProvider\FloatProvider
    : 提供任意浮点数(
    arbitrary()
    )、大于1(
    greaterThanOne()
    )、大于0(
    greaterThanZero()
    )、小于1(
    lessThanOne()
    )、小于0(
    lessThanZero()
    )、1.0(
    one()
    )、0.0(
    zero()
    )等。
  • Ergebnis\DataProvider\IntProvider
    : 提供任意整数(
    arbitrary()
    )、大于1(
    greaterThanOne()
    )、大于0(
    greaterThanZero()
    )、小于1(
    lessThanOne()
    )、小于0(
    lessThanZero()
    )、1(
    one()
    )、0(
    zero()
    )等。
  • Ergebnis\DataProvider\NullProvider
    : 专门提供
    null
    null()
    )。
  • Ergebnis\DataProvider\ObjectProvider
    : 提供
    stdClass
    实例(
    object()
    )。
  • Ergebnis\DataProvider\ResourceProvider
    : 提供一个资源类型(
    resource()
    )。
  • Ergebnis\DataProvider\StringProvider
    : 除了
    blank()
    empty()
    ,还有
    arbitrary()
    (任意字符串),
    trimmed()
    (无前后空格的非空字符串),
    untrimmed()
    (带前后空格的非空字符串),
    withWhitespace()
    (包含空格的字符串) 等。
  • Ergebnis\DataProvider\UuidProvider
    : 提供小写(
    caseLower()
    )或大写(
    caseUpper()
    )的 UUID 字符串,以及任意大小写(
    arbitrary()
    )。

这些提供者都设计得非常细致,几乎覆盖了你在单元测试中所有常见的输入场景。

引入

ergebnis/data-provider
后,我真切感受到了它的巨大优势:

  1. 告别样板代码:彻底消除了为通用数据类型重复编写数据提供者的烦恼,让我的测试文件更专注于业务逻辑的验证。
  2. 提升可读性:测试方法不再被冗长的数据提供者方法所干扰,一眼就能看出测试的意图。
  3. 增强一致性:所有团队成员都可以使用同一套标准化的数据,确保测试覆盖的全面性和一致性。
  4. 简化维护:如果需要更新某种数据类型(例如,增加一种新的空白字符),只需
    ergebnis/data-provider
    库自身更新,或者我可以在我自己的项目里扩展它,而无需修改大量测试文件。
  5. 提高开发效率:编写测试的速度显著加快,因为大部分基础数据我已经无需自己去构建。
  6. 强大的组合能力:你可以像例子中那样,通过
    @dataProvider
    #[Framework\DataProviderExternal]
    组合多个提供者,轻松构建复杂的测试场景。

总之,

ergebnis/data-provider
是一个非常实用且优雅的 PHPUnit 辅助库。如果你也曾被数据提供者的重复编写所困扰,那么我强烈推荐你尝试一下它。它不仅能让你的测试代码更加精简、易读,还能大幅提升你的开发效率和测试质量。让我们的测试代码,从今天开始,变得更加智能和高效吧!

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2488

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1584

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1480

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1414

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1305

2023.11.13

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.4万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 6.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号