如何重用 PHPUnit 函数

Posted

技术标签:

【中文标题】如何重用 PHPUnit 函数【英文标题】:How to reuse PHPUnit functions 【发布时间】:2017-01-20 15:26:18 【问题描述】:

我想通过调用它们而不是在所有单元测试中重复它们来重用我的一些 phpUnit 函数,例如:

public function testContent()
    
        $this->assertNotEmpty($this->response, $this->message);
    

如果我将它放在tests/TestCase.php 下,它会为所有单元测试运行。

在哪里放置这个合适的地方或者这通常是如何做的?顺便说一句,我在 Laravel 4 上使用它。

【问题讨论】:

一般来说,单元测试应该有相关的断言。检查响应的内容,以及设置不同场景时您期望的具体差异,而不是不为空。 @jedifans 我看不出有任何问题可以做出自己的断言 自己做是好的,但对每个测试重复断言相同的断言表明测试不会改变它们正在设置的内容。由于每个合作者都/应该被嘲笑,因此应该只有少数明确的情况下响应可能为空。 @jedifans 你在谈论经典的单元测试。同时,PHPUnit 可以完美地用于集成测试,在这种情况下,您可能希望确保正确生成应用程序的所有重要页面。 @jedifans :给定的代码只是一个例子。我在我的大多数单元测试中测试相关的东西。诸如缓存之类的东西,不为空,... 【参考方案1】:

显然,您的问题不是重复使用测试,而是您的测试在不期望的情况下被调用。

因此,请记住:现有类中名称以“test”(testFoo,testBar)开头的任何方法都将被视为测试。

所以如果你有这样的 A、B 和 C 类

class A extends \PHPUnit_Framework_TestCase 
   public function testFoo() ...
   public function testBar() ...


class B extends A 
   public function testBaz() ...


class C extends A 
   public function testQuz() ...

您将有 8 个测试:A::testFoo()、A::testBar()、B::testFoo()、B::testBar()、B::testBaz()、C::testFoo() , C::testBar(), C::testQuz()。

这可能不是你想要做的。 您可能希望仅在 B 和 C 类中拥有 testFoo 和 testBar,而不是 A。在这种情况下,您只需将 A 声明为抽象类。

abstract class A extends \PHPUnit_Framework_TestCase 
   public function testFoo() ...
   public function testBar() ...


class B extends A 
   public function testBaz() ...


class C extends A 
   public function testQuz() ...

现在你有 6 个测试:B::testFoo()、B::testBar()、B::testBaz()、C::testFoo()、C::testBar()、C::testQuz() .

也许,这是你需要的,也许不是。也许,您希望 testFoo() 和 testBar() 仅在 一些 继承的类中,而不是全部。

在这种情况下,在你的父类而不是测试中进行断言。

abstract class A extends \PHPUnit_Framework_TestCase 
   public function assertFoo()  ... 
   public function assertBar()  ... 


class B extends A 
   public function testFoo()  $this->assertFoo(); ...

   public function testBaz() ...


class C extends A 
   public function testBar()  $this->assertBar(); ...

   public function testQuz() ...

现在,您只有 4 个测试:B::testFoo()、B::testBaz、C::testBar()、C::testQuz()

【讨论】:

非常感谢,现在就试试。我需要你的最后一段代码。只有一件事,A 类中的 assertFoo() 和 assertBar 会有实现吗?不是空方法? 当然。毕竟这是主要目标 - 避免代码重复。附:不要忘记将答案标记为解决方案:)【参考方案2】:

根据to this manual做出自己的断言

制作类似的东西

namespace Vendor\Library\Tests;

abstract class BaseTestCase extends \PHPUnit_Framework_TestCase

   public function assertContentNotEmpty($response) 
       $this->assertNotEmpty($response);
   

然后用你的测试扩展这个类。 如果由于某些原因这种方法不方便,您可以将断言作为一个单独的类。

【讨论】:

setUp、tearDown等方法怎么样,需要再重复一遍吗?另外,它与放入 TestCase 有什么不同,它不会为所有测试运行吗?抱歉,phpunit 新手。 “运行所有测试”是什么意思?它只会在你调用一些测试 $this->assertNotEmpty($response) 时运行。 setUp、tearDown 不需要在父类中定义,但是如果你想在测试之间重复使用某些东西,你可以这样做。 目前,我的单元测试正在扩展TestCase.php。我的主要问题是,如果我将可重用函数放在那里,它们会默认运行,而无需我调用它们。 在这种情况下,只需将这个TestCase抽象化

以上是关于如何重用 PHPUnit 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用返回 IP 的函数进行 PHPUnit 测试?

如果该函数应该杀死 PHP,您如何使用 PHPUnit 来测试该函数?

PHPUnit:如何通过测试方法模拟内部调用的函数

PHPUnit 如何获得模拟方法的真实返回值?

使用匿名函数进行PHPUnit测试

如何在使用phpunit进行测试时生成会话变量