12

我遇到了一个有趣的问题。我正在使用 PHPUnit,我的测试每次运行时都会占用更多内存。IE...

2.25 MB

2.5 MB

3.0 MB

3.5 MB .......

有谁知道如何清除正在消耗的内存,有人可以建议我深入探索吗?直接的问题是我的一些较大的测试内存不足,仅仅继续增加 PHP 中的最大内存分配还不够好......我需要知道为什么从命令行运行的 PHPUnit 测试会有内存在运行之间“停留”的用法。

4

4 回答 4

26

内存增加有三到四个原因:

1) PHPUnit 收集代码覆盖率数据

除了关闭代码覆盖率之外,您无能为力。

2) PHPUnit 缓存文件令牌以进行代码覆盖

您可以<phpunit cacheTokens="false">在您的 PHPUnit xml 中使用。请参阅http://phpunit.de/manual/current/en/installation.html#installing.upgrading中的说明

3) PHPUnit 自身没有正确清理

在其当前的实现中,它保留了测试用例,因为那是存储结果数据的地方。将来这将被更改为更有效,但现在它是如何运作的。

4)通向“4”:你也需要清理自己

由于TestCase实例保留在周围,因此您的成员变量也保留在周围。

这意味着您可以通过使用来节省大量内存

public function tearDown() {
    unset($this->whatever);
}

但这样做非常乏味。

我的建议是为所有的 TestCases 建立一个基础测试类并使用它:

class MyBaseTest extends \PHPUnit_Framework_TestCase {

    protected function tearDown()
    {
        $refl = new \ReflectionObject($this);
        foreach ($refl->getProperties() as $prop) {
            if (!$prop->isStatic() && 0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit_')) {
                $prop->setAccessible(true);
                $prop->setValue($this, null);
            }
        }
    }
}

这将以一种很好的自动化方式在您之后进行清理。

(片段的道具转到: http: //kriswallsmith.net/post/18029585104/faster-phpunit


PHPUnit 不能以向后兼容的方式做到这一点,这不会破坏人们的项目,所以你必须自己添加它:)

于 2012-11-25T14:05:04.427 回答
5

Calvin,根据聊天中的讨论,这是由于缺少重置功能。

在测试的时候,我们必须保证测试环境是一致的,这样我们才能得到准确的结果。计算是输入/输出,因此我们应该在 PHPUnit 中使用 Fixtures来重置存储,以防止像这样的“内存泄漏”。

于 2012-11-24T02:15:29.357 回答
4

@edorian 和 @mauris 已经介绍了 PHPUnit 垃圾收集背后的技术细节,但我想添加 PHPUnit(至少在我正在运行的版本 3.7.21 中)让您能够添加评论:

/**
 * @backupGlobals disabled
 */
class MyClassTests extends PHPUnit_Framework_TestCase{}

在添加注释之前,每次运行测试套件时,我的内存使用量大致翻了一番,最后一个达到约 1100 MB。现在它们以 15 MB 运行。

于 2013-12-23T17:02:53.677 回答
1

如果您使用 PDO(或类似的数据库抽象),那么您可以使用“sqlite::memory:”作为 DSN。这具有三个很大的优点:

  1. 每次测试后自动清理
  2. 没有机会意外接触生产数据库(例如,即使您在生产服务器上运行单元测试)。
  3. 全部在内存中,因此测试可能会运行得更快

缺点是您的 SQL 必须在 MySQL 和 SQLite 之间移植。这可能需要做很多工作(对于更大的项目,这通常是值得的,不仅仅是为了测试,而是为了改进代码设计的方式。)在你的情况下,你在聊天记录中提到了使用 Doctrine ,所以你可能已经有了一个很好的抽象,因此它可能只是在 SQLite 上运行而无需更改。

于 2012-11-25T00:32:23.467 回答