chrispenny/silverstripe-data-object-to-fixture

为DataObjects生成YAML测试用例

安装次数: 3,980

依赖者: 0

建议者: 0

安全: 0

星标: 7

关注者: 1

分支: 2

开放问题: 2

类型:silverstripe-vendormodule

2.0.0 2023-06-29 22:35 UTC

This package is auto-updated.

Last update: 2024-08-30 01:23:22 UTC


README

从DataObjects生成YAML测试用例

安装

composer require chrispenny/silverstripe-data-object-to-fixture

目的(初期阶段)

此模块(在初期阶段)的目的不是保证每次生成的测试用例都完美,而是提供一个关于测试用例应该是什么样子的坚实指导。

例如:编写单元测试用例可能很困难,特别是当你需要可视化许多不同的DataObjects的结构和关系(如果你使用Fluent等,还需要额外一层)。

我还希望这个模块能与Populate模块很好地配合工作。请注意,但你需要运行版本2.1或更高,因为在此之前的版本不支持循环关系。

目的(未来开发)

我对这个模块的梦想是,我希望达到一个阶段,我们可以有信心地说生成的测试用例每次都是完美的。

从那里,我可以看到这个模块(例如)将被用于测试人员能够通过CMS在他们的测试环境中导出页面,这样那些页面就可以在任何时候通过(可能是)Populate恢复。具体如何操作,以及是否使用Populate,还有待确定。

警告

这仍然处于初期开发阶段。请注意

  • 类可能会改变
  • 返回类型可能会改变
  • 我生成测试用例的方法的整个范式可能会改变

不会改变的内容

  • 公共API将不会改变。仍然有一个具有3个主要方法的服务。

我目前不建议您将此模块用于任何关键功能的应用程序,但我强烈建议您将其用作开发工具(例如,帮助您编写自己的测试用例,无论是用于测试还是与Populate一起使用)。

通用用法

开发任务

开发任务可以在/dev/tasks/generate-fixture-from-dataobject中找到。

此任务允许您为项目中的任何DataObject生成测试用例(输出到屏幕上供您复制粘贴)。

代码使用

// Instantiate the Service.
$service = new FixtureService();

// Fetch the DataObject that you wish to generate a fixture for.
/** @var Page $page */
$page = Page::get()->byID(1);

// Add the DataObject to the Service.
$service->addDataObject($dataObject);

// Generating the fixture can also generate new warnings
$output = $service->outputFixture();

// Check for warnings? This is somewhat important, because if you have looping relationships (which we have no way of
// creating fixtures for at the moment) this is how you'll know about it.
if (count($service->getWarnings()) > 0) {
    Debug::dump($service->getWarnings());
}

// Do something with the fixture output.
highlight_string($output);

// Or maybe save the output to a file?
$fixture = Director::baseFolder() . '/app/resources/fixture.yml';
file_put_contents($fixture, $service->outputFixture());

从导出中排除类

可能有一些类(如Members?)您不想包含在测试用例中。清单将检查类是否存在(以及真实性)配置变量exclude_from_fixture_relationships

您可以在yml文件中设置此变量

SilverStripe\Security\Member:
  exclude_from_fixture_relationships: 1

SilverStripe\Security\Group:
  exclude_from_fixture_relationships: 1

SilverStripe\Security\MemberPassword:
  exclude_from_fixture_relationships: 1

SilverStripe\Security\RememberLoginHash:
  exclude_from_fixture_relationships: 1

上述示例已在_config/model.yml中设置。如果您想覆盖它们,也可以通过添加自己的yml配置“After”dataobjecttofixturemodel来实现。例如:

Name: my_dataobjecttofixturemodel
After: dataobjecttofixturemodel
---
SilverStripe\Security\Member:
  exclude_from_fixture_relationships: 0

从导出中排除关系

与排除类类似,可能存在一些特定类之间的特定关系需要排除。也许您已经识别出循环关系,并希望排除其中之一以使事物更可预测,或者这可能只是您在固定装置中不需要的关系。

您可以通过将 excluded_fixture_relationships 添加到所需类中,来排除特定关系。

excluded_fixture_relationships 接受一个包含 关系名称 的数组。

例如

class MyModel extends DataObject
{
    private static $has_one = [
        'FeatureImage' => Image::class,
    ];
}
App\Models\MyModel:
  excluded_fixture_relationships:
    - FeatureImage

常见问题

包含在导出中的父页面

当您导出页面时,如果该页面有 父级,则该 父级 被视为有效关系,因此它将随您选择的页面一起导出。

我仍在考虑如何处理这个问题,但到目前为止,我可能会建议您将 父级 添加到 SiteTree 的排除关系列表中

SilverStripe\CMS\Model\SiteTree:
    excluded_fixture_relationships:
        - Parent

节点 [YourClass][x] 个剩余依赖项,因此无法排序

这通常发生在您有循环关系时。例如:页面 has_one 链接,而 链接 has_one 回到 页面。排序器无法确定哪个类应该优先于另一个。

这并不意味着事物会出错,但值得审查。您可能会发现,您可以通过排除其中一个关系来使事物更加一致。

一个好的例子是 Elemental。Elemental 提供了一个名为 TopPage 的扩展,它提供从每个 BaseElement 到它所属的 页面 的直接关系(就像一个“索引”,这样您就可以从 BaseElement 中以更少的数据库查询回溯 页面)。这对于开发人员来说很方便,但对于 YAML 固定装置来说则不那么方便。我们实际上更希望排除这种关系,并遵循从 页面ElementalAreaBaseElement 的正确关系流程。

我可以通过以下配置来排除这种关系

DNADesign\Elemental\Models\BaseElement:
  excluded_fixture_relationships:
    - TopPage

生成测试用例时请求超时

以上是两种可以用来尝试减少这种情况的选项。

我建议您首先排除不需要导出的类,然后转向排除可能导致深层嵌套关系的特定关系。

DataObject::get() 不能直接查询非子类DataObject

如果您有多态关系(关系定义为简单的 DataObject::class),您可能会看到此错误

private static $has_one = [
    'Parent' => DataObject::class,
];

此模块需要知道它正在查询哪个 DataObject。像 Userforms 这样的模块会这样做,因为您可以技术上用任何模型作为父级。然而,这些模块确实将此关系的类名称存储在单独的字段中,以便我们能够适当地查询父级。对于 Userforms,此关系的类名称存储在名为 ParentClass 的字段中。但是,此模块不知道这一点。

您可以使用以下配置来告诉此模块任何关系的类名称信息所在位置(这里以 Userforms 为例)

SilverStripe\UserForms\Model\EditableFormField:
  field_classname_map:
    ParentID: ParentClass

field_classname_map 是我们要填充的配置,它期望一个数组,其中关系字段名称作为 key,对应的类名称字段作为 value

模块使用 relField()value,因此您可以通过数据字段或方法呈现此信息。

支持的关联关系

  • has_one
  • has_many
  • many_many(带有和没有 through 定义)

流畅支持

我打算在未来支持 Fluent 和导出本地化字段,但目前还没有提供支持。

未来功能

  • 添加选项/能力以存储二进制文件,以便可以使用固定装置恢复。
  • 告诉我您还需要什么!

此模块目前不执行的事情

  • 导出 _Live 表。我希望很快(不久)添加 _Live 表导出功能。
  • 尚未添加导出/保存资产二进制文件的支持。这意味着在当前状态下,您只能生成资产数据库记录。