Commit 6ef5a054 authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

Merge branch 'dev' of github.com:IvanChepurnyi/EcomDev_PHPUnit into dev

parents a5e71621 226f4127
......@@ -33,6 +33,9 @@ class EcomDev_PHPUnit_Model_Fixture
// Configuration path for eav loaders
const XML_PATH_FIXTURE_EAV_LOADERS = 'phpunit/suite/fixture/eav';
// Configuration path for attribute loaders
const XML_PATH_FIXTURE_ATTRIBUTE_LOADERS = 'phpunit/suite/fixture/attribute';
// Default eav loader class node in loaders configuration
const DEFAULT_EAV_LOADER_NODE = 'default';
......@@ -42,6 +45,9 @@ class EcomDev_PHPUnit_Model_Fixture
// Default eav loader class alias
const DEFAULT_EAV_LOADER_CLASS = 'ecomdev_phpunit/fixture_eav_default';
// Default attribute loader class alias
const DEFAULT_ATTRIBUTE_LOADER_CLASS = 'ecomdev_phpunit/fixture_attribute_default';
// Key for storing fixture data into storage
const STORAGE_KEY_FIXTURE = 'fixture';
......@@ -51,9 +57,12 @@ class EcomDev_PHPUnit_Model_Fixture
// Key for loaded entities by EAV loaders
const STORAGE_KEY_ENTITIES = 'entities';
// Key for loaded cache options
// Key for loaded attributes by attribute loaders
const STORAGE_KEY_ATTRIBUTES = 'attributes';
// Key for loaded cache options
const STORAGE_KEY_CACHE_OPTIONS = 'cache_options';
// Key for created scope models
const STORAGE_KEY_SCOPE = 'scope';
......@@ -266,6 +275,16 @@ class EcomDev_PHPUnit_Model_Fixture
return $this->getScope() === self::SCOPE_LOCAL;
}
/**
* Check that current fixture scope is equal to SCOPE_DEFAULT
*
* @return boolean
*/
public function isScopeDefault()
{
return $this->getScope() === self::SCOPE_DEFAULT;
}
/**
* Loads fixture files from test case annotations
*
......@@ -278,10 +297,10 @@ class EcomDev_PHPUnit_Model_Fixture
'loadFixture',
array('class', 'method')
);
$cacheOptions = $testCase->getAnnotationByName('cache', 'method');
$this->_parseCacheOptions($cacheOptions);
$this->_loadFixtureFiles($fixtures, $testCase);
......@@ -312,16 +331,16 @@ class EcomDev_PHPUnit_Model_Fixture
$cacheOptions = $method->invokeArgs(
null, array($className, 'cache', 'class')
);
$this->_parseCacheOptions($cacheOptions);
$this->_loadFixtureFiles($fixtures, $className);
return $this;
}
/**
* Loads test case cache on off annotations
*
*
* @param array $annotations
* @return EcomDev_PHPUnit_Model_Fixture
*/
......@@ -338,9 +357,9 @@ class EcomDev_PHPUnit_Model_Fixture
} else {
$cacheOptions[$cacheType] = $flag;
}
}
if ($cacheOptions) {
$this->_fixture['cache_options'] = $cacheOptions;
}
......@@ -422,7 +441,7 @@ class EcomDev_PHPUnit_Model_Fixture
}
}
// Clear fixture for getting rid of duoble processing
// Clear fixture for getting rid of double processing
$this->_fixture = array();
return $this;
}
......@@ -452,10 +471,10 @@ class EcomDev_PHPUnit_Model_Fixture
$this->_fixture = array();
}
/**
* Applies cache options for current test or test case
*
*
* @param array $options
* @return EcomDev_PHPUnit_Model_Fixture
*/
......@@ -463,16 +482,16 @@ class EcomDev_PHPUnit_Model_Fixture
{
$originalOptions = Mage::app()->getCacheOptions();
$this->setStorageData(self::STORAGE_KEY_CACHE_OPTIONS, $originalOptions);
$options += $originalOptions;
Mage::app()->setCacheOptions($options);
return $this;
}
/**
* Discards changes that were made to Magento cache
*
*
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardCacheOptions()
......@@ -696,7 +715,26 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected function _getEavLoader($entityType)
{
$loaders = Mage::getConfig()->getNode(self::XML_PATH_FIXTURE_EAV_LOADERS);
return $this->_getComplexLoader($entityType, 'EAV');
}
/**
* Retrieves the loader for a particular entity type and data type
*
* @throws InvalidArgumentException
* @param string $entityType
* @param string $dataType
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture
*/
protected function _getComplexLoader($entityType, $dataType)
{
if(!$dataType) {
throw new InvalidArgumentException('Must specify a data type for the loader');
}
$reflection = EcomDev_Utils_Reflection::getRelflection($this);
$loaders = Mage::getConfig()->getNode($reflection->getConstant("XML_PATH_FIXTURE_{$dataType}_LOADERS"));
if (isset($loaders->$entityType)) {
$classAlias = (string)$loaders->$entityType;
......@@ -720,7 +758,7 @@ class EcomDev_PHPUnit_Model_Fixture
if (!is_array($entities)) {
throw new InvalidArgumentException('EAV part should be an associative list with rows as value and entity type as key');
}
$this->getResource()->beginTransaction();
foreach ($entities as $entityType => $values) {
......@@ -760,7 +798,7 @@ class EcomDev_PHPUnit_Model_Fixture
$this->_getEavLoader($entityType)
->cleanEntity($entityType);
}
$this->getResource()->commit();
return $this;
......@@ -906,4 +944,102 @@ class EcomDev_PHPUnit_Model_Fixture
return $this;
}
/**
* Retrieves attribute loader for a particular entity type
*
* @param string $entityType
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Abstract
*/
protected function _getAttributeLoader($entityType)
{
return $this->_getComplexLoader($entityType, 'ATTRIBUTE');
}
/**
* Applies fixture EAV attribute values
*/
protected function _applyAttributes($attributes)
{
if (!is_array($attributes)) {
throw new InvalidArgumentException(
'Attributes part should be an associative list with rows as value and attribute code as key'
);
}
if (!$this->getStorageData(self::STORAGE_KEY_ATTRIBUTES, self::SCOPE_DEFAULT)) {
// since attributes are being used, we need to load all previously-existing
// attributes into default scope
$ignoreCleanup = array();
foreach(array_keys($attributes) as $entityType) {
$ignoreCleanup[$entityType] = $this->_getAttributeLoader(self::DEFAULT_SHARED_FIXTURE_NAME)
->setFixture($this)
->setOptions($this->_options)
->loadDefaultAttributes($entityType);
}
$this->setStorageData(self::STORAGE_KEY_ATTRIBUTES, $ignoreCleanup, self::SCOPE_DEFAULT);
}
$this->getResource()->beginTransaction();
foreach ($attributes as $entityType => $values) {
$this->_getAttributeLoader($entityType)
->setFixture($this)
->setOptions($this->_options)
->loadAttribute($entityType, $values);
}
$this->getResource()->commit();
$this->setStorageData(self::STORAGE_KEY_ATTRIBUTES, $attributes);
return $this;
}
/**
* Clean applied attribute data
*
* @param array $attributes
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardAttributes($attributes)
{
// Ignore cleaning of attributes if they existed before fixtures were loaded
$ignoreCleanUp = $this->getStorageData(self::STORAGE_KEY_ATTRIBUTES, self::SCOPE_DEFAULT);
if($ignoreCleanUp === null) $ignoreCleanUp = array();
// Ignore cleaning of attributes if shared fixture loaded something for them
if ($this->isScopeLocal() && $this->getStorageData(self::STORAGE_KEY_ATTRIBUTES, self::SCOPE_SHARED)) {
$ignoreCleanUp = array_merge_recursive(
$ignoreCleanUp,
$this->getStorageData(self::STORAGE_KEY_ENTITIES, self::SCOPE_SHARED)
);
}
$this->getResource()->beginTransaction();
foreach ($attributes as $entityType => $values) {
$attributeCodes = array();
foreach ($values as $value) {
if (isset($value['attribute_code'])
&& !in_array($value['attribute_code'], $ignoreCleanUp[$entityType])) {
$attributeCodes[] = $value['attribute_code'];
}
}
if (!empty($attributeCodes)) {
$this->_getAttributeLoader(self::DEFAULT_SHARED_FIXTURE_NAME)
->cleanAttributes($entityType, $attributeCodes);
}
}
$this->getResource()->commit();
foreach (array_keys($attributes) as $entityType) {
$this->_getAttributeLoader(self::DEFAULT_SHARED_FIXTURE_NAME)->resetAttributesAutoIncrement($entityType);
}
$this->_getAttributeLoader(self::DEFAULT_SHARED_FIXTURE_NAME)->resetAttributesAutoIncrement();
return $this;
}
}
......@@ -25,8 +25,12 @@
*/
interface EcomDev_PHPUnit_Model_Fixture_Interface extends EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/** Local scope - used for fixtures that apply only to the current test */
const SCOPE_LOCAL = 'local';
/** Shared scope - used for fixtures that apply to the current test class */
const SCOPE_SHARED = 'shared';
/** Default scope - used for storing data that exists in database before tests are run */
const SCOPE_DEFAULT = 'default';
/**
* Sets fixture options
......@@ -84,6 +88,14 @@ interface EcomDev_PHPUnit_Model_Fixture_Interface extends EcomDev_PHPUnit_Model_
*/
public function setScope($scope);
/**
* Check that current fixture scope is equal to SCOPE_DEFAULT
*
* @abstract
* @return boolean
*/
public function isScopeDefault();
/**
* Check that current fixture scope is equal to SCOPE_SHARED
*
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2012 EcomDev BV (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
* @author Steve Rice <srice@endertech.com>
*/
abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Abstract
extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Complex_Abstract
{
protected $_setupModel = 'Mage_Eav_Model_Entity_Setup';
/**
* @param string $entityType
* @return array
*/
public function loadDefaultAttributes($entityType)
{
/** @var $eavConfig Mage_Eav_Model_Config */
$eavConfig = Mage::getSingleton('eav/config');
$attributeCodes = $eavConfig->getEntityAttributeCodes($entityType);
return $attributeCodes;
}
/**
* Loads EAV attribute into DB tables
*
* @throws UnexpectedValueException
* @throws InvalidArgumentException
* @param string $entityType
* @param array $values
*/
public function loadAttribute($entityType, $values)
{
/** @var $eavConfig Mage_Eav_Model_Config */
$eavConfig = Mage::getSingleton('eav/config');
/** @var $entityTypeModel Mage_Eav_Model_Entity_Type */
$entityTypeModel = $eavConfig->getEntityType($entityType);
$entityModel = $entityTypeModel->getEntity();
//use entity model to figure out setup class
$entityReflection = EcomDev_Utils_Reflection::getRelflection($entityModel);
$classArray = explode('_', $entityReflection->getName());
$moduleName = $classArray[0] . '_' . $classArray[1];
$eavSetupModel = $this->_getSetupModelForModule($moduleName);
foreach ($values as $value) {
if (!isset($value['attribute_code'])) {
throw new InvalidArgumentException('Attribute definition must contain attribute_code');
}
/** @var $eavSetupModel Mage_Eav_Model_Entity_Setup */
$eavSetupModel->addAttribute($entityTypeModel->getEntityTypeCode(), $value['attribute_code'], $value);
}
}
/**
* Remove fixture-generated attributes from database
*
* @param string $entityType
* @param array $attributeCodes
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Abstract
* @throws EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception
*/
public function cleanAttributes($entityType, array $attributeCodes)
{
$eavSetup = new Mage_Eav_Model_Entity_Setup('core_setup');
try {
//delete entry from eav/attribute and allow FK cascade to delete all related values
$this->_getWriteAdapter()
->delete(
$this->getTable('eav/attribute'),
array(
'entity_type_id = ?' => $eavSetup->getEntityTypeId($entityType),
'attribute_code IN (?)' => $attributeCodes,
)
);
$this->_getWriteAdapter()->commit();
} catch (Exception $e) {
throw new EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception(
sprintf('Unable to clear records for a table "%s"', 'eav/attribute'),
$e
);
}
return $this;
}
/**
* Reset autoincrement value of all EAV attribute tables or those associated with an entity type
*
* @throws EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception
* @param string $entityType
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Abstract
*/
public function resetAttributesAutoIncrement($entityType = null)
{
//@TODO track which tables are altered
if ($entityType !== null) {
/** @var $eavConfig Mage_Eav_Model_Config */
$eavConfig = Mage::getSingleton('eav/config');
/** @var $entityTypeModel Mage_Eav_Model_Entity_Type */
$entityTypeModel = $eavConfig->getEntityType($entityType);
$this->resetTableAutoIncrement($entityTypeModel->getAdditionalAttributeTable());
} else {
//@TODO don't hardcode these
$this->resetTableAutoIncrement('eav/attribute');
$this->resetTableAutoIncrement('eav/attribute_set');
$this->resetTableAutoIncrement('eav/attribute_group');
$this->resetTableAutoIncrement('eav/attribute_label');
$this->resetTableAutoIncrement('eav/attribute_option');
$this->resetTableAutoIncrement('eav/attribute_option_value');
}
return $this;
}
/**
* Reset autoincrement value of a table
*
* @param string $table
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Abstract
* @throws EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception
*/
public function resetTableAutoIncrement($table)
{
try {
//reset table auto_increment to maximum value in table
$this->_getWriteAdapter()->query("ALTER TABLE `{$this->getTable($table)}` AUTO_INCREMENT = 1");
} catch (Exception $e) {
throw new EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception(
sprintf('Unable to reset autoincrement for table "%s"', $table),
$e
);
}
return $this;
}
/**
* Get the setup model used by a Magento module
*
* @param $moduleName
* @return mixed
* @throws UnexpectedValueException
*/
protected function _getSetupModelForModule($moduleName)
{
$resources = Mage::getConfig()->getNode('global/resources')->children();
$resourceName = 'eav_setup';
$className = 'Mage_Eav_Model_Entity_Setup';
foreach ($resources as $resName => $resource) {
if (!$resource->setup) {
continue;
}
if (isset($resource->setup->module) && $resource->setup->module == $moduleName
&& isset($resource->setup->class)) {
$className = $resource->setup->getClassName();
$resourceName = $resName;
break;
}
}
$setupModel = new $className($resourceName);
$setupReflection = EcomDev_Utils_Reflection::getRelflection($setupModel);
if (!$setupReflection->hasMethod('addAttribute')) {
throw new UnexpectedValueException('Problem loading EAV setup model');
}
return $setupModel;
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2012 EcomDev BV (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
* @author Steve Rice <srice@endertech.com>
*/
class EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Default
extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Attribute_Abstract
{
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2012 EcomDev BV (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
* @author Steve Rice <srice@endertech.com>
*/
abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Complex_Abstract extends EcomDev_PHPUnit_Model_Mysql4_Fixture
{
/**
* Fixture options
*
* @var array
*/
protected $_options = array();
/**
* Fixture model
*
* @var EcomDev_PHPUnit_Model_Fixture_Interface
*/
protected $_fixture = null;
/**
* Inject fixture model into complex loader
*
* @param EcomDev_PHPUnit_Model_Fixture_Interface $fixture
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Complex_Abstract
*/
public function setFixture($fixture)
{
$this->_fixture = $fixture;
return $this;
}
/**
* Set fixture options
*
* @param array $options
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Complex_Abstract
*/
public function setOptions(array $options)
{
$this->_options = $options;
return $this;
}
}
......@@ -20,7 +20,8 @@
* Base implementation of EAV fixtures loader
*
*/
abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev_PHPUnit_Model_Mysql4_Fixture
abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract
extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Complex_Abstract
{
/**
* List of indexers required to build
......@@ -29,20 +30,6 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
*/
protected $_requiredIndexers = array();
/**
* Fixture options
*
* @var array
*/
protected $_options = array();
/**
* Fixture model
*
* @var EcomDev_PHPUnit_Model_Fixture_Interface
*/
protected $_fixture = null;
/**
* Retrieve required indexers for re-building
*
......@@ -53,29 +40,6 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
return $this->_requiredIndexers;
}
/**
* Sets fixture model to EAV loader
*
* @param EcomDev_PHPUnit_Model_Fixture_Interface $fixture
*/
public function setFixture($fixture)
{
$this->_fixture = $fixture;
return $this;
}
/**
* Set fixture options
*
* @param array $options
* @return EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract
*/
public function setOptions(array $options)
{
$this->_options = $options;
return $this;
}
/**
* Add indexer by specific code to required indexers list
*
......@@ -98,6 +62,7 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
*/
public function cleanEntity($entityType)
{
/** @var $entityTypeModel Mage_Eav_Model_Entity_Type */
$entityTypeModel = Mage::getSingleton('eav/config')->getEntityType($entityType);
$this->cleanTable($entityTypeModel->getEntityTable());
return $this;
......@@ -123,6 +88,7 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
}
}
/** @var $entityTypeModel Mage_Eav_Model_Entity_Type */
$entityTypeModel = Mage::getSingleton('eav/config')->getEntityType($entityType);
......@@ -160,12 +126,13 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
// Preparing simple attributes records
foreach ($entityTypeModel->getAttributeCollection() as $attribute) {
/** @var $attribute Mage_Eav_Model_Entity_Attribute */
$attributeBackendTable = $attribute->getBackendTable();
if (!$attribute->isStatic()
&& $attributeBackendTable
&& isset($attributeTableColumns[$attributeBackendTable])) {
// Prepearing data for insert per attribute table
// Preparing data for insert per attribute table
$attributeRecords = $this->_getAttributeRecords(
$row,
$attribute,
......
......@@ -70,9 +70,15 @@
<fixture>
<!-- Default model for loading of fixtures -->
<model>ecomdev_phpunit/fixture</model>
<attribute>
<!-- Fixture loaders for EAV attributes
Default can be used but does not support extra attribute table configuration -->
<default>ecomdev_phpunit/fixture_attribute_default</default>
<!--<catalog_product>ecomdev_phpunit/fixture_attribute_catalog_product</catalog_product>-->
</attribute>
<eav>
<!-- Here goes the list of fixture loaders for EAV
If no fixture loader is specified for entity, then default will be used
If no fixture loader is specified for entity, then default will be used
-->
<default>ecomdev_phpunit/fixture_eav_default</default>
<catalog_product>ecomdev_phpunit/fixture_eav_catalog_product</catalog_product>
......@@ -101,9 +107,9 @@
</controller>
<modules>
<!-- Place your module name in your module config.xml
<!-- Place your module name in your module config.xml
For adding it to test suite -->
<!-- Example:
<!-- Example:
<Namespace_MyModule />
-->
</modules>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment