”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 将测试集中在域上。 PHPUnit 示例

将测试集中在域上。 PHPUnit 示例

发布于2024-11-03
浏览:346

介绍

很多时候,开发人员尝试测试 100%(或几乎 100%)的代码。显然,这是每个团队应该为他们的项目达到的目标,但从我的角度来看,只应该完全测试整个代码的一部分:您的域。

域基本上是代码中定义项目实际功能的部分。例如,当您将实体持久保存到数据库时,您的域不负责将其持久保存在数据库上,而是确保持久数据根据您的业务模型有意义。可能,当您将数据保存到数据库时,您将使用 PHP Doctrine 等外部库。该库已经经过充分测试,无需测试它的功能。如果您将正确的数据传递给学说,它将毫无问题地保存到数据库中。

以下部分中显示的示例并不试图展示领域驱动设计是如何工作的,有很多文章对其进行了很好的解释。我将尝试展示如何明确定义和解耦您的域可以帮助轻松测试并专注于您的应用程序的功能。

该示例是在 Symfony 环境上构建并使用 PHPUnit 库的,但这个想法对任何语言或框架都有效。

要测试的代码

假设我们的应用程序连接到一个外部 API,该 API 返回有关指定日期的下雨概率的数据。返回的数据如下所示:


{
   "date" : "2022-12-01",
   "rain_probability" : 0.75
}


现在,我们必须获取这些数据并按照以下映射对其进行分类:

  • rain_probability 低
  • rain_probability ≥ 0.40 && rain_probability MEDIUM
  • rain_probability ≥ 0.75:

并将结果保存在由以下实体描述的数据库表中:


#[ORM\Entity(repositoryClass: RainMeasure::class)]
class RainMeasure {

    #[ORM\Column]
    private string $date;

    #[ORM\Column]
    private float $probability;

    #[ORM\Column(length: 10)]
    private string $label;

    // Getters and setters
    // .......
}


让我们创建一个处理程序,它获取外部 api 数据,根据下雨概率设置标签并将其保存到数据库。


