adrhumphreys / silverstripe-fixtures
Silverstripe 的 fixtures。
Requires
- php: ^7.4 || ^8.0
- silverstripe/admin: ^1.0 || ^2.0
- silverstripe/framework: ^4.0 || ^5.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.0
README
为所有混合物提供 fixtures 👋
要求
- SilverStripe ^4.0 || ^5.0
- PHP ^7.4 || ^8.0
开发要求
phpunit/phpunit
^9.5squizlabs/php_codesniffer
^3.0
安装
composer require adrhumphreys/silverstripe-fixtures dev-master
仅作为开发模块安装
当运行 dev/build
时,Silverstripe 框架会尝试将其所有类加载到它的 ClassManifest 中以缓存它们,并允许依赖注入等功能。在这个过程中,它将尝试加载你的 Fixture 类,然后尝试加载 AdrHumphreys\Fixtures\AbstractFixture
,该类不存在。这将抛出异常并停止 dev/build
过程。
你有几种选择来解决这个问题,从最好到最差排序
选项 1: 将你的 fixtures 放在你的项目的 tests
目录中:这些是为仅在测试/开发环境中运行的而设计的,代码更侧重于参考而非实现。因此,将这些文件移动到该目录是有意义的。为什么?它明确地被 ManifestFileFinder
忽略
选项 2: 在 fixtures 目录中添加 _manifest_exclude
:这将确保 ManifestFileFinder
将忽略目录中的文件。这是选项 2,因为它使得测试代码最终被生产代码依赖的可能性更大,而这种情况决不应该发生
选项 3: 在所有 fixtures 中添加 implements TestOnly
如果你将此作为开发依赖项安装,则 所有 fixtures 都需要实现 \SilverStripe\Dev\TestOnly
,该接口专门被排除在 Silverstripes 类清单加载器之外
如何使用
默认设置是将其作为一个任务运行,如下所示
vendor/bin/sake dev/tasks/load-fixtures directory=app/src/fixtures
你需要创建你的 fixtures 在指定的目录中。或者,你可以实现自己的任务,以 LoadFixtures
任务为例。你可以将 ->loadFromDirectory
改为多次调用 ->loadFixture($fixtureClassName)
一个基本的 fixture 看起来像下面这样
<?php namespace App\Fixtures; use AdrHumphreys\Fixtures\AbstractFixture; use SilverStripe\Dev\TestOnly; class PageFixture extends AbstractFixture implements TestOnly { public function load(): void { $page = \Page::create(); $page->Title = 'Example title'; $page->URLSegment = 'example-page'; $page->write(); $page->publishRecursive(); } public function getClassesToClear(): ?array { return [\Page::class]; } }
load
在创建 fixture 时被调用,然后 getClassesToClear
在清除 fixture 时被调用。你还可以实现 unload
函数,这是一个你可以选择做什么的函数,以及 getTablesToClear
,这是一个类似于 getClassesToClear
的函数,但仅针对表。
加载顺序是首先加载没有顺序要求的依赖项,然后是无依赖项的依赖项。最后加载有序 fixture,然后是带有依赖项的 fixture。
依赖项 fixture
如果 fixture 依赖于另一个 fixture,你可以实现 DependentFixtureInterface
并通过 getDependencies
函数返回一个表示 fixture 依赖的类的数组。
一个例子是
<?php namespace App\Fixtures; use AdrHumphreys\Fixtures\AbstractFixture; use AdrHumphreys\Fixtures\DependentFixtureInterface; use SilverStripe\Dev\TestOnly; class MyOtherPageFixture extends AbstractFixture implements DependentFixtureInterface, TestOnly { public function load(): void { // Example } public function getDependencies(): array { return [PageFixture::class]; } }
有序 fixture
你还可以通过实现接口 OrderedFixtureInterface
来指定 fixtures 加载的顺序,方法 getOrder
返回一个表示顺序的数字。
<?php namespace App\Fixtures; use AdrHumphreys\Fixtures\AbstractFixture; use AdrHumphreys\Fixtures\OrderedFixtureInterface; use SilverStripe\Dev\TestOnly; class PageFixture extends AbstractFixture implements OrderedFixtureInterface, TestOnly { public function load(): void { // Example } public function getOrder(): int { return 2; } }
引用其他 fixtures
在加载过程中,你可以通过将 fixture 添加到内部引用存储中来存储对 fixture 的引用,使用 $this->addReference(string $identifier, object $reference);
。一个例子是
<?php namespace App\Fixtures; use AdrHumphreys\Fixtures\AbstractFixture; use SilverStripe\Dev\TestOnly; class PageFixture extends AbstractFixture implements TestOnly { public const PAGE_REF = 'my-page-ref'; public function load(): void { $page = \Page::create(); $page->Title = 'Example title'; $page->URLSegment = 'example-page'; $page->write(); $page->publishRecursive(); $this->addReference(self::PAGE_REF, $page); } }
然后你可以通过调用 $this->getByReference(string $identifier)
来使用它。示例
<?php namespace App\Fixtures; use AdrHumphreys\Fixtures\AbstractFixture; use SilverStripe\Dev\TestOnly; class PageFixtureTwo extends AbstractFixture implements TestOnly { public function load(): void { $refPage = $this->getByReference(PageFixture::PAGE_REF); $page = \Page::create(); $page->Title = 'Example title'; $page->URLSegment = 'example-page'; $page->Body = 'PageID: ' . $refPage->ID; $page->write(); $page->publishRecursive(); } }
仅运行创建/清除
运行任务而不清除
vendor/bin/sake dev/tasks/load-fixtures directory=app/src/fixtures append=true
清除数据
vendor/bin/sake dev/tasks/load-fixtures directory=app/src/fixtures purgeOnly=true
实际上什么也不做
vendor/bin/sake dev/tasks/load-fixtures directory=app/src/fixtures purgeOnly=true append=true
生活品质功能
过滤
您可以使用过滤器参数选择性地运行测试用例
vendor/bin/sake dev/tasks/load-fixtures directory=app/src/fixtures filter=/PageFixtureTwo/
这将运行任何与过滤器模式匹配的测试用例以及任何依赖项。请注意,您可以过滤掉有序测试用例,并且它们不会像依赖项那样自动解决。
过滤器模式必须是preg_match的有效模式,包括分隔符。模式将与完全限定的类名(例如App\My\Fixture
)进行匹配。
创建资源
您可以轻松创建资源,如下所示
\AdrHumphreys\Fixtures\ReferenceManager::findOrMakeAsset('my-asset-id', 'file/path.jpg');
这将创建图像,并使用my-asset-id
作为引用存储。您还可以通过第三个参数传递一个包含参数的数组,例如['Title' => 'my asset title']
,这将被转换为$image->Title = 'my asset title'
,因此是区分大小写的。该函数还将返回存储的图像。第四个参数允许您指定另一个资源类型,例如SilverStripe\Assets\File。
然后您可以通过$this->getByReference('my-asset-id')
访问该资源
创建其他DataObject
的方式如下(这些仅通过->write
写入)
$ref = ReferenceManager::findOrMakeDataObject( 'my-cool-page', // reference \Page::class, // object to create [ 'Title' => 'My cool page', // params 'URLSegment' => 'my-cool-page' ] );
维护者
- Adrian adrhumphreys@gmail.com
开发和贡献
点击那个拉取请求按钮吧 🥰