使用 Behat 进行 PHP 集成测试

问题描述

我是集成测试的新手,我的任务是为 cli 创建集成测试场景: bin/console import:products products.xml 负责从 xml 文件中读取数据并将数据插入到数据库表中。

final class ProductImporter extends AbstractImporter implements ProductImporterInterface
{
private ResourceResolverInterface $productResourceResolver;

private ProductRelationsPurifierInterface $productRelationsPurifier;

private ProductimagesAssignerInterface $productimagesAssigner;

private ProductChannelsAssignerInterface $productChannelsAssigner;

private ProductDesignerAssignerInterface $productDesignerAssigner;

private static array $channels = [];

private static array $designers = [];

public function __construct(
    ResourceResolverInterface $productResourceResolver,ProductRelationsPurifierInterface $productRelationsPurifier,ProductimagesAssignerInterface $productimagesAssigner,ProductChannelsAssignerInterface $productChannelsAssigner,ProductDesignerAssignerInterface $productDesignerAssigner
) {
    $this->productResourceResolver = $productResourceResolver;
    $this->productRelationsPurifier = $productRelationsPurifier;
    $this->productimagesAssigner = $productimagesAssigner;
    $this->productChannelsAssigner = $productChannelsAssigner;
    $this->productDesignerAssigner = $productDesignerAssigner;
}

public function import(array $row): ?ResourceInterface
{
    $code = $this->getColumnValue(self::CODE_TAG,$row);
    $designerId = (int) $this->getColumnValue('designerID',$row);
    $attributes = $this->getColumnValue(self::ATTRIBUTES_TAG,$row);
    $productChannels = $this->getColumnValue('channelAttributes',$row)['channel'];
    $images = $this->getColumnValue(self::IMAGES_TAG,$row)['image'];
    $isHidden = (bool) $attributes['isHidden'];

    /** @var ProductInterface $product */
    $product = $this->productResourceResolver->resolveResource($code);

    if (null !== $product->getId()) {
        // only if product is already in db
        $this->productRelationsPurifier->purifyRelations($product);
    }

    $product->setCode($code);
    $product->setEnabled(!$isHidden);
    $this->productimagesAssigner->assignImages($product,$images);
    $this->productDesignerAssigner->assign($product,$designerId);
    $this->productChannelsAssigner->assign($product,$productChannels);

    return $product;
}

public function getResourceCode(): string
{
    return 'product';
}

public static function setChannels(array $channels): void
{
    self::$channels = $channels;
}

public static function getChannels(): array
{
    return self::$channels;
}

public static function addDesigner(DesignerInterface $designer): void
{
    self::$channels[] = $designer;
}

public static function getDesigners(int $designerId): ?DesignerInterface
{
    /** @var DesignerInterface $designer */
    foreach (self::$designers as $designer) {
        if ($designer->getId() === $designerId) {
            return $designer;
        }
    }

    return null;
 }
}

我的问题不是给我写测试,而是告诉我如何/从哪里开始编写集成测试,以及我需要做的步骤。

解决方法

首先,如果您还没有设置 behat,则需要设置 behat。这大致意味着:

  • 通过作曲家要求它
  • 添加配置
  • 添加第一个上下文
  • 编写 .feature 文件

特征文件是用人类可读的语言编写的,而上下文将其翻译成代码。完成设置后,您可以逐行编写功能文件并使用上下文文件实现其背后的代码。

这是一个 example 特征文件,这是它的 example 上下文。

,

我假设您已阅读有关 Behat 的快速入门指南。 您可能错过的重要事项:

  1. 需要 composer require --dev
  2. 运行 vendor/bin/behat --init 将生成骨架文件

如果您的集成测试是关于运行某种网络浏览器和点击按钮 — 您还需要安装 Mink Extension 来为页面导航提供现成的实现低级句子。

如果您想在测试期间访问您的实际应用程序(例如,在测试设置期间在 DB 中创建一些 ORM 对象或获取预先验证的会话或其他内容),您需要在您的上下文中实例化您的实际应用程序(请参阅项目的 index.phpbootstrap.php 文件以了解它是如何实例化的)。在这种情况下,您可能最好为此目的使用单独的上下文,以便您可以将其用作其他测试上下文的子上下文。