class RainMeassureHandler {
    private EntityManagerInterface $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function saveMeasure(array $measureData): void
    {
        if($measureData['rain_probability'] = 0.40 && $measureData['rain_probability'] setDate($measureData['date']);
        $rainMeasure->setProbability($measureData['rain_probability']);
        $rainMeasure->setLabel($label);

        $this->em->persist($rainMeasure);
        $this->em->flush();
    }
}


如果我们尝试为上述处理程序创建一个测试,我们会发现我们需要注入EntityManagerInterface,因为我们想要测试的行为(根据概率值设置标签)是耦合在同一个处理程序中,将结果保存到数据库中。我们可以尝试使用模拟和存根加载 EntityManagerInterface,但是有必要吗?显然不是。正如之前所说,我们应该尝试专注于测试属于我们领域的行为,即根据下雨概率获得正确的标签。

我们想要测试的解耦行为

为了简化我们的测试,我们将要测试的行为移至另一个类:


class RainMeasureLabelHandler 
{
    public function getLabelFromProbability(float $prob): string
    {
        if($prob = 0.40 && $prob 

现在,我们的 RainMeassureHandler 将如下所示:


class RainMeasureHandler 
{
    private EntityManagerInterface $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function saveMeasure(array $measureData): void
    {
        $rainMeasureLabelHandler = new RainMeasureLabelHandler();
        $label = $rainMeasureLabelHandler->getLabelFromProbability($measureData['rain_probability']);

        $rainMeasure = new RainMeasure();
        $rainMeasure->setDate($measureData['date']);
        $rainMeasure->setProbability($measureData['rain_probability']);
        $rainMeasure->setLabel($label);

        $this->em->persist($rainMeasure);
        $this->em->flush();
    }
}


现在我们可以专注于测试我们的RainMeasureLabelHandler,它将成为我们域的一部分,并且不依赖于外部层。测试它很简单,如图所示:

Focusing your tests on the domain. A PHPUnit example

结论

我想说其他类型的测试也很有用。也许我们有一个 api,并且希望使用一个测试环境来测试输入和输出,其中包括数据库和我们可能需要的其他资源。但是,请记住将您的域解耦并进行全面测试。

版本声明 本文转载于:https://dev.to/icolomina/focusing-your-tests-on-the-domain-a-phpunit-example-c82?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何为 DOM 元素生成精确的 CSS 路径?
    如何为 DOM 元素生成精确的 CSS 路径?
    以增强的精度从 DOM 元素检索 CSS 路径提供的函数尝试为给定 DOM 元素生成 CSS 路径。然而,它的输出缺乏特异性,无法捕获元素在其兄弟元素中的位置。为了解决这个问题,我们需要一种更复杂的方法。改进的 CSS 路径函数下面介绍的增强函数解决了原来的限制:var cssPath = func...
    编程 发布于2024-11-03
  • 如何将单个 Python 字典写入具有精确标题和值行的 CSV 文件?
    如何将单个 Python 字典写入具有精确标题和值行的 CSV 文件?
    探索将 Python 字典写入 CSV 文件的细微差别您对将 Python 字典无缝写入 CSV 文件的追求给您带来了意想不到的挑战。虽然您设想在作为标题的字典键和作为第二行的值之间进行清晰的划分,但您当前的方法似乎还不够。让我们深入细节,解锁解决方案。问题在于方法的选择。 DictWriter.w...
    编程 发布于2024-11-03
  • 如何处理 Go 中延迟函数的错误返回值?
    如何处理 Go 中延迟函数的错误返回值?
    处理 Go 中返回值错误的延迟函数当返回变量的函数在没有延迟的情况下被延迟时,gometalinter 和 errcheck 正确地发出警告检查其返回的错误。这可能会导致未处理的错误和潜在的运行时问题。处理这种情况的习惯用法不是推迟函数本身,而是将其包装在另一个检查返回值的函数中。这是一个例子:de...
    编程 发布于2024-11-03
  • 为什么程序员不能总是记住代码:背后的科学
    为什么程序员不能总是记住代码:背后的科学
    如果您曾经想知道为什么程序员很难回忆起他们编写的确切代码,那么您并不孤单。尽管花费了数小时编码,许多开发人员经常忘记细节。这并不是因为缺乏知识或经验,而是因为工作本身的性质。我们来探究一下这种现象背后的原因。 编程的本质 通过记忆解决问题 这比仅仅记忆语法更能解决问题...
    编程 发布于2024-11-03
  • 你并不孤单:在社区的支持下掌握 Python
    你并不孤单:在社区的支持下掌握 Python
    加入 Python 社区可获得:社区论坛:向经验丰富的开发者获取支持和建议(如 Stack Overflow)。Discord 服务器:实时聊天室,提供即时支持和指导(如 Python Discord)。在线课程和研讨会:来自专家的指导,涵盖各种主题(如 Udemy 上的 Python NumPy ...
    编程 发布于2024-11-03
  • 学习伙伴
    学习伙伴
    聊天机器人界面,允许用户输入消息并接收来自 GPT-3.5 语言模型的对话响应。 特征 用于处理 HTTP 请求的基于 Flask 的 Web 服务器。 呈现用作用户界面的基本 HTML 模板 (chat.html)。 通过 POST 请求接受用户输入并将其发送到 OpenAI 的 GPT-3.5 ...
    编程 发布于2024-11-03
  • 前端开发 + 数据结构和算法:DSA 如何为您的 React 应用程序提供动力 ⚡
    前端开发 + 数据结构和算法:DSA 如何为您的 React 应用程序提供动力 ⚡
    专注于前端的面试通常根本不关心 DSA。 对于我们这些记得在学校/大学学习过 DSA 的人来说,所有的例子都感觉纯粹是算法(有充分的理由),但几乎没有任何例子或指导来说明我们每天使用的产品如何利用这个概念。 “我需要这个吗?” 你已经问过很多次这个问题了,不是吗? ? 以下是您今天可以在 React...
    编程 发布于2024-11-03
  • 为什么表行上的框阴影在不同浏览器中表现不同?
    为什么表行上的框阴影在不同浏览器中表现不同?
    跨浏览器表行上的框阴影外观不一致应用于表行 () 的 CSS 框阴影可能表现出不一致的行为跨各种浏览器。尽管 CSS 相同,但某些浏览器可能会按预期显示阴影,而其他浏览器则可能不会。要解决此问题,建议将 Transform 属性与 box-shadow 属性结合使用。将scale(1,1)添加到tr...
    编程 发布于2024-11-03
  • 探索 PHP 中的并发性和并行性:实践教程和技巧
    探索 PHP 中的并发性和并行性:实践教程和技巧
    理解并发性和并行性对于编写高效的 PHP 应用程序至关重要,特别是在处理需要同时处理的多个任务或操作时。这是理解和实现 PHP 并发性和并行性的分步指南,包含实践示例和说明。 1.并发与并行 并发:指系统通过交错执行同时处理多个任务的能力。这并不一定意味着任务是同时执行的,只是对它们...
    编程 发布于2024-11-03
  • ReactJs 与 Angular
    ReactJs 与 Angular
    React 和 Angular 是用于构建 Web 应用程序的两个最流行的框架/库,但它们在关键方面有所不同。以下是 React 和 Angular 之间主要区别的细分: 1. 类型:库与框架 React:一个用于构建用户界面的库,主要关注视图层。它允许开发人员将其与其他库集成以处理...
    编程 发布于2024-11-03
  • 如何使用变量中存储的类名动态实例化 JavaScript 对象?
    如何使用变量中存储的类名动态实例化 JavaScript 对象?
    使用动态类名实例化 JavaScript 对象假设您需要使用存储在变量中的类名实例化 JavaScript 对象。下面是一个说明性示例:// Define the class MyClass = Class.extend({}); // Store the class name in a strin...
    编程 发布于2024-11-03
  • Spring Boot 中的 OAuth 身份验证:Google 和 GitHub 登录集成指南
    Spring Boot 中的 OAuth 身份验证:Google 和 GitHub 登录集成指南
    使用 OAuth 2.0 增强安全性:在 Spring Boot 中实现社交登录 在现代 Web 开发的世界中,保护您的应用程序并使用户的身份验证尽可能顺利是首要任务。这就是 OAuth 2.0 的用武之地——它是一个强大的工具,不仅可以帮助保护您的 API,还可以让用户使用现有帐户从 Google...
    编程 发布于2024-11-03
  • 热点图——巴西 vs 意大利世界杯决赛)
    热点图——巴西 vs 意大利世界杯决赛)
    在这篇文章中,我开始尝试使用 Python 和 Seaborn 和 Matplotlib 创建 1970 年世界杯决赛中巴西运动的热图 。这个想法是根据那场比赛的比赛风格特征来代表巴西队在场上占据的空间。 1. 绘制场地 场地设计为比例坐标(130x90),包括边线、球门区和中心圈,...
    编程 发布于2024-11-03
  • 如何在 C++ 中连接字符串文字和字符文字?
    如何在 C++ 中连接字符串文字和字符文字?
    C 中的字符串文字和字符文字 尝试在 C 中连接字符串文字与字符文字时,可能会出现意外行为。例如:string str = "ab" 'c'; cout << str << endl;此代码会产生不可预测的输出,因为没有定义“”运算符来组合字符串文字和...
    编程 发布于2024-11-03
  • 通过“Go 练习挑战”课程释放您的算法潜力
    通过“Go 练习挑战”课程释放您的算法潜力
    通过 LabEx 的“Go Practice Challenges”课程踏上激动人心的旅程,提高您的编程技能。这门综合课程旨在帮助您掌握解决问题的艺术和提高编码效率,为您提供应对各种算法挑战的工具和技术。 深入算法世界 “围棋实践挑战”课程提供了一系列实际挑战,将突破您的算法思维界限...
    编程 发布于2024-11-03

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3