Commit 350ca36f authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

! Merged trunk into QA

parents fd93125f c03bbe26
...@@ -56,6 +56,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -56,6 +56,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
*/ */
protected static $_oldEventCollection = null; protected static $_oldEventCollection = null;
/**
* List of singletons in original application
*
* @var array
*/
protected static $_oldRegistry = null;
/** /**
* Configuration model class name for unit tests * Configuration model class name for unit tests
* *
...@@ -77,6 +84,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -77,6 +84,13 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
*/ */
protected static $_cacheClass = 'EcomDev_PHPUnit_Model_Cache'; protected static $_cacheClass = 'EcomDev_PHPUnit_Model_Cache';
/**
* Enabled events flag
*
* @var boolean
*/
protected $_eventsEnabled = true;
/** /**
* This method replaces application, event and config objects * This method replaces application, event and config objects
* in Mage to perform unit tests in separate Magento steam * in Mage to perform unit tests in separate Magento steam
...@@ -88,15 +102,14 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -88,15 +102,14 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
self::$_oldApplication = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_app'); self::$_oldApplication = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_app');
self::$_oldConfig = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_config'); self::$_oldConfig = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_config');
self::$_oldEventCollection = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_events'); self::$_oldEventCollection = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_events');
self::$_oldEventCollection = EcomDev_Utils_Reflection::getRestrictedPropertyValue('Mage', '_registry');
$resource = Mage::getSingleton('core/resource');
// Setting environment variables for unit tests // Setting environment variables for unit tests
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_config', new self::$_configClass); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_config', new self::$_configClass);
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_app', new self); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_app', new self);
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_events', new self::$_eventCollectionClass); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_events', new self::$_eventCollectionClass);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($resource, '_connections', array()); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_registry', array());
// All unit tests will be runned in admin scope, to get rid of frontend restrictions // All unit tests will be runned in admin scope, to get rid of frontend restrictions
Mage::app()->initTest(); Mage::app()->initTest();
...@@ -113,7 +126,22 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -113,7 +126,22 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
$this->_config->setOptions($options); $this->_config->setOptions($options);
$this->_initBaseConfig(); $this->_initBaseConfig();
$this->_initCache(); $this->_initCache();
// Set using cache
// for things that shouldn't be reloaded each time
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$this->_cache,
'_allowedCacheOptions',
array(
'eav' => 1,
'layout' => 1,
'translate' => 1
)
);
// Clean cache before the whole suite is running
$this->getCache()->clean(); $this->getCache()->clean();
// Init modules runs install proccess for table structures, // Init modules runs install proccess for table structures,
// It is required for setting up proper setup script // It is required for setting up proper setup script
$this->_initModules(); $this->_initModules();
...@@ -127,6 +155,18 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -127,6 +155,18 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
return $this; return $this;
} }
/**
* Overriden to fix issue with stores loading
* (non-PHPdoc)
* @see Mage_Core_Model_App::_initStores()
*/
protected function _initStores()
{
$this->_store = null;
parent::_initStores();
return $this;
}
/** /**
* Discard test scope for application, returns all the objects from live version * Discard test scope for application, returns all the objects from live version
* *
...@@ -137,18 +177,44 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -137,18 +177,44 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_app', self::$_oldApplication); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_app', self::$_oldApplication);
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_config', self::$_oldConfig); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_config', self::$_oldConfig);
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_events', self::$_oldEventCollection); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_events', self::$_oldEventCollection);
$resource = Mage::getSingleton('core/resource'); EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_registry', self::$_oldRegistry);
EcomDev_Utils_Reflection::setRestrictedPropertyValue($resource, '_connections', array());
} }
/** /**
* We will not use cache for UnitTests * Disables events fire
* *
* @return boolean * @return EcomDev_PHPUnit_Model_App
*/ */
public function useCache($type=null) public function disableEvents()
{ {
return false; $this->_eventsEnabled = false;
return $this;
}
/**
* Enable events fire
*
* @return EcomDev_PHPUnit_Model_App
*/
public function enableEvents()
{
$this->_eventsEnabled = true;
return $this;
} }
/**
* Overriden for disabling events
* fire during fixutre loading
*
* (non-PHPdoc)
* @see Mage_Core_Model_App::dispatchEvent()
*/
public function dispatchEvent($eventName, $args)
{
if ($this->_eventsEnabled) {
parent::dispatchEvent($eventName, $args);
}
return $this;
}
} }
...@@ -23,6 +23,77 @@ ...@@ -23,6 +23,77 @@
*/ */
class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
{ {
/**
* Scope snapshot without applied configurations,
* It is used for proper store/website/default loading on per store basis
*
* @var Mage_Core_Model_Config_Base
*/
protected $_scopeSnapshot = null;
/**
* Load config data from DB
*
* @return Mage_Core_Model_Config
*/
public function loadDb()
{
if ($this->_isLocalConfigLoaded
&& Mage::isInstalled()
&& $this->_scopeSnapshot === null) {
$this->saveScopeSnapshot();
}
parent::loadDb();
return $this;
}
/**
* Loads scope snapshot
*
* @return EcomDev_PHPUnit_Model_Config
*/
public function loadScopeSnapshot()
{
if ($this->_scopeSnapshot === null) {
throw new RuntimeException('Cannot load scope snapshot, because it was not saved before');
}
$scopeNode = $this->_scopeSnapshot->getNode();
foreach ($scopeNode->children() as $nodeName => $values) {
// Remove somehow modified before xml node
unset($this->getNode()->$nodeName);
// Add saved snapshot of configuration node
$this->getNode()->addChild($nodeName);
$this->getNode()->$nodeName->extend($values);
}
return $this;
}
/**
* Saves current configuration snapshot,
* for pussible restoring in feature
*
* @param array $nodesToSave list of nodes for saving data, by default it is 'default', 'webistes', 'stores'
* @return EcomDev_PHPUnit_Model_Config
*/
public function saveScopeSnapshot($nodesToSave = array('default', 'websites', 'stores'))
{
$this->_scopeSnapshot = clone $this->_prototype;
$this->_scopeSnapshot->loadString('<config />');
$scopeNode = $this->_scopeSnapshot->getNode();
foreach ($nodesToSave as $node) {
$scopeNode->addChild($node);
$scopeNode->{$node}->extend(
$this->getNode($node),
true
);
}
return $this;
}
/** /**
* Loads additional configuration for unit tests * Loads additional configuration for unit tests
* (non-PHPdoc) * (non-PHPdoc)
......
<?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) 2011 Ecommerce Developers (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>
*/
/**
* Base Catalog EAV fixture loader
*
*
*/
abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Abstract extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract
{
const SCOPE_TYPE_STORE = 'stores';
const SCOPE_TYPE_WEBSITE = 'websites';
/**
* Overriden to add GWS implementation for attribute records
*
* @param array $row
* @param Mage_Catalog_Model_Resource_Eav_Attribute $attribute
* @param array $tableColumns
* @return array
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::_getAttributeRecords()
*/
protected function _getAttributeRecords($row, $attribute, $tableColumns)
{
$records = parent::_getAttributeRecords($row, $attribute, $tableColumns);
// If the attribute is not global,
// then walk over all websites and stores scopes for attribute value
if ($attribute->isScopeStore() || $attribute->isScopeWebsite()) {
// Search for website values and fullfil data per website's store
$storeValues = array();
foreach ($this->_getGwsCodes($row, self::SCOPE_TYPE_WEBSITE) as $websiteCode) {
$website = Mage::app()->getWebsite($websiteCode);
$value = $this->_getGwsValue($row, $attribute, $websiteCode, self::SCOPE_TYPE_WEBSITE);
if ($value !== null) {
foreach ($website->getStoreIds() as $storeId) {
$storeValues[$storeId] = $value;
}
}
}
// If attribute has store scope, then override website values by store ones
if ($attribute->isScopeStore()) {
foreach ($this->_getGwsCodes($row, self::SCOPE_TYPE_STORE) as $storeCode) {
$store = Mage::app()->getStore($storeCode);
$value = $this->_getGwsValue($row, $attribute, $storeCode, self::SCOPE_TYPE_STORE);
if ($value !== null) {
$storeValues[$store->getId()] = $value;
}
}
}
// Apply collected values
$valueInfo = $this->_getAttributeValueInfo($row, $attribute);
foreach ($storeValues as $storeId => $value) {
$valueInfo['store_id'] = $storeId;
$valueInfo['value'] = $value;
$records[] = $this->_getTableRecord($valueInfo, $tableColumns);
}
}
return $records;
}
/**
* Check is available store/website values
*
* @param array $row
* @param string $scopeType
* @return boolean
*/
protected function _hasGwsValues($row, $scopeType = self::SCOPE_TYPE_STORE)
{
return isset($row['/' . $scopeType]);
}
/**
* Retrieves list of websites/stores codes
*
* @param array $row
* @param string $scopeType
*/
protected function _getGwsCodes($row, $scopeType = self::SCOPE_TYPE_STORE)
{
if (!$this->_hasGwsValues($row, $scopeType)) {
return array();
}
return array_keys($row['/' . $scopeType]);
}
/**
* Retrieves scope dependent value from fixture value, i.e,
* store view or
* website attribute value
*
*
* @param array $row
* @param Mage_Eav_Model_Entity_Attribute $attribute
* @param string $scopeCode
* @param string $scopeType
* @return mixed|null
*/
protected function _getGwsValue($row, $attribute, $scopeCode, $scopeType = self::SCOPE_TYPE_STORE)
{
if (!isset($row['/' . $scopeType][$scopeCode]) || !is_array($row['/' . $scopeType][$scopeCode])) {
return null;
}
return $this->_getAttributeValue($row['/' . $scopeType][$scopeCode], $attribute);
}
/**
* Overriden to add default store id
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::_getAttributeValueInfo()
*/
protected function _getAttributeValueInfo($row, $attribute)
{
$info = parent::_getAttributeValueInfo($row, $attribute);
$info['store_id'] = 0;
return $info;
}
}
<?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) 2011 Ecommerce Developers (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>
*/
/**
* Category EAV fixture loader
*
*
*/
class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Category extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Abstract
{
protected $_requiredIndexers = array(
'catalog_category_flat'
);
/**
* Overriden to add easy fixture loading for product associations
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::_getCustomTableRecords()
*/
protected function _getCustomTableRecords($row, $entityTypeModel)
{
return $this->_getProductAssociationRecords($row, $entityTypeModel);
}
/**
* Generates records for catalog_category_product table
*
* @param array $row
* @param Mage_Eav_Model_Entity_Type $entityTypeModel
* @return array
*/
protected function _getProductAssociationRecords($row, $entityTypeModel)
{
if (isset($row['products']) && is_array($row['products'])) {
$records = array();
foreach ($row['products'] as $productId => $position) {
$records[] = array(
'category_id' => $row[$this->_getEntityIdField($entityTypeModel)],
'product_id' => $productId,
'position' => $position
);
}
if ($records) {
$this->addRequiredIndexer('catalog_category_product');
return array('catalog/category_product' => $records);
}
}
return array();
}
}
\ No newline at end of file
<?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) 2011 Ecommerce Developers (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>
*/
/**
* Product EAV fixture loader
*
*
*/
class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Product extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Abstract
{
protected $_requiredIndexers = array(
'cataloginventory_stock',
'catalog_product_flat',
'catalog_product_attribute',
'catalog_product_price'
);
/**
* Ovveriden to fix issue with flat tables existance mark
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::loadEntity()
*/
public function loadEntity($entityType, $values)
{
// Fix of Product Flat Indexer
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
Mage::getResourceSingleton('catalog/product_flat_indexer'),
'_existsFlatTables',
array()
);
return parent::loadEntity($entityType, $values);
}
/**
* Overriden to add easy fixture loading for websites and categories associations
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::_getCustomTableRecords()
*/
protected function _getCustomTableRecords($row, $entityTypeModel)
{
$records = array();
$records += $this->_getWebsiteVisibilityRecords($row, $entityTypeModel);
$records += $this->_getTierPriceRecords($row, $entityTypeModel);
$records += $this->_getCategoryAssociationRecords($row, $entityTypeModel);
$records += $this->_getProductStockRecords($row, $entityTypeModel);
return $records;
}
/**
* Changed to support price attribute type multi-scope
* (non-PHPdoc)
* @param Mage_Eav_Model_Entity_Attribute $attribute
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Abstract::_getAttributeRecords()
*/
protected function _getAttributeRecords($row, $attribute, $tableColumns)
{
if ($attribute->getFrontendInput() == 'price') {
$attribute->setIsGlobal(
Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE
);
}
return parent::_getAttributeRecords($row, $attribute, $tableColumns);
}
/**
* Generates records for catalog_product_website table
*
* @param array $row
* @param Mage_Eav_Model_Entity_Type $entityTypeModel
* @return array
* @throws RuntimeException
*/
protected function _getWebsiteVisibilityRecords($row, $entityTypeModel)
{
if (isset($row['website_ids']) && is_array($row['website_ids'])) {
$records = array();
foreach ($row['website_ids'] as $websiteId) {
$website = Mage::app()->getWebsite($websiteId);
$records[] = array(
'product_id' => $row[$this->_getEntityIdField($entityTypeModel)],
'website_id' => $website->getId()
);
}
// We shouldn't return empty table data
if ($records) {
return array('catalog/product_website' => $records);
}
}
return array();
}
/**
* Generates records for catalog_product_entity_tier_price table
*
* @param array $row
* @param Mage_Eav_Model_Entity_Type $entityTypeModel
* @return array
*/
protected function _getTierPriceRecords($row, $entityTypeModel)
{
if (isset($row['tier_price']) && is_array($row['tier_price'])) {
$tableName = $entityTypeModel->getValueTablePrefix() . '_tier_price';
$columns = $this->_getWriteAdapter()->describeTable(
$tableName
);
$records = array();
foreach ($row['tier_price'] as $tierPrice) {
$tierPrice[$this->_getEntityIdField($entityTypeModel)] = $row[$this->_getEntityIdField($entityTypeModel)];
$records[] = $this->_getTableRecord($tierPrice, $columns);
}
if ($records) {
return array($tableName => $records);
}
}
return array();
}
/**
* Generates records for catalog_category_product table
*
* @param array $row
* @param Mage_Eav_Model_Entity_Type $entityTypeModel
* @return array
*/
protected function _getCategoryAssociationRecords($row, $entityTypeModel)
{
if (isset($row['category_ids']) && is_array($row['category_ids'])) {
$records = array();
foreach ($row['category_ids'] as $categoryId) {
$records[] = array(
'category_id' => $categoryId,
'product_id' => $row[$this->_getEntityIdField($entityTypeModel)]
);
}
if ($records) {
$this->addRequiredIndexer('catalog_category_product');
return array('catalog/category_product' => $records);
}
}
return array();
}
/**
* Generates records for cataloginventory_stock_item table
*
* @param array $row
* @param Mage_Eav_Model_Entity_Type $entityTypeModel
* @return array
*/
protected function _getProductStockRecords($row, $entityTypeModel)
{
if (isset($row['stock']) && is_array($row['stock'])) {
$columns = $this->_getWriteAdapter()->describeTable(
$this->getTable('cataloginventory/stock_item')
);
$row['stock']['product_id'] = $row[$this->_getEntityIdField($entityTypeModel)];
if (!isset($row['stock']['stock_id'])) {
$row['stock']['stock_id'] = 1;
}
return array(
'cataloginventory/stock_item' => array(
$this->_getTableRecord($row['stock'], $columns)
)
);
}
return array();
}
/**
* Adding enabled and visibility indexes
*
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::_customEntityAction()
*/
protected function _customEntityAction($entity, $entityTypeModel)
{
Mage::getResourceSingleton('catalog/product_status')
->refreshEnabledIndex($entity[$this->_getEntityIdField($entityTypeModel)], 0);
parent::_customEntityAction($entity, $entityTypeModel);
return $this;
}
}
\ No newline at end of file
<?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) 2011 Ecommerce Developers (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>
*/
/**
* Default EAV fixture loaded
*
*
*/
class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Default extends EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract
{
}
\ No newline at end of file
...@@ -34,6 +34,14 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -34,6 +34,14 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/ */
protected $_expectations = null; protected $_expectations = null;
/**
* Original store kept for tearDown,
* if was set in test method
*
* @var Mage_Core_Model_Store
*/
protected $_originalStore = null;
/** /**
* Loads expectations for current test case * Loads expectations for current test case
* *
...@@ -78,9 +86,29 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -78,9 +86,29 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$this->_expectations = new Varien_Object($expectations); $this->_expectations = new Varien_Object($expectations);
} }
$arguments = func_get_args();
if ($arguments) {
if (count($arguments) > 1) {
$dataKey = call_user_func_array('sprintf', $arguments);
} else {
$dataKey = array_shift($arguments);
}
$dataPart = $this->_expectations->getData($dataKey);
if (!is_array($dataPart)) {
throw new InvalidArgumentException(
'Argument values for specifying special scope of expectations should be presented '
. ' in expectation file and should be an associative list (dataKey: "' . $dataKey . '")'
);
}
return new Varien_Object($dataPart);
}
return $this->_expectations; return $this->_expectations;
} }
/** /**
* Retrieves fixture model singleton * Retrieves fixture model singleton
* *
...@@ -148,7 +176,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -148,7 +176,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$this->_getFixture()->loadYaml($filePath); $this->_getFixture()->loadYaml($filePath);
} }
} }
// Pass methods for
$this->_getFixture()->setOptions($annotations['method']);
$this->_getFixture()->apply(); $this->_getFixture()->apply();
parent::setUp(); parent::setUp();
} }
...@@ -172,6 +201,24 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -172,6 +201,24 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
return Spyc::YAMLLoad($filePath); return Spyc::YAMLLoad($filePath);
} }
/**
* Set current store scope for test
*
* @param int|string|Mage_Core_Model_Store $store
* @return EcomDev_PHPUnit_Test_Case
*/
public function setCurrentStore($store)
{
if (!$this->_originalStore) {
$this->_originalStore = Mage::app()->getStore();
}
Mage::app()->setCurrentStore(
Mage::app()->getStore($store)
);
return $this;
}
/** /**
* Performs a clean up after a particular test was run * Performs a clean up after a particular test was run
* (non-PHPdoc) * (non-PHPdoc)
...@@ -179,6 +226,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -179,6 +226,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/ */
protected function tearDown() protected function tearDown()
{ {
if ($this->_originalStore) { // Remove store scope, that was set in test
Mage::app()->setCurrentStore($this->_originalStore);
$this->_originalStore = null;
}
$this->_expectations = null; // Clear expectation values $this->_expectations = null; // Clear expectation values
$this->_getFixture()->discard(); // Clear applied fixture $this->_getFixture()->discard(); // Clear applied fixture
parent::tearDown(); parent::tearDown();
......
...@@ -29,6 +29,8 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite ...@@ -29,6 +29,8 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
const XML_PATH_UNIT_TEST_GROUPS = 'phpunit/suite/groups'; const XML_PATH_UNIT_TEST_GROUPS = 'phpunit/suite/groups';
const XML_PATH_UNIT_TEST_MODULES = 'phpunit/suite/modules'; const XML_PATH_UNIT_TEST_MODULES = 'phpunit/suite/modules';
const XML_PATH_UNIT_TEST_APP = 'phpunit/suite/app'; const XML_PATH_UNIT_TEST_APP = 'phpunit/suite/app';
const CACHE_TAG = 'ECOMDEV_PHPUNIT';
const CACHE_TYPE = 'ecomdev_phpunit';
/** /**
* Setting up test scope for Magento * Setting up test scope for Magento
...@@ -86,15 +88,52 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite ...@@ -86,15 +88,52 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
continue; continue;
} }
$directoryIterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($searchPath)
);
$currentGroups = array( $currentGroups = array(
$group->getName(), $group->getName(),
$module->getName() $module->getName()
); );
$testCases = self::_loadTestCases($searchPath, $moduleCodeDir);
foreach ($testCases as $className) {
$classReflection = EcomDev_Utils_Reflection::getRelflection($className);
$suite->addTest(new PHPUnit_Framework_TestSuite($classReflection), $currentGroups);
}
}
}
if (!$suite->count()) {
$suite->addTest(self::warning('There were no test cases for the current run'));
}
return $suite;
}
/**
* Loads test cases from search path,
* Will return cached result
*
* @param string $searchPath path for searching files with tests
* @param string $moduleCodeDir path where the module files are placed (e.g. app/code/local),
* used for determining the class name
*/
protected static function _loadTestCases($searchPath, $moduleCodeDir)
{
if (Mage::app()->useCache(self::CACHE_TYPE)) {
$cachedTestCases = Mage::app()->loadCache(
self::CACHE_TYPE . md5($searchPath)
);
if ($cachedTestCases) {
return unserialize($cachedTestCases);
}
}
$testCases = array();
$directoryIterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($searchPath)
);
foreach ($directoryIterator as $fileObject) { foreach ($directoryIterator as $fileObject) {
/* @var $fileObject SplFileObject */ /* @var $fileObject SplFileObject */
// Skip entry if it is not a php file // Skip entry if it is not a php file
...@@ -102,30 +141,29 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite ...@@ -102,30 +141,29 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
continue; continue;
} }
$classPath = substr($fileObject->getPath() . DS . $fileObject->getBasename('.php'), strlen($moduleCodeDir)); $classPath = substr($fileObject->getPath() . DS . $fileObject->getBasename('.php'), strlen($moduleCodeDir));
$className = uc_words(ltrim($classPath, DS), '_', DS); $className = uc_words(ltrim($classPath, DS), '_', DS);
// Add unit test case only // Add unit test case only
// if it is a valid class extended from EcomDev_PHPUnit_Test_Case // if it is a valid class extended from EcomDev_PHPUnit_Test_Case
if (class_exists($className, true)) { if (class_exists($className, true)) {
$reflectionClass = EcomDev_Utils_Reflection::getRelflection($className); $reflectionClass = EcomDev_Utils_Reflection::getRelflection($className);
if (!$reflectionClass->isSubclassOf('EcomDev_PHPUnit_Test_Case')) { if (!$reflectionClass->isSubclassOf('EcomDev_PHPUnit_Test_Case')
|| $reflectionClass->isAbstract()) {
continue; continue;
} }
$testCases[] = $className;
$suite->addTest(new PHPUnit_Framework_TestSuite($reflectionClass), $currentGroups);
}
}
} }
} }
if (!$suite->count()) { if (Mage::app()->useCache(self::CACHE_TYPE)) {
$suite->addTest(self::warning('There were no test cases for the current run')); Mage::app()->saveCache(
serialize($testCases),
self::CACHE_TYPE . md5($searchPath),
array(self::CACHE_TAG)
);
} }
return $suite; return $testCases;
} }
} }
...@@ -33,6 +33,15 @@ ...@@ -33,6 +33,15 @@
<class>EcomDev_PHPUnit_Model_Mysql4</class> <class>EcomDev_PHPUnit_Model_Mysql4</class>
</ecomdev_phpunit_mysql4> </ecomdev_phpunit_mysql4>
</models> </models>
<cache>
<types>
<ecomdev_phpunit>
<label>Unit Test Cases</label>
<description>Unit test case file paths cache.</description>
<tags>ECOMDEV_PHPUNIT</tags>
</ecomdev_phpunit>
</types>
</cache>
</global> </global>
<phpunit> <phpunit>
<suite> <suite>
...@@ -42,6 +51,16 @@ ...@@ -42,6 +51,16 @@
<helpers>Helper</helpers> <helpers>Helper</helpers>
<blocks>Block</blocks> <blocks>Block</blocks>
</groups> </groups>
<fixture>
<eav>
<!-- Here goes the list of fixture loaders for EAV
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>
<catalog_category>ecomdev_phpunit/fixture_eav_catalog_category</catalog_category>
</eav>
</fixture>
<!-- Application model class name for running tests --> <!-- Application model class name for running tests -->
<app>EcomDev_PHPUnit_Model_App</app> <app>EcomDev_PHPUnit_Model_App</app>
<modules> <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