La creazione appuntamento fisso nel DBUnit è estremamente lento. Ci vogliono 1,5 secondi ogni volta con Core2Duo E8400 4GB Kingston 1333. È possibile trovare il collo di bottiglia con xdebug e risolvere il problema (se è possibile), o si può fare in uno dei seguenti:
1.)
È può essere eseguito solo i file di test attualmente sviluppa con un xml bootstrap personalizzato:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://phpunit.de/phpunit.xsd"
backupGlobals="false"
verbose="true"
bootstrap="test/bootstrap.php">
<testsuites>
<testsuite>
<directory>test/integration</directory>
<exclude>test/integration/database/RoleDataTest.php</exclude>
</testsuite>
</testsuites>
<php>
<env name="APPLICATION_MODE" value="test"/>
</php>
</phpunit>
La escludere una parte è importante qui. Puoi anche usare i gruppi di test.
2.)
namespace test\integration;
abstract class AbstractTestCase extends \PHPUnit_Extensions_Database_TestCase
{
static protected $pdo;
static protected $connection;
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
public function getConnection()
{
if (!isset(static::$pdo)) {
static::$pdo = new \PDO('pgsql:host=localhost;port=5432;dbname=dobra_test', 'postgres', 'inflames', array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
static::$connection = $this->createDefaultDBConnection(static::$pdo);
}
return static::$connection;
}
/**
* @return \PHPUnit_Extensions_Database_Operation_DatabaseOperation
*/
static protected $fixtureSet = false;
protected function getSetUpOperation()
{
$c = get_class($this;
if (!$c::$fixtureSet) {
$c::$fixtureSet = true;
return \PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT(true);
}
return \PHPUnit_Extensions_Database_Operation_Factory::NONE();
}
static protected $dataSet;
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
public function getDataSet()
{
$c = get_class($this;
if (!isset($c::$dataSet)) {
$c::$dataSet = $this->createDataSet();
}
return $c::$dataSet;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
abstract protected function createDataSet();
protected function dataSetToRows($tableName, array $ids)
{
$transformer = new DataSetRowsTransformer($this->getDataSet());
$transformer->findRowsByIds($tableName, $ids);
$transformer->cutColumnPrefix();
return $transformer->getRows();
}
}
È possibile eseguire l'override del TestCase. In questo esempio si utilizzerà una sola connessione pdo per ogni caso di test (è possibile iniettarlo nel proprio codice con l'iniezione delle dipendenze), ignorando l'operazione di configurazione è possibile impostare l'apparecchio solo una volta per testcase o una sola volta per ogni test (dipende da self::
o $cls = get_class($this); $cls::
). (PHPUnit ha una cattiva progettazione, crea una nuova istanza ad ogni chiamata di prova, quindi devi modificare i nomi delle classi per memorizzare le variabili per istanza o per classe.) In questo scenario devi scrivere i test per dipendere reciprocamente con l'annotazione @depend
. Ad esempio è possibile eliminare la stessa riga creata nel test precedente.
Con questo codice di prova 1.5 secs
invece di 6 x 1.5 = 9 secs
:
namespace test\integration\database;
use Authorization\PermissionData;
use test\integration\AbstractTestCase;
use test\integration\ArrayDataSet;
class PermissionDataTest extends AbstractTestCase
{
static protected $fixtureSet = false;
static protected $dataSet;
/** @var PermissionData */
protected $permissionData;
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
public function createDataSet()
{
return new ArrayDataSet(array(
'permission' => array(
array('permission_id' => '1', 'permission_method' => 'GET', 'permission_resource' => '^/$'),
array('permission_id' => '2', 'permission_method' => 'POST', 'permission_resource' => '^/$'),
array('permission_id' => '3', 'permission_method' => 'DELETE', 'permission_resource' => '^/$')
),
'user' => array(
array('user_id' => '1', 'user_name' => 'Jánszky László', 'user_email' => '[email protected]', 'user_salt' => '12435')
),
'user_permission' => array(
array('user_permission_id' => '1', 'user_id' => '1', 'permission_id' => '1'),
array('user_permission_id' => '2', 'user_id' => '1', 'permission_id' => '2')
),
'role' => array(
array('role_id' => '1', 'role_name' => 'admin')
),
'role_permission' => array(
array('role_permission_id' => '1', 'role_id' => '1', 'permission_id' => '1')
),
'permission_cache' => array(
array('permission_cache_id' => '1', 'user_id' => '1', 'permission_id' => '1'),
array('permission_cache_id' => '2', 'user_id' => '1', 'permission_id' => '2'),
)
));
}
public function testReadAllShouldReturnEveryRow()
{
$this->assertEquals($this->permissionData->readAll(), $this->dataSetToRows('permission', array(3, 2, 1)));
}
/** @depends testReadAllShouldReturnEveryRow */
public function testReadAllByRoleIdShouldReturnEveryRowRelatedToRoleId()
{
$this->assertEquals($this->permissionData->readAllByRoleId(1), $this->dataSetToRows('permission', array(1)));
}
/** @depends testReadAllByRoleIdShouldReturnEveryRowRelatedToRoleId */
public function testReadAllByUserIdShouldReturnEveryRowRelatedToUserId()
{
$this->assertEquals($this->permissionData->readAllByUserId(1), $this->dataSetToRows('permission', array(2, 1)));
}
/** @depends testReadAllByUserIdShouldReturnEveryRowRelatedToUserId */
public function testCreateShouldAddNewRow()
{
$method = 'PUT';
$resource = '^/$';
$createdRow = $this->permissionData->create($method, $resource);
$this->assertTrue($createdRow['id'] > 0);
$this->assertEquals($this->getDataSet()->getTable('permission')->getRowCount() + 1, $this->getConnection()->getRowCount('permission'));
return $createdRow;
}
/** @depends testCreateShouldAddNewRow */
public function testDeleteShouldRemoveRow(array $createdRow)
{
$this->permissionData->delete($createdRow['id']);
$this->assertEquals($this->getDataSet()->getTable('permission')->getRowCount(), $this->getConnection()->getRowCount('permission'));
}
/** @depends testDeleteShouldRemoveRow */
public function testDeleteShouldRemoveRowAndRelations()
{
$this->permissionData->delete(1);
$this->assertEquals($this->getDataSet()->getTable('permission')->getRowCount() - 1, $this->getConnection()->getRowCount('permission'));
$this->assertEquals($this->getDataSet()->getTable('user_permission')->getRowCount() - 1, $this->getConnection()->getRowCount('user_permission'));
$this->assertEquals($this->getDataSet()->getTable('role_permission')->getRowCount() - 1, $this->getConnection()->getRowCount('role_permission'));
$this->assertEquals($this->getDataSet()->getTable('permission_cache')->getRowCount() - 1, $this->getConnection()->getRowCount('permission_cache'));
}
public function setUp()
{
parent::setUp();
$this->permissionData = new PermissionData($this->getConnection()->getConnection());
}
}
3.)
Un'altra soluzione per creare l'apparecchio solo una volta per ogni progetto, e dopo che l'uso ogni prova nelle transazioni e rollback dopo ogni test. (Questo non funziona se si ha il codice differito pgsql che richiede il commit per verificare i vincoli.)
È necessario specificare dove si trova il collo di bottiglia. Probabilmente accelererà i tuoi bisogni se riuscirai a prendere in giro l'intero database in modo da non dover eseguire affatto dbunit. Un test dovrebbe essere eseguito al di sotto di un decimo di secondo, il che è in realtà considerevole lento per un test. – hakre
Dato che non hai menzionato, stai usando Fixtures e condividendo il più possibile? – Pradeep
Sto utilizzando gli apparecchi e condividendo il più ragionevolmente possibile. C'è un modo per profilare il corridore di prova? –