如何用二手存储分隔TestCases?

时间:2012-10-03 16:52:01

标签: php unit-testing phpunit

我有测试数据模型的测试:

<?php
namespace Tests\Model\SQL;

/**
 * @group Model_Users
 * @group Model
 */
class UsersTest extends TestCase {

/** @var Users */
private $model;

public function setUp() {
    parent::setUp();
    $this->connection->execute( file_get_contents(
        __DIR__ . '/fixtures/countries.sql' ) );
    $this->model = new \Users(
        $this->connection
    );
}

    public function testUserExists() {
            $exists = $this->model->userExists( 'johndoe' );
            $this->assertTrue( $exists );
    }

}

Tests\Model\SQL\TestCase使用 SQLite 作为数据库,以尽可能快地保持测试。 无论如何,正如您所料,SQLite与 Postgres 不是同一个数据库,因此可能存在一些特殊情况,它们将在SQLite上失败并传递给PostgreSQL,反之亦然。

我的问题是

如何有效地(在记住DRY时)将架构设计为只能使用SQLite运行测试,然后才能使用Postgres。

当我说DRY时,我的意思是理想情况,当我只为一个模型编写一个测试用例时,我的测试架构会处理这个问题,所以我将能够运行这样的测试:

php tests/run.php --group=MockedDbWithSqlite # fast way, prefered, default

php tests/run.php --group=RealDb # slower way, but with more precise results

2 个答案:

答案 0 :(得分:1)

因此从评论来看,该问题与任何具体存储问题无关,而是更多关于如何将自定义参数传递给PHPUnit

因为,使用此参数,您将切换数据库驱动程序。

有几个选项可以做到这一点,但没有官方支持的“自定义参数”对象或其他东西。即便如此,如果有人愿意添加这个可能会很好:)

我的建议是使用以下选项之一:

Env变量

使测试/引导代码依赖于$_ENV变量。

$dbDriverFactory->getInstanceFor(getenv('DB'));

并使用以下方法之一

export DB=postgress
phpunit

DB=postpress; phpunit;

或使用phpunits xml config设置env或您喜欢的任何内容。

通过这样做,您可以提供两个xml配置phpunit-sqlite.xml&amp; phpunit-pg.xml并运行:

phpunit -c phpunit-sqlite.xml

不是env。文档部分Setting PHP INI settings, Constants and Global Variables中列出的任何方法都可以使用。

“自定义”cli参数

像这样调用phpunit:

phpunit --colors --usePostgres

并在测试用例或引导代码中添加类似内容:

if (in_array('--usePostgress', $_SERVER['argv'], true) {
    $db = $this->setupPG();
} else {
    $db = $this->setupSqlite();
}

答案 1 :(得分:0)

我对edorian的看法与此不同。我喜欢使用继承来做这种事情。优点是您可以在同一测试运行中运行SQLite和Postgres测试。缺点是您必须为要在两个数据库中运行的每个测试文件添加一些代码。您必须为要测试的每个新数据库重复此操作。以下是它的工作原理:

class UsersTestBase extends TestCase {
    //Unchanged
}

class UsersTestSQLite extends UsersTestBase{}

class UsersTestPostgres extends UsersTestBase {
    function __construct(){
        parent::_construct("postgres");
    }
}

因此,UsersTest完全相同,除了名称已更改为追加“Base”。 然后,您有一个派生的UsersTestSQLite类。这什么都不做。在这一点上,我们没有获得或失去任何东西。

然后我们有了UsersTestPostgres。这以某种方式告诉对象使用postgres而不是sqlite。在这种情况下,我假设TestCase有一个构造函数,可以将数据库用作可选参数(默认为“sqlite”)。显然有很多替代方案,但我希望你能看到一般的想法。

最后,您需要将适当的@group标记添加到派生类中,以便控制它们何时运行。