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

Jac*_*ero 6 standards unit-testing naming-conventions laravel eloquent

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

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

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


public function getPriceAttribute($)
{
    return $this->prices()->first() * 2;
}
Run Code Online (Sandbox Code Playgroud)

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

单元测试

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

集成测试

  • 测试系统的一部分协同工作
  • 例如,调用需要一起测试的辅助函数的控制器

功能测试

  • 黑盒测试
  • 例如调用 api 端点,查看它是否返回了正确的 JSON 响应

鉴于这些描述,这是我的问题:

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

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

dm0*_*514 2

如果 I\xe2\x80\x99m 正确解释你原来的问题,我认为这里的杀手约束是:

\n\n

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

\n\n

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

\n\n
\n\n

我的想法是获取价格属性功能与数据库是分开的。即使它在模型中,价格也可能来自任何地方。现在它是一个 RDBMS,但是如果您的组织变得非常大并且它分裂成另一个服务怎么办?基本上,我认为, 的功能getPriceAttributes与属性的存储不同:

\n\n
public function getPriceAttribute($)\n{\n    return $this->prices()->first() * 2;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您接受这种推理,它就会创建支持单元测试的逻辑分离。 prices()可以模拟返回 0、1 和多 (2) 个结果的集合。该测试可以作为单元测试来执行(测试执行速度要快几个数量级(即,与本地数据库通信可能需要10 或 100 毫秒,而大约 1 毫秒)

\n\n
\n\n

我不熟悉 php 测试生态系统,但一种方法可以是使用特定于测试的子类(不确定以下内容是否有效 PHP :p ):

\n\n
class PricedModel extends YourModel {\n   function __construct($stub_prices_supporting_first) {\n     $this->stub_prices = $stub_prices_supporting_first;\n   }\n\n   public function prices() {\n     return $this->stub_prices;\n   }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

测试

\n\n
function test_priced_model_0_prices() {\n   p = new PricedModel(new Prices(array()));\n   assert.equal(null, p.getPriceAttribute());\n}\n\nfunction test_priced_model_1_price() {\n   p = new PricedModel(new Prices(array(1)));\n   assert.equal(2, p.getPriceAttribute());\n}\n\nfunction test_priced_model_2_prices() {\n   p = new PricedModel(new Prices(array(5, 1)));\n   assert.equal(10, p.getPriceAttribute());\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

上面的内容应该能让您完全控制方法的输入getPriceAttribute,以支持直接的无 IO 单元测试。

\n\n

\xe2\x80\x94\xe2\x80\x94\n上述所有单元测试都可以告诉您,您\xe2\x80\x99能够正确处理价格,它不会\xe2\x80\x99对任何反馈进行定价您\xe2\x80\x99可以查询价格!

\n