Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Laravel 单元测试、集成测试还是功能测试?_Laravel_Unit Testing_Eloquent_Naming Conventions_Standards - Fatal编程技术网

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

Laravel 单元测试、集成测试还是功能测试?,laravel,unit-testing,eloquent,naming-conventions,standards,Laravel,Unit Testing,Eloquent,Naming Conventions,Standards,一个简单的问题:如何区分特性测试、单元测试和集成测试 有很多不同的观点,但我特别想确定如何组织一个涉及模特关系的拉威尔测试。以下是一些需要测试的PHP代码的示例: public function prices() { return $this->hasMany(Prices::class); } public function getPriceAttribute($) { return $this->prices()->first() * 2; } 我理

一个简单的问题:如何区分特性测试、单元测试和集成测试

有很多不同的观点,但我特别想确定如何组织一个涉及模特关系的拉威尔测试。以下是一些需要测试的PHP代码的示例:

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


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

我理解的测试描述(请随意更正):

单元测试

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

  • 测试系统的一部分是否协同工作
  • e、 g调用需要一起测试的辅助函数的控制器
功能测试

  • 黑盒试验
  • e、 g.调用api端点,查看它是否返回了正确的JSON响应

根据这些描述,以下是我的问题:

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

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

如果我正确地解释了您的原始问题,我认为这里的致命限制是:

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

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


我认为,get price属性功能与DB是分开的。即使在模型中,价格也可能来自任何地方。现在它是一个关系数据库管理系统,但是如果你的组织变得非常庞大,它分裂成另一个服务呢?基本上,我认为
getPriceAttributes
的功能不同于属性的存储:

public function getPriceAttribute($)
{
    return $this->prices()->first() * 2;
}
如果您接受这种推理,它将创建一个支持单元测试的逻辑分离<代码>价格()可以模拟为返回0、1和多(2)个结果的集合。该测试可以作为单元测试执行(测试执行速度快几个数量级(即与本地DB对话的毫秒数可能为1毫秒,而不是10秒或100秒)


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

测验

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

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

这些测试的区别在于它们各自的目标:

  • 单元测试的目的是发现那些可以在软件的孤立小部分中发现的bug。(请注意,这并不是说您必须隔离—这只是意味着您的注意力集中在隔离的代码上。不需要经常进行隔离和模拟来达到这个目标:考虑调用
    sin
    函数—您几乎不需要模拟它,您让您的测试系统只调用原始的一个。)

  • 集成测试的目的是发现两个或多个组件交互中的错误,例如对接口的相互误解。这些错误在隔离的软件中找不到:如果您单独测试代码,您也会根据对其他组件的理解(可能是错误的)编写测试

  • 然后,您描述的功能测试的目标是发现更多的bug,而目前其他测试无法检测到这些bug。此类bug的一个例子是,集成了旧版本的功能(当时是正确的,但缺少一些功能)

结论,虽然可能令人惊讶,但它不是在单元测试中禁止数据库访问的更严格的意义。考虑下面的场景:您开始编写单元测试并模拟数据库访问。稍后,您意识到您可以更加懒惰,只使用数据库而不嘲弄-但是,否则留下一个所有测试都保持原样。您的测试没有更改,它们将继续像以前一样在隔离的代码中查找错误。它们现在可能运行得稍慢,并且安装可能比模拟数据库更复杂。但是,测试套件的目标是相同的-有和没有模拟数据库


这个场景稍微简化了一些事情,因为可能有一些测试用例只能通过模拟来完成:例如,测试数据库以特定方式损坏的情况,并且您的代码可以正确处理。使用真实的数据库,这些测试用例实际上可能无法设置。

另一种观点(与您的定义非常相似)感谢您的详细回答。我不确定我是否能将您答案的第二部分翻译成可以使用PHP的内容,但我猜您谈论的是模拟和存根。我在其他地方也使用过这些内容,但似乎总有中间测试的类型(如我问题中的测试).模仿它是非常困难的,因为拉威尔正在使用这个方法作为一个神奇的访问器。我认为你是对的,它是一个int
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());
}