adrhumphreys/silverstripe-fixtures

Silverstripe 的 fixtures。

安装数: 12,566

依赖项: 0

建议者: 1

安全: 0

星标: 2

关注者: 4

分支: 4

公开问题: 3

类型:silverstripe-vendormodule

1.2.1 2024-07-24 22:30 UTC

This package is auto-updated.

Last update: 2024-09-24 22:55:16 UTC


README

为所有混合物提供 fixtures 👋

要求

  • SilverStripe ^4.0 || ^5.0
  • PHP ^7.4 || ^8.0

开发要求

  • phpunit/phpunit ^9.5
  • squizlabs/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'
    ]
);

维护者

开发和贡献

点击那个拉取请求按钮吧 🥰