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

可以通过一下地址学习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 安装:

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

后,我真切感受到了它的巨大优势:

告别样板代码:彻底消除了为通用数据类型重复编写数据提供者的烦恼,让我的测试文件更专注于业务逻辑的验证。提升可读性:测试方法不再被冗长的数据提供者方法所干扰,一眼就能看出测试的意图。增强一致性:所有团队成员都可以使用同一套标准化的数据,确保测试覆盖的全面性和一致性。简化维护:如果需要更新某种数据类型(例如,增加一种新的空白字符),只需

ergebnis/data-provider

库自身更新,或者我可以在我自己的项目里扩展它,而无需修改大量测试文件。提高开发效率:编写测试的速度显著加快,因为大部分基础数据我已经无需自己去构建。强大的组合能力:你可以像例子中那样,通过

@dataProvider

#[Framework\DataProviderExternal]

组合多个提供者,轻松构建复杂的测试场景。

总之,

ergebnis/data-provider

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

以上就是如何解决PHPUnit测试中数据提供者重复冗余的问题,使用ergebnis/data-provider让你的测试代码更优雅高效的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/165630.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
或影响3A游戏销量?报告称XGP未能显著改变玩家行为!
上一篇 2026年8月26日 21:55:33
定时器(Timer)的底层实现
下一篇 2026年8月26日 22:00:08

相关推荐

发表回复

登录后才能评论
关注微信