laravel - 单元测试、集成测试还是功能测试?

标签 laravel unit-testing eloquent naming-conventions standards

一个简单的问题:您如何区分功能、单元和集成测试?

有很多不同的意见,但我特别想确定如何组织涉及模型关系的 Laravel 测试。以下是一些需要测试的 PHP 代码示例:

public function prices()
{
    return $this->hasMany(Prices::class);
}


public function getPriceAttribute($)
{
    return $this->prices()->first() * 2;
}

我所理解的测试描述(请随时纠正我):

单元测试
  • 测试代码的最小部分
  • 不接触数据库
  • 不与系统的任何其他部分交互

  • 集成测试
  • 测试部分系统协同工作
  • 例如调用需要一起测试的辅助函数的 Controller

  • 功能测试
  • 黑盒测试
  • 例如调用一个 api 端点,看到它返回了正确的 JSON 响应


  • 鉴于这些描述,这是我的问题:
  • 我的 Laravel 模型测试需要测试最小的代码单元——模型的计算访问器,这让它感觉像一个单元测试
  • 但是,它在加载模型的关系时会接触到数据库
  • 感觉不像是集成测试,因为它只涉及其他相关模型,不涉及内部或外部服务
  • 当 Laravel 中的其他属性访问器测试不涉及数据库或模型的关系时,它们将归入单元测试
  • 将这些类型的测试分成集成测试意味着针对其属性的单个模型的测试在集成和单元测试之间分散

  • 那么,如果不模拟模型之间的关系,我的测试应该属于哪里?

    最佳答案

    如果我正确解释了您的原始问题,我认为这里的杀手级约束是:

    那么,如果不模拟模型之间的关系,我的测试应该属于哪里?

    如果不允许模拟并且您需要接触数据库,那么根据您/和谷歌的定义,它必须属于集成/中型测试:)

    我认为这是获取价格属性功能与数据库分离的方式。即使它在模型中,价格也可能来自任何地方。现在它是一个 RDBMS,但是如果您的组织变得非常大并且它拆分为另一个服务怎么办?基本上,我相信 getPriceAttributes 的能力区别于属性的存储:

    public function getPriceAttribute($)
    {
        return $this->prices()->first() * 2;
    }
    

    如果你接受这个推理,它会创建一个支持单元测试的逻辑分离。 prices()可以模拟以返回 0、1 和许多 (2) 个结果的集合。此测试可以作为单元测试执行(为了使测试执行速度提高几个数量级(即大约 1 毫秒,而与本地数据库对话可能需要 10 或 100 毫秒)

    我不熟悉 php 测试生态系统,但一种方法是使用 test specific subclass (不确定以下是否有效 PHP :p ):
    class PricedModel extends YourModel {
       function __construct($stub_prices_supporting_first) {
         $this->stub_prices = $stub_prices_supporting_first;
       }
    
       public function prices() {
         return $this->stub_prices;
       }
    
    }
    

    测试
    function test_priced_model_0_prices() {
       p = new PricedModel(new Prices(array()));
       assert.equal(null, p.getPriceAttribute());
    }
    
    function test_priced_model_1_price() {
       p = new PricedModel(new Prices(array(1)));
       assert.equal(2, p.getPriceAttribute());
    }
    
    function test_priced_model_2_prices() {
       p = new PricedModel(new Prices(array(5, 1)));
       assert.equal(10, p.getPriceAttribute());
    }
    

    以上应该希望能让你完全控制输入到getPriceAttribute支持直接无IO单元测试的方法。

    ——
    此外,上面的所有单元测试都可以告诉您,您能够正确处理价格,如果您能够查询价格,则不会对任何价格反馈!

    关于laravel - 单元测试、集成测试还是功能测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55636697/

    相关文章:

    laravel - Kubernetes副本数量与性能

    c# - WPF MVVM - 单元测试命令 - 私有(private)方法与公共(public)方法?

    mysql - 如何在 Eloquent 中重命名属性?

    php - MySQL 语法错误 : ORDER BY clause is not in GROUP BY

    laravel - 如何在 Laravel 上的电子邮件布局中显示图像?

    php - Laravel 5.5 自定义异常处理

    unit-testing - 模拟 DBSet,EF 模型优先

    php - 对日期敏感的功能进行单元测试?

    php - 在 eloquent LARAVEL 5.2.29 上进行子查询

    laravel - Laravel 中发送多个附件邮件时出现问题