Commit d7fb0f16 authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

Merge branch 'dev'

parents 85757c0b 7ff0baed
......@@ -8,7 +8,7 @@ This extension was created especially for resolving this problem and promoting t
System Requirements
-------------------
* PHP 5.3 or higher
* PHPUnit 3.5
* PHPUnit 3.6.x
* Magento CE1.4.x-1.5.x/PE1.9.x-PE1.10.x/EE1.9.x-1.10.x
Documentation
......@@ -40,6 +40,8 @@ required for proper controller tests.
4. Run the unit tests first time for installing test database. It will take about 3 minutes.
$ phpunit UnitTests.php
5. If it shows that there was no tests found, it means that extension was successfully
installed. If it shows some errors than it means that your customizations has install
scripts that relay on your current database data so you should fix them.
......@@ -58,6 +60,8 @@ required for proper controller tests.
3. Run the unit tests first time for installing test database. It will take about 3 minutes.
$ phpunit UnitTests.php
4. If it shows that there was no tests found, it means that extension was successfully
installed. If it shows some errors than it means that your customizations has install
scripts that relay on your current database data so you should fix them.
......@@ -77,4 +81,4 @@ If you want to take a part in improving our extension please create branches bas
$ git checkout -b [your-name]/[feature] dev
Then submit them for pull request.
\ No newline at end of file
Then submit them for pull request.
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -48,6 +48,8 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
const REGISTRY_PATH_LAYOUT_SINGLETON = '_singleton/core/layout';
const REGISTRY_PATH_DESIGN_PACKAGE_SINGLETON = '_singleton/core/design_package';
const REGISTRY_PATH_SHARED_STORAGE = 'test_suite_shared_storage';
const XML_PATH_LAYOUT_MODEL_FOR_TEST = 'phpunit/suite/layout/model';
const XML_PATH_DESIGN_PACKAGE_MODEL_FOR_TEST = 'phpunit/suite/design/package/model';
......@@ -152,7 +154,7 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
EcomDev_Utils_Reflection::setRestrictedPropertyValue('Mage', '_events', new self::$_eventCollectionClass);
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 run in admin scope, to get rid of frontend restrictions
Mage::app()->initTest();
}
......@@ -177,20 +179,16 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// 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
)
);
$this->setCacheOptions(array(
'eav' => 1,
'layout' => 1,
'translate' => 1
));
// Clean cache before the whole suite is running
$this->getCache()->clean();
// Init modules runs install proccess for table structures,
// Init modules runs install process for table structures,
// It is required for setting up proper setup script
$this->_initModules();
......@@ -221,9 +219,39 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
$designPackageModel);
$this->loadAreaPart(self::AREA_TEST, self::AREA_PART_EVENTS);
$this->replaceRegistry(self::REGISTRY_PATH_SHARED_STORAGE, new Varien_Object());
return $this;
}
/**
* Sets cache options for test case
*
* @param array $options
* @return EcomDev_PHPUnit_Model_App
*/
public function setCacheOptions(array $options)
{
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$this->_cache,
'_allowedCacheOptions',
$options
);
}
/**
* Retrieve cache options for test case
*
* @return array
*/
public function getCacheOptions()
{
return EcomDev_Utils_Reflection::getRestrictedPropertyValue(
$this->_cache,
'_allowedCacheOptions'
);
}
/**
* Retrieves a model from config and checks it on interface implementation
*
......@@ -362,7 +390,7 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
/**
* Returns class name from configuration path,
* If $interface is specified, then it additionaly checks it for implementation
* If $interface is specified, then it additionally checks it for implementation
*
*
* @param string $configPath
......@@ -504,7 +532,7 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
/**
* Overriden for disabling events
* fire during fixutre loading
* fire during fixture loading
*
* (non-PHPdoc)
* @see Mage_Core_Model_App::dispatchEvent()
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -37,6 +37,7 @@ class EcomDev_PHPUnit_Model_App_Area
*/
public function reset()
{
$this->_loadedParts = array();
$this->resetEvents();
$this->resetDesign();
$this->resetTranslate();
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -28,12 +28,18 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
const CHANGE_ME = '[change me]';
/**
* Scope snapshot without applied configurations,
* It is used for proper store/website/default loading on per store basis
* Scope snapshot with different levels of saving configuration
*
* @var Mage_Core_Model_Config_Base
*/
protected $_scopeSnapshot = null;
protected $_scopeSnapshot = array();
/**
* Scope snapshot for a particular test case
*
* @var Mage_Core_Model_Config_Base
*/
protected $_localScopeSnapshot = null;
/**
* List of replaced instance creation
......@@ -51,7 +57,7 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
{
if ($this->_isLocalConfigLoaded
&& Mage::isInstalled()
&& $this->_scopeSnapshot === null) {
&& empty($this->_scopeSnapshot)) {
$this->saveScopeSnapshot();
}
parent::loadDb();
......@@ -141,43 +147,39 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
*/
public function loadScopeSnapshot()
{
if ($this->_scopeSnapshot === null) {
if (empty($this->_scopeSnapshot)) {
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);
}
$scope = clone end($this->_scopeSnapshot);
$this->_xml = $scope;
return $this;
}
/**
* Saves current configuration snapshot,
* for pussible restoring in feature
* Flushes current scope snapshot level if it is not the last one
*
* @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'))
public function flushScopeSnapshot()
{
$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
);
if (count($this->_scopeSnapshot) > 1) {
array_pop($this->_scopeSnapshot);
memory_get_usage(); // Memory GC
}
return $this;
}
/**
* Saves current configuration snapshot,
* for pussible restoring in feature
*
* @return EcomDev_PHPUnit_Model_Config
*/
public function saveScopeSnapshot()
{
$this->_scopeSnapshot[] = clone $this->_xml;
return $this;
}
......@@ -277,7 +279,7 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
echo sprintf(
'Please change values in %s file for nodes %s and %s. '
. 'It will help in setting up proper controller test cases',
'app/etc/local.phpunit', self::XML_PATH_SECURE_BASE_URL, self::XML_PATH_UNSECURE_BASE_URL
'app/etc/local.xml.phpunit', self::XML_PATH_SECURE_BASE_URL, self::XML_PATH_UNSECURE_BASE_URL
);
exit();
}
......
......@@ -30,6 +30,11 @@ class EcomDev_PHPUnit_Model_Design_Package
$this->setPackageName($designPackage);
$this->setTheme($theme);
$params = array(
'_area' => $area,
'_package' => $designPackage,
'_theme' => $theme,
);
$actualFileName = $this->getLayoutFilename($fileName, $params);
if ($theme !== null || $designPackage !== null) {
......@@ -41,7 +46,7 @@ class EcomDev_PHPUnit_Model_Design_Package
'_package' => $expectedDesignPackage
);
$expectedFileName = Mage::getBaseDir('design') . DS . $this->_renderFilename($fileName, $params);
$expectedFileName = $this->_renderFilename($fileName, $params);
} else {
$expectedFileName = $actualFileName;
if (!file_exists($actualFileName)) {
......
......@@ -12,7 +12,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,13 +11,13 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
// Loading Spyc yaml parser,
// becuase Symfony component is not working propertly with nested
// because Symfony component is not working properly with nested structures
require_once 'Spyc/spyc.php';
/**
......@@ -36,9 +36,27 @@ class EcomDev_PHPUnit_Model_Fixture
// Default eav loader class node in loaders configuration
const DEFAULT_EAV_LOADER_NODE = 'default';
// Default shared fixture name
const DEFAULT_SHARED_FIXTURE_NAME = 'default';
// Default eav loader class alias
const DEFAULT_EAV_LOADER_CLASS = 'ecomdev_phpunit/fixture_eav_default';
// Key for storing fixture data into storage
const STORAGE_KEY_FIXTURE = 'fixture';
// Key for loaded tables into database
const STORAGE_KEY_TABLES = 'tables';
// Key for loaded entities by EAV loaders
const STORAGE_KEY_ENTITIES = 'entities';
// Key for loaded cache options
const STORAGE_KEY_CACHE_OPTIONS = 'cache_options';
// Key for created scope models
const STORAGE_KEY_SCOPE = 'scope';
/**
* Fixtures array, contains config,
* table and eav keys.
......@@ -70,6 +88,20 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected $_fixture = array();
/**
* Storage object, for storing data between tests
*
* @var Varien_Object
*/
protected $_storage = null;
/**
* Scope of the fixture,
* used for different logic depending on
*
* @var string
*/
protected $_scope = self::SCOPE_LOCAL;
/**
* Fixture options
......@@ -78,9 +110,21 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected $_options = array();
/**
* List of scope model aliases by scope type
*
* @var array
*/
protected static $_scopeModelByType = array(
'store' => 'core/store',
'group' => 'core/store_group',
'website' => 'core/website'
);
/**
* Associative array of configuration nodes xml that was changed by fixture,
* it is used to preserve
* @deprecated since 0.2.1
*
* @var array
*/
......@@ -89,13 +133,14 @@ class EcomDev_PHPUnit_Model_Fixture
/**
* Hash of current scope instances (store, website, group)
*
* @deprecated since 0.2.1
* @return array
*/
protected $_currentScope = array();
/**
* Model constuctor, just defines wich resource model to use
* Model constructor, just defines which resource model to use
* (non-PHPdoc)
* @see Varien_Object::_construct()
*/
......@@ -117,7 +162,112 @@ class EcomDev_PHPUnit_Model_Fixture
}
/**
* Loads fixture from test case annotations
* Sets storage for fixtures
*
* @param Varien_Object $storage
* @return EcomDev_PHPUnit_Model_Fixture
*/
public function setStorage(Varien_Object $storage)
{
$this->_storage = $storage;
return $this;
}
/**
* Retrieve fixture storage
*
* @return Varien_Object
*/
public function getStorage()
{
return $this->_storage;
}
/**
* Retrieves storage data for a particular fixture scope
*
* @param string $key
* @param string|null $scope
* @return mixed
*/
public function getStorageData($key, $scope = null)
{
if ($scope === null) {
$scope = $this->getScope();
}
$dataKey = sprintf('%s_%s', $scope, $key);
return $this->getStorage()->getData($dataKey);
}
/**
* Sets storage data for a particular fixture scope
*
* @param string $key
* @param mixed $value
* @param string|null $scope
* @return EcomDev_PHPUnit_Model_Fixture
*/
public function setStorageData($key, $value, $scope = null)
{
if ($scope === null) {
$scope = $this->getScope();
}
$dataKey = sprintf('%s_%s', $scope, $key);
$this->getStorage()->setData($dataKey, $value);
return $this;
}
/**
* Returns current fixture scope
*
* @return string
*/
public function getScope()
{
return $this->_scope;
}
/**
* Sets current fixture scope
*
* @param string $scope EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_LOCAL|EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_SHARED
* @return EcomDev_PHPUnit_Model_Fixture
*/
public function setScope($scope)
{
$this->_scope = $scope;
return $this;
}
/**
* Check that current fixture scope is equal to SCOPE_SHARED
*
* @return boolean
*/
public function isScopeShared()
{
return $this->getScope() === self::SCOPE_SHARED;
}
/**
* Check that current fixture scope is equal to SCOPE_LOCAL
*
* @return boolean
*/
public function isScopeLocal()
{
return $this->getScope() === self::SCOPE_LOCAL;
}
/**
* Loads fixture files from test case annotations
*
* @param EcomDev_PHPUnit_Test_Case $testCase
* @return EcomDev_PHPUnit_Model_Fixture
......@@ -128,13 +278,102 @@ class EcomDev_PHPUnit_Model_Fixture
'loadFixture',
array('class', 'method')
);
$cacheOptions = $testCase->getAnnotationByName('cache', 'method');
$this->_parseCacheOptions($cacheOptions);
$this->_loadFixtureFiles($fixtures, $testCase);
return $this;
}
/**
* Loads fixture files from test class annotations
*
* @param string $className
* @return EcomDev_PHPUnit_Model_Fixture
*/
public function loadForClass($className)
{
$reflection = EcomDev_Utils_Reflection::getRelflection($className);
$method = $reflection->getMethod('getAnnotationByNameFromClass');
if (!$method instanceof ReflectionMethod) {
throw new RuntimeException('Unable to read class annotations, because it is not extended from EcomDev_PHPUnit_Test_Case');
}
$fixtures = $method->invokeArgs(
null, array($className, 'loadSharedFixture', 'class')
);
$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
*/
protected function _parseCacheOptions($annotations)
{
$cacheOptions = array();
foreach ($annotations as $annotation) {
list($action, $cacheType) = preg_split('/\s+/', trim($annotation));
$flag = ($action === 'off' ? 0 : 1);
if ($cacheType === 'all') {
foreach (Mage::app()->getCacheInstance()->getTypes() as $type) {
$cacheOptions[$type->getId()] = $flag;
}
} else {
$cacheOptions[$cacheType] = $flag;
}
}
if ($cacheOptions) {
$this->_fixture['cache_options'] = $cacheOptions;
}
}
/**
* Loads fixture files
*
* @param array $fixtures
* @param string|EcomDev_PHPUnit_Test_Case $classOrInstance
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _loadFixtureFiles(array $fixtures, $classOrInstance)
{
$isShared = ($this->isScopeShared() || !$classOrInstance instanceof EcomDev_PHPUnit_Test_Case);
foreach ($fixtures as $fixture) {
if (empty($fixture)) {
if (empty($fixture) && $isShared) {
$fixture = self::DEFAULT_SHARED_FIXTURE_NAME;
} elseif (empty($fixture)) {
$fixture = null;
}
$filePath = $testCase->getYamlFilePath('fixtures', $fixture);
$filePath = false;
if ($isShared) {
$reflection = EcomDev_Utils_Reflection::getRelflection($classOrInstance);
$method = $reflection->getMethod('getYamlFilePathByClass');
if ($method instanceof ReflectionMethod) {
$filePath = $method->invokeArgs(null, array($classOrInstance, 'fixtures', $fixture));
}
} else {
$filePath = $classOrInstance->getYamlFilePath('fixtures', $fixture);
}
if (!$filePath) {
throw new RuntimeException('Unable to load fixture for test');
......@@ -173,7 +412,9 @@ class EcomDev_PHPUnit_Model_Fixture
*/
public function apply()
{
$this->setStorageData(self::STORAGE_KEY_FIXTURE, $this->_fixture);
$reflection = EcomDev_Utils_Reflection::getRelflection($this);
foreach ($this->_fixture as $part => $data) {
$method = '_apply' . uc_words($part, '', '_');
if ($reflection->hasMethod($method)) {
......@@ -181,6 +422,8 @@ class EcomDev_PHPUnit_Model_Fixture
}
}
// Clear fixture for getting rid of duoble processing
$this->_fixture = array();
return $this;
}
......@@ -191,6 +434,14 @@ class EcomDev_PHPUnit_Model_Fixture
*/
public function discard()
{
$fixture = $this->getStorageData(self::STORAGE_KEY_FIXTURE);
if (!is_array($fixture)) {
$fixture = array();
}
$this->_fixture = $fixture;
$this->setStorageData(self::STORAGE_KEY_FIXTURE, null);
$reflection = EcomDev_Utils_Reflection::getRelflection($this);
foreach ($this->_fixture as $part => $data) {
$method = '_discard' . uc_words($part, '', '_');
......@@ -201,6 +452,36 @@ 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
*/
protected function _applyCacheOptions($options)
{
$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()
{
Mage::app()->setCacheOptions(
$this->getStorageData(self::STORAGE_KEY_CACHE_OPTIONS)
);
return $this;
}
/**
* Applies fixture configuration values into Mage_Core_Model_Config
......@@ -213,12 +494,14 @@ class EcomDev_PHPUnit_Model_Fixture
if (!is_array($configuration)) {
throw new InvalidArgumentException('Configuration part should be an associative list');
}
Mage::getConfig()->loadScopeSnapshot();
foreach ($configuration as $path => $value) {
$this->_setConfigNodeValue($path, $value);
}
Mage::getConfig()->loadDb();
Mage::app()->reinitStores();
return $this;
}
......@@ -250,7 +533,6 @@ class EcomDev_PHPUnit_Model_Fixture
throw new InvalidArgumentException('Configuration value should be a valid xml string');
}
$this->_originalConfigurationXml[$path] = $node->asNiceXml();
$node->extend($xmlElement, true);
}
......@@ -258,15 +540,25 @@ class EcomDev_PHPUnit_Model_Fixture
}
/**
* Reverts fixture configuration values in Mage_Core_Model_Config
* Restores config to a previous configuration scope
*
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardConfig()
protected function _restoreConfig()
{
Mage::getConfig()->loadScopeSnapshot();
Mage::getConfig()->loadDb();
Mage::app()->reinitStores();
return $this;
}
/**
* Reverts fixture configuration values in Mage_Core_Model_Config
*
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardConfig()
{
$this->_restoreConfig();
return $this;
}
......@@ -277,15 +569,9 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardConfigXml()
{
foreach ($this->_originalConfigurationXml as $path => $value) {
$node = Mage::getConfig()->getNode($path);
$parentNode = $node->getParent();
unset($parentNode->{$node->getName()});
$oldXml = new Varien_Simplexml_Element($value);
$parentNode->appendChild($oldXml);
if (!isset($this->_fixture['config'])) {
$this->_resetConfig();
}
$this->_originalConfigurationXml = array();
return $this;
}
......@@ -303,12 +589,25 @@ class EcomDev_PHPUnit_Model_Fixture
);
}
$ignoreCleanUp = array();
// Ignore cleaning of tables if shared fixture loaded something
if ($this->isScopeLocal() && $this->getStorageData(self::STORAGE_KEY_TABLES, self::SCOPE_SHARED)) {
$ignoreCleanUp = array_keys($this->getStorageData(self::STORAGE_KEY_TABLES, self::SCOPE_SHARED));
}
$this->getResource()->beginTransaction();
foreach ($tables as $tableEntity => $data) {
$this->getResource()->cleanTable($tableEntity);
if (!in_array($tableEntity, $ignoreCleanUp)) {
$this->getResource()->cleanTable($tableEntity);
}
if (!empty($data)) {
$this->getResource()->loadTableData($tableEntity, $data);
}
}
$this->getResource()->commit();
$this->setStorageData(self::STORAGE_KEY_TABLES, $tables);
}
/**
......@@ -325,9 +624,24 @@ class EcomDev_PHPUnit_Model_Fixture
);
}
foreach ($tables as $tableEntity => $data) {
$restoreTableData = array();
// Data for tables used in shared fixture
if ($this->isScopeLocal() && $this->getStorageData(self::STORAGE_KEY_TABLES, self::SCOPE_SHARED)) {
$restoreTableData = $this->getStorageData(self::STORAGE_KEY_TABLES, self::SCOPE_SHARED);
}
$this->getResource()->beginTransaction();
foreach (array_keys($tables) as $tableEntity) {
$this->getResource()->cleanTable($tableEntity);
if (isset($restoreTableData[$tableEntity])) {
$this->getResource()->loadTableData($tableEntity, $restoreTableData[$tableEntity]);
}
}
$this->getResource()->commit();
$this->setStorageData(self::STORAGE_KEY_TABLES, null);
}
/**
......@@ -357,7 +671,7 @@ class EcomDev_PHPUnit_Model_Fixture
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$website, '_configCache', array()
);
// Should change value
default:
Mage::getConfig()->setNode($path, $value);
......@@ -391,7 +705,7 @@ class EcomDev_PHPUnit_Model_Fixture
/**
* Applies fixture EAV values
*
* @param array $configuration
* @param array $entities
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _applyEav($entities)
......@@ -399,13 +713,20 @@ 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) {
$this->_getEavLoader($entityType)
->setFixture($this)
->setOptions($this->_options)
->loadEntity($entityType, $values);
}
$this->getResource()->commit();
$this->setStorageData(self::STORAGE_KEY_ENTITIES, array_keys($entities));
return $this;
}
......@@ -417,10 +738,23 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardEav($entities)
{
$ignoreCleanUp = array();
// Ignore cleaning of entities if shared fixture loaded something for them
if ($this->isScopeLocal() && $this->getStorageData(self::STORAGE_KEY_ENTITIES, self::SCOPE_SHARED)) {
$ignoreCleanUp = $this->getStorageData(self::STORAGE_KEY_ENTITIES, self::SCOPE_SHARED);
}
$this->getResource()->beginTransaction();
foreach (array_keys($entities) as $entityType) {
if (in_array($entityType, $ignoreCleanUp)) {
continue;
}
$this->_getEavLoader($entityType)
->cleanEntity($entityType);
}
$this->getResource()->commit();
return $this;
}
......@@ -434,38 +768,96 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected function _applyScope($types)
{
$modelByType = array(
'store' => 'core/store',
'group' => 'core/store_group',
'website' => 'core/website'
Mage::app()->disableEvents();
// Validate received fixture data
$this->_validateScope($types);
if ($this->getStorageData(self::STORAGE_KEY_SCOPE) !== null) {
throw new RuntimeException('Scope data was not cleared after previous test');
}
$scopeModels = array();
foreach ($types as $type => $rows) {
foreach ($rows as $row) {
$model = $this->_handleScopeRow($type, $row);
if ($model) {
$scopeModels[$type][$model->getId()] = $model;
}
}
}
$this->setStorageData(self::STORAGE_KEY_SCOPE, $scopeModels);
Mage::app()->enableEvents();
Mage::app()->reinitStores();
return $this;
}
/**
* Handle scope row data
*
* @param string $type
* @param array $row
* @return boolean|Mage_Core_Model_Abstract
*/
protected function _handleScopeRow($type, $row)
{
$previousScope = array();
if ($this->isScopeLocal() && $this->getStorageData(self::STORAGE_KEY_SCOPE, self::SCOPE_SHARED) !== null) {
$previousScope = $this->getStorageData(self::STORAGE_KEY_SCOPE, self::SCOPE_SHARED);
}
if (isset($previousScope[$type][$row[$type . '_id']])) {
return false;
}
$scopeModel = Mage::getModel(self::$_scopeModelByType[$type]);
$scopeModel->setData($row);
// Change property for saving new objects with specified ids
EcomDev_Utils_Reflection::setRestrictedPropertyValues(
$scopeModel->getResource(),
array(
'_useIsObjectNew' => true,
'_isPkAutoIncrement' => false
)
);
Mage::app()->disableEvents();
$scopeModel->isObjectNew(true);
$scopeModel->save();
// Revert changed property
EcomDev_Utils_Reflection::setRestrictedPropertyValues(
$scopeModel->getResource(),
array(
'_useIsObjectNew' => false,
'_isPkAutoIncrement' => true
)
);
return $scopeModel;
}
/**
* Validate scope data
*
* @param array $types
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function _validateScope($types)
{
foreach ($types as $type => $rows) {
if (!isset($modelByType[$type])) {
if (!isset(self::$_scopeModelByType[$type])) {
throw new RuntimeException(sprintf('Unknown "%s" scope type specified', $type));
}
foreach ($rows as $row) {
$scopeModel = Mage::getModel($modelByType[$type]);
$this->_currentScope[$type][] = $scopeModel;
$scopeModel->setData($row);
// Change property for saving new objects with specified ids
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$scopeModel->getResource(), '_useIsObjectNew', true
);
$scopeModel->isObjectNew(true);
$scopeModel->save();
// Revert changed property
EcomDev_Utils_Reflection::setRestrictedPropertyValue(
$scopeModel->getResource(), '_useIsObjectNew', false
);
foreach ($rows as $rowNumber => $row) {
if (!isset($row[$type . '_id'])) {
throw new RuntimeException(sprintf('Missing primary key for "%s" scope entity at #%d row', $type, $rowNumber + 1));
}
}
}
Mage::app()->enableEvents();
Mage::app()->reinitStores();
return $this;
}
......@@ -477,19 +869,29 @@ class EcomDev_PHPUnit_Model_Fixture
*/
protected function _discardScope()
{
if ($this->getStorageData(self::STORAGE_KEY_SCOPE) === null) {
return $this;
}
Mage::app()->disableEvents();
$scope = array_reverse($this->_currentScope);
$scope = array_reverse($this->getStorageData(self::STORAGE_KEY_SCOPE));
foreach ($scope as $models) {
foreach ($models as $model) {
$model->delete();
}
}
$this->_currentScope = array();
$this->setStorageData(self::STORAGE_KEY_SCOPE, null);
Mage::app()->getCache()->clean(
Zend_Cache::CLEANING_MODE_MATCHING_TAG,
array(Mage_Core_Model_Mysql4_Collection_Abstract::CACHE_TAG)
Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG,
array(
Mage_Core_Model_Store::CACHE_TAG,
Mage_Core_Model_Store_Group::CACHE_TAG,
Mage_Core_Model_Website::CACHE_TAG
)
);
Mage::app()->enableEvents();
Mage::app()->reinitStores();
return $this;
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -25,6 +25,9 @@
*/
interface EcomDev_PHPUnit_Model_Fixture_Interface extends EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
const SCOPE_LOCAL = 'local';
const SCOPE_SHARED = 'shared';
/**
* Sets fixture options
*
......@@ -32,4 +35,74 @@ interface EcomDev_PHPUnit_Model_Fixture_Interface extends EcomDev_PHPUnit_Model_
* @return EcomDev_PHPUnit_Model_Fixture_Interface
*/
public function setOptions(array $options);
}
\ No newline at end of file
/**
* Sets storage for fixtures
*
* @param Varien_Object $storage
* @return EcomDev_PHPUnit_Model_Fixture_Interface
*/
public function setStorage(Varien_Object $storage);
/**
* Retrieve fixture storage
*
* @return Varien_Object
*/
public function getStorage();
/**
* Retrieves storage data for a particular fixture scope
*
* @param string $key
* @param string|null $scope
*/
public function getStorageData($key, $scope = null);
/**
* Sets storage data for a particular fixture scope
*
* @param string $key
* @param mixed $value
* @param string|null $scope
*/
public function setStorageData($key, $value, $scope = null);
/**
* Returns current fixture scope
*
* @return string
*/
public function getScope();
/**
* Sets current fixture scope
*
*
* @param string $scope EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_LOCAL|EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_SHARED
*/
public function setScope($scope);
/**
* Check that current fixture scope is equal to SCOPE_SHARED
*
* @return boolean
*/
public function isScopeShared();
/**
* Check that current fixture scope is equal to SCOPE_LOCAL
*
* @return boolean
*/
public function isScopeLocal();
/**
* Loads fixture files from test class annotations
*
* @param string $className
* @return EcomDev_PHPUnit_Model_Fixture_Interface
*/
public function loadForClass($className);
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -37,8 +37,15 @@ class EcomDev_PHPUnit_Model_Mysql4_Fixture extends Mage_Core_Model_Mysql4_Abstra
*/
public function cleanTable($tableEntity)
{
$this->_getWriteAdapter()
->truncate($this->getTable($tableEntity));
try {
$this->_getWriteAdapter()
->delete($this->getTable($tableEntity));
} catch (Exception $e) {
throw new EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception(
sprintf('Unable to clear records for a table "%s"', $tableEntity),
$e
);
}
return $this;
}
......@@ -58,11 +65,18 @@ class EcomDev_PHPUnit_Model_Mysql4_Fixture extends Mage_Core_Model_Mysql4_Abstra
$records[] = $this->_getTableRecord($row, $tableColumns);
}
$this->_getWriteAdapter()->insertMultiple(
$this->getTable($tableEntity),
$records
);
try {
$this->_getWriteAdapter()->insertOnDuplicate(
$this->getTable($tableEntity),
$records
);
} catch (Exception $e) {
throw new EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception(
sprintf('Unable to insert/update records for a table "%s"', $tableEntity),
$e
);
}
return $this;
}
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -36,6 +36,13 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
*/
protected $_options = array();
/**
* Fixture model
*
* @var EcomDev_PHPUnit_Model_Fixture_Interface
*/
protected $_fixture = null;
/**
* Retrieve required indexers for re-building
*
......@@ -46,6 +53,17 @@ 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
*
......@@ -95,8 +113,19 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
*/
public function loadEntity($entityType, $values)
{
$originalRequiredIndexers = $this->_requiredIndexers;
if (!empty($this->_options['addRequiredIndex'])) {
foreach ($this->_options['addRequiredIndex'] as $data) {
if (preg_match('/^([a-z0-9_\\-])+\\s+([a-z0-9_\\-])\s*$/i', $data, $match)
&& $match[1] == $entityType) {
$this->_requiredIndexers[] = $match[2];
}
}
}
$entityTypeModel = Mage::getSingleton('eav/config')->getEntityType($entityType);
$entityTableColumns = $this->_getWriteAdapter()->describeTable(
$this->getTable($entityTypeModel->getEntityTable())
);
......@@ -119,7 +148,7 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
throw new RuntimeException('Entity Id should be specified in EAV fixture');
}
// Fullfil neccessary information
// Fulfill necessary information
$row['entity_type_id'] = $entityTypeModel->getEntityTypeId();
if (!isset($row['attribute_set_id'])) {
$row['attribute_set_id'] = $entityTypeModel->getDefaultAttributeSetId();
......@@ -197,6 +226,8 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
}
}
// Restoring original required indexers for making tests isolated
$this->_requiredIndexers = $originalRequiredIndexers;
return $this;
}
......@@ -325,9 +356,35 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
$value = null;
}
if ($attribute->usesSource() && $value !== null) {
if ($attribute->getSource() instanceof Mage_Eav_Model_Entity_Attribute_Source_Abstract) {
$value = $attribute->getSource()->getOptionId($value);
} else {
$value = $this->_getOptionIdNonAttributeSource($attribute->getSource()->getAllOptions(), $value);
}
}
return $value;
}
/**
* Get option id if attribute source model doesn't support eav attribute interface
*
*
* @param array $options
* @param mixed $value
*/
protected function _getOptionIdNonAttributeSource($options, $value)
{
foreach ($options as $option) {
if (strcasecmp($option['label'], $value)==0 || $option['value'] == $value) {
return $option['value'];
}
}
return null;
}
/**
* Retrieves entity id field, based on entity configuration
*
......@@ -341,4 +398,4 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract extends EcomDev
}
return Mage_Eav_Model_Entity::DEFAULT_ENTITY_ID_FIELD;
}
}
\ No newline at end of file
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -120,7 +120,9 @@ abstract class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Abstract extends
*/
protected function _getGwsValue($row, $attribute, $scopeCode, $scopeType = self::SCOPE_TYPE_STORE)
{
if (!isset($row['/' . $scopeType][$scopeCode]) || !is_array($row['/' . $scopeType][$scopeCode])) {
if (!isset($row['/' . $scopeType][$scopeCode])
|| !is_array($row['/' . $scopeType][$scopeCode])
|| !isset($row['/' . $scopeType][$scopeCode][$attribute->getAttributeCode()])) {
return null;
}
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -25,14 +25,13 @@ class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Product extends EcomDev_P
{
protected $_requiredIndexers = array(
'cataloginventory_stock',
'catalog_product_flat',
'catalog_product_attribute',
'catalog_product_price'
);
/**
* Ovveriden to fix issue with flat tables existance mark
* Overridden to fix issue with flat tables existance mark
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::loadEntity()
*/
......@@ -49,7 +48,7 @@ class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Product extends EcomDev_P
}
/**
* Overriden to add easy fixture loading for websites and categories associations
* Overridden to add easy fixture loading for websites and categories associations
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Abstract::_getCustomTableRecords()
*/
......@@ -207,4 +206,4 @@ class EcomDev_PHPUnit_Model_Mysql4_Fixture_Eav_Catalog_Product extends EcomDev_P
parent::_customEntityAction($entity, $entityTypeModel);
return $this;
}
}
\ No newline at end of file
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
<?php
class EcomDev_PHPUnit_Model_Mysql4_Fixture_Exception extends RuntimeException
{
public function __construct($message, Exception $previous)
{
parent::__construct($message, 0, $previous);
}
}
\ No newline at end of file
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -75,8 +75,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
public static function assertEventDispatched($eventName)
{
if (is_array($eventName)) {
foreach ($eventNames as $eventName) {
self::assertEventDispatched($eventName);
foreach ($eventName as $singleEventName) {
self::assertEventDispatched($singleEventName);
}
return;
}
......@@ -95,8 +95,8 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
public static function assertEventNotDispatched($eventName)
{
if (is_array($eventName)) {
foreach ($eventNames as $eventName) {
self::assertEventNotDispatched($eventName);
foreach ($eventName as $singleEventName) {
self::assertEventNotDispatched($singleEventName);
}
return;
}
......@@ -271,12 +271,28 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
* @return array
*/
public function getAnnotationByName($name, $sources = 'method')
{
return self::getAnnotationByNameFromClass(get_class($this), $name, $sources, $this->getName(false));
}
/**
* Retrieves annotation by its name from different sources (class, method) based on meta information
*
* @param string $className
* @param string $name annotation name
* @param array|string $sources
* @param string $testName test method name
*/
public static function getAnnotationByNameFromClass($className, $name, $sources = 'class', $testName = '')
{
if (is_string($sources)) {
$sources = array($sources);
}
$allAnnotations = $this->getAnnotations();
$allAnnotations = PHPUnit_Util_Test::parseTestMethodAnnotations(
$className, $testName
);
$annotation = array();
// Walkthrough sources for annotation retrieval
......@@ -627,12 +643,30 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function getFixture()
protected static function getFixture()
{
return Mage::getSingleton($this->getLoadableClassAlias(
'fixture',
self::XML_PATH_DEFAULT_FIXTURE_MODEL
));;
$fixture = Mage::getSingleton(
self::getLoadableClassAlias(
'fixture',
self::XML_PATH_DEFAULT_FIXTURE_MODEL
)
);
if (!$fixture instanceof EcomDev_PHPUnit_Model_Fixture_Interface) {
throw new RuntimeException('Fixture model should implement EcomDev_PHPUnit_Model_Fixture_Interface interface');
}
$storage = Mage::registry(EcomDev_PHPUnit_Model_App::REGISTRY_PATH_SHARED_STORAGE);
if (!$storage instanceof Varien_Object) {
throw new RuntimeException('Fixture storage object was not initialized during test application setup');
}
$fixture->setStorage(
Mage::registry(EcomDev_PHPUnit_Model_App::REGISTRY_PATH_SHARED_STORAGE)
);
return $fixture;
}
/**
......@@ -642,10 +676,12 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/
protected function getExpectation()
{
return Mage::getSingleton($this->getLoadableClassAlias(
'expectation',
self::XML_PATH_DEFAULT_EXPECTATION_MODEL
));
return Mage::getSingleton(
self::getLoadableClassAlias(
'expectation',
self::XML_PATH_DEFAULT_EXPECTATION_MODEL
)
);
}
......@@ -655,15 +691,19 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*
* @param string $type
* @param string $configPath
* @return string
*/
protected function getLoadableClassAlias($type, $configPath)
protected static function getLoadableClassAlias($type, $configPath)
{
$annotationValue = $this->getAnnotationByName($type .'Model' , 'class');
$annotationValue = self::getAnnotationByNameFromClass(
get_called_class(),
$type .'Model'
);
if (current($annotationValue)) {
$classAlias = current($annotationValue);
} else {
$classAlias = $this->app()->getConfig()->getNode($configPath);
$classAlias = self::app()->getConfig()->getNode($configPath);
}
return $classAlias;
......@@ -699,17 +739,45 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$name = $this->getName(false);
}
return self::getYamlFilePathByClass(get_called_class(), $type, $name);
}
/**
* Loads YAML file from directory inside of the unit test class or
* the directory inside the module directory if name is prefixed with ~/
* or from another module if name is prefixed with ~My_Module/
*
* @param string $className class name for looking fixture files
* @param string $type type of YAML data (fixtures,expectations,dataproviders)
* @param string $name the file name for loading
* @return string|boolean
*/
public static function getYamlFilePathByClass($className, $type, $name)
{
if (strrpos($name, '.yaml') !== strlen($name) - 5) {
$name .= '.yaml';
}
$classFileObject = new SplFileInfo(
EcomDev_Utils_Reflection::getRelflection($this)->getFileName()
EcomDev_Utils_Reflection::getRelflection($className)->getFileName()
);
$filePath = $classFileObject->getPath() . DS
. $classFileObject->getBasename('.php') . DS
. $type . DS . $name;
// When prefixed with ~/ or ~My_Module/, load from the module's Test/<type> directory
if (preg_match('#^~(?<module>[^/]*)/(?<path>.*)$#', $name, $matches)) {
$name = $matches['path'];
if( ! empty($matches['module'])) {
$moduleName = $matches['module'];
} else {
$moduleName = substr($className, 0, strpos($className, '_Test_'));;
}
$filePath = Mage::getModuleDir('', $moduleName) . DS . 'Test' . DS;
}
// Otherwise load from the Class/<type> directory
else {
$filePath = $classFileObject->getPath() . DS
. $classFileObject->getBasename('.php') . DS;
}
$filePath .= $type . DS . $name;
if (file_exists($filePath)) {
return $filePath;
......@@ -726,15 +794,38 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/
protected function setUp()
{
$this->getFixture()->loadByTestCase($this);
self::getFixture()
->setScope(EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_LOCAL)
->loadByTestCase($this);
$annotations = $this->getAnnotations();
$this->getFixture()->setOptions($annotations['method']);
$this->getFixture()->apply();
self::getFixture()
->setOptions($annotations['method'])
->apply();
$this->app()->resetDispatchedEvents();
parent::setUp();
}
/**
* Initializes test environment for subset of tests
*
*/
public static function setUpBeforeClass()
{
self::getFixture()
->setScope(EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_SHARED)
->loadForClass(get_called_class());
$annotations = PHPUnit_Util_Test::parseTestMethodAnnotations(
get_called_class()
);
self::getFixture()
->setOptions($annotations['class'])
->apply();
parent::setUpBeforeClass();
}
/**
* Implements default data provider functionality,
* returns array data loaded from Yaml file with the same name as test method
......@@ -796,9 +887,24 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$this->app()->replaceRegistry($registryPath, $originalValue);
}
$this->getFixture()->discard(); // Clear applied fixture
self::getFixture()
->setScope(EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_LOCAL)
->discard(); // Clear applied fixture
parent::tearDown();
}
/**
* Clean up all the shared fixture data
*
* @return void
*/
public static function tearDownAfterClass()
{
self::getFixture()
->setScope(EcomDev_PHPUnit_Model_Fixture_Interface::SCOPE_SHARED)
->discard();
parent::tearDownAfterClass();
}
}
\ No newline at end of file
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -40,6 +40,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
* @param string $nodePath
* @param string $type
* @param mixed $expectedValue
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configNode($nodePath, $type, $expectedValue = null)
{
......@@ -54,6 +55,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
* @param string $moduleName
* @param string $type
* @param string|null $expectedValue
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configModule($moduleName, $type, $expectedValue = null)
{
......@@ -61,13 +63,56 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
new EcomDev_PHPUnit_Constraint_Config_Module($moduleName, $type, $expectedValue)
);
}
/**
* A new constraint for checking module node
* A new constraint for checking resources node
*
* @param string $moduleName
* @param string $type
* @param string|null $expectedValue
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configResource($moduleName,
$type = EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_DEFINED,
$expectedValue = null)
{
return self::config(
new EcomDev_PHPUnit_Constraint_Config_Resource($moduleName, $type,
self::app()->getConfig()->getModuleDir('', $moduleName),
$expectedValue)
);
}
/**
* A new constraint for checking resource setup scripts consistency
*
* @param string $moduleName
* @param string $type
* @param array|null $expectedValue
* @param string $resourceName
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configResourceScript($moduleName,
$type = EcomDev_PHPUnit_Constraint_Config_Resource_Script::TYPE_SCRIPT_SCHEME,
array $expectedValue = null, $resourceName = null)
{
return self::config(
new EcomDev_PHPUnit_Constraint_Config_Resource_Script($moduleName, $type,
self::app()->getConfig()->getModuleDir('', $moduleName),
$resourceName, $expectedValue)
);
}
/**
* A new constraint for checking class alias nodes
*
* @param string $group
* @param string $classAlias
* @param string $expectedClassName
* @param string $type
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configClassAlias($group, $classAlias, $expectedClassName,
$type = EcomDev_PHPUnit_Constraint_Config_ClassAlias::TYPE_CLASS_ALIAS)
......@@ -76,6 +121,22 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
new EcomDev_PHPUnit_Constraint_Config_ClassAlias($group, $classAlias, $expectedClassName, $type)
);
}
/**
* A new constraint for checking table alias nodes
*
* @param string $tableAlias
* @param string $expectedTableName
* @param string $type
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configTableAlias($tableAlias, $expectedTableName,
$type = EcomDev_PHPUnit_Constraint_Config_TableAlias::TYPE_TABLE_ALIAS)
{
return self::config(
new EcomDev_PHPUnit_Constraint_Config_TableAlias($tableAlias, $expectedTableName, $type)
);
}
/**
* Creates layout constraint
......@@ -86,6 +147,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
* @param string|null $layoutUpdate
* @param string|null $theme
* @param string|null $designPackage
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configLayout($area, $expectedFile, $type, $layoutUpdate = null, $theme = null, $designPackage = null)
{
......@@ -106,7 +168,9 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
* @param string $eventName
* @param string $observerClassAlias
* @param string $observerMethod
* @param string $type
* @param string|null $observerName
* @return EcomDev_PHPUnit_Constraint_Config
*/
public static function configEventObserver($area, $eventName, $observerClassAlias, $observerMethod,
$type = EcomDev_PHPUnit_Constraint_Config_EventObserver::TYPE_DEFINDED, $observerName = null)
......@@ -127,6 +191,235 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertThat(Mage::getConfig(), $constraint, $message);
}
/**
* Asserts that config resource for module is defined
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSetupResourceDefined($moduleName = null, $expectedResourceName = null, $message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
self::assertThatConfig(
self::configResource($moduleName,
EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_DEFINED,
$expectedResourceName),
$message
);
}
/**
* Asserts that config resource for module is NOT defined
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSetupResourceNotDefined($moduleName = null, $expectedResourceName = null, $message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
self::assertThatConfig(
self::logicalNot(
self::configResource($moduleName,
EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_DEFINED,
$expectedResourceName)
),
$message
);
}
/**
* Asserts that config resource for module is defined and directory with the same name exists in module
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSchemeSetupExists($moduleName = null, $expectedResourceName = null, $message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
self::assertThatConfig(
self::configResource($moduleName,
EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_SCHEME_EXISTS,
$expectedResourceName),
$message
);
}
/**
* Asserts that config resource for module is defined and directory with the same name exists in module
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSchemeSetupNotExists($moduleName = null, $expectedResourceName = null, $message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
self::assertThatConfig(
self::logicalNot(
self::configResource($moduleName,
EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_SCHEME_EXISTS,
$expectedResourceName)
),
$message
);
}
/**
* Asserts that config resource for module is defined and directory with the same name exists in module directory
* for data setup scripts
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertDataSetupExists($moduleName = null, $expectedResourceName = null, $message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
self::assertThatConfig(
self::configResource($moduleName,
EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_DATA_EXISTS,
$expectedResourceName),
$message
);
}
/**
* Asserts that config resource for module is defined and directory with the same name exists in module
* directory for data setup scripts
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertDataSetupNotExists($moduleName = null, $expectedResourceName = null, $message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
self::assertThatConfig(
self::logicalNot(
self::configResource($moduleName,
EcomDev_PHPUnit_Constraint_Config_Resource::TYPE_SETUP_DATA_EXISTS,
$expectedResourceName)
),
$message
);
}
/**
* Asserts that there is defined properly list of data/scheme upgrade scripts
*
* @param string $type
* @param string|null $from
* @param string|null $to
* @param string|null $moduleName
* @param string|null $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSetupScriptVersions(
$type = EcomDev_PHPUnit_Constraint_Config_Resource_Script::TYPE_SCRIPT_SCHEME, $from = null, $to = null,
$moduleName = null, $resourceName = null,$message = '')
{
if ($moduleName === null) {
$moduleName = self::getModuleNameFromCallStack();
}
if ($to === null) {
$moduleConfig = self::app()->getConfig()->getModuleConfig($moduleName);
if (isset($moduleConfig->version)) {
$to = (string)$moduleConfig->version;
}
}
self::assertThatConfig(
self::configResourceScript($moduleName,
$type,
array($from, $to),
$resourceName
),
$message
);
}
/**
* Asserts that there is defined properly list of scheme upgrade scripts
*
* @param string|null $from
* @param string|null $to
* @param string|null $moduleName
* @param string|null $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSchemeSetupScriptVersions($from = null, $to = null,
$moduleName = null, $resourceName = null,$message = '')
{
self::assertSetupScriptVersions(EcomDev_PHPUnit_Constraint_Config_Resource_Script::TYPE_SCRIPT_SCHEME, $from,
$to, $moduleName, $resourceName, $message);
}
/**
* Asserts that there is defined properly list of data upgrade scripts
*
* @param string|null $from
* @param string|null $to
* @param string|null $moduleName
* @param string|null $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertDataSetupScriptVersions($from = null, $to = null,
$moduleName = null, $resourceName = null,$message = '')
{
self::assertSetupScriptVersions(EcomDev_PHPUnit_Constraint_Config_Resource_Script::TYPE_SCRIPT_DATA, $from,
$to, $moduleName, $resourceName, $message);
}
/**
* Alias of assertSchemeSetupExists() model
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSetupResourceExists($moduleName = null, $expectedResourceName = null, $message = '')
{
self::assertSchemeSetupExists($moduleName, $expectedResourceName, $message);
}
/**
* Alias of assertSchemeSetupNotExists() model
*
*
* @param string $moduleName
* @param mixed $expectedResourceName
* @param string $message
*/
public static function assertSetupResourceNotExists($moduleName = null, $expectedResourceName = null, $message = '')
{
self::assertSchemeSetupNotExists($moduleName, $expectedResourceName, $message);
}
/**
* Asserts that config node value is equal to the expected value.
*
......@@ -304,6 +597,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
*
* @param string $nodePath
* @param decimal $expectedValue
* @param string $message
*/
public static function assertConfigNodeLessThanOrEquals($nodePath, $expectedValue, $message = '')
{
......@@ -344,6 +638,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
*
* @param string $nodePath
* @param decimal $expectedValue
* @param string $message
*/
public static function assertConfigNodeGreaterThanOrEquals($nodePath, $expectedValue, $message = '')
{
......@@ -640,6 +935,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
* @param string $group
* @param string $classAlias
* @param string $expectedClassName
* @param string $message
*/
public static function assertGroupedClassAlias($group, $classAlias, $expectedClassName, $message = '')
{
......@@ -655,6 +951,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
* @param string $group
* @param string $classAlias
* @param string $expectedClassName
* @param string $message
*/
public static function assertGroupedClassAliasNot($group, $classAlias, $expectedClassName, $message = '')
{
......@@ -678,7 +975,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAlias(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_BLOCK,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......@@ -694,7 +992,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAliasNot(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_BLOCK,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......@@ -710,7 +1009,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAlias(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_MODEL,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......@@ -726,7 +1026,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAliasNot(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_MODEL,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......@@ -744,7 +1045,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAlias(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_MODEL,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......@@ -762,7 +1064,40 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAliasNot(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_MODEL,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
/**
* Assert that table alias is mapped to expected table name
*
* @param string $tableAlias
* @param string $expectedTableName
* @param string $message
*/
public static function assertTableAlias($tableAlias, $expectedTableName, $message = '')
{
self::assertThatConfig(
self::configTableAlias($tableAlias, $expectedTableName),
$message
);
}
/**
* Assert that table alias is NOT mapped to expected table name
*
* @param string $tableAlias
* @param string $expectedTableName
* @param string $message
*/
public static function assertTableAliasNot($tableAlias, $expectedTableName, $message = '')
{
self::assertThatConfig(
self::logicalNot(
self::configTableAlias($tableAlias, $expectedTableName)
),
$message
);
}
......@@ -778,7 +1113,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAlias(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_HELPER,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......@@ -794,7 +1130,8 @@ abstract class EcomDev_PHPUnit_Test_Case_Config extends EcomDev_PHPUnit_Test_Cas
self::assertGroupedClassAliasNot(
EcomDev_PHPUnit_Constraint_Config_ClassAlias::GROUP_HELPER,
$classAlias,
$expectedClassName
$expectedClassName,
$message
);
}
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -431,7 +431,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Controller extends EcomDev_PHPUnit_Test
{
self::assertRequestNot(
EcomDev_PHPUnit_Constraint_Controller_Request::TYPE_BEFORE_FORWARD_ROUTE,
$expectedActionName, $message
$expectedBeforeForwardedRoute, $message
);
}
......@@ -1969,7 +1969,7 @@ abstract class EcomDev_PHPUnit_Test_Case_Controller extends EcomDev_PHPUnit_Test
// Workaround for form key
if ($this->getRequest()->isPost()) {
$this->getRequest()->setPost('form_key', Mage::getSingleton('core/session')->getFromKey());
$this->getRequest()->setPost('form_key', Mage::getSingleton('core/session')->getFormKey());
}
$this->getLayout()->reset();
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -141,11 +141,11 @@ class EcomDev_PHPUnit_Test_Suite extends PHPUnit_Framework_TestSuite
$directoryIterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($searchPath)
);
foreach ($directoryIterator as $fileObject) {
/* @var $fileObject SplFileObject */
// Skip entry if it is not a php file
if (!$fileObject->isFile() || $fileObject->getBasename('.php') === $fileObject->getBasename()) {
if ((!$fileObject->isFile() && !$fileObject->isLink()) || $fileObject->getBasename('.php') === $fileObject->getBasename()) {
continue;
}
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -25,13 +25,19 @@ class EcomDev_PHPUnit_Test_Suite_Group extends PHPUnit_Framework_TestSuite
{
const NO_GROUP_KEYWORD = '__nogroup__';
/**
* Name of suite that will be printed in tap/testdox format
*
* @var string
*/
protected $suiteName = null;
/**
* Contructor adds test groups defined on global level
* and adds additional logic for test names retrieval
*
* (non-PHPdoc)
* @see PHPUnit_Framework_TestSuite::__construct()
* @param array $groups
*/
public function __construct($theClass = '', $groups = array())
{
......@@ -44,14 +50,12 @@ class EcomDev_PHPUnit_Test_Suite_Group extends PHPUnit_Framework_TestSuite
$theClass->getName()
);
if (isset($annotation['name'])) {
$name = $annotations['name'];
} else {
$name = sprintf('Test suite for %s', $theClass->getName());
if (isset($annotations['name'])) {
$this->suiteName = $annotations['name'];
}
// Creates all test instances
parent::__construct($theClass, $name);
parent::__construct($theClass);
// Just sort-out them by our internal groups
foreach ($groups as $group) {
......@@ -81,4 +85,15 @@ class EcomDev_PHPUnit_Test_Suite_Group extends PHPUnit_Framework_TestSuite
unset($this->groups[self::NO_GROUP_KEYWORD]);
}
}
/**
* Outputs test suite name from annotations
*
* (non-PHPdoc)
* @see PHPUnit_Framework_TestSuite::toString()
*/
public function toString()
{
return $this->suiteName !== null ? $this->suiteName : $this->name;
}
}
......@@ -12,7 +12,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -20,6 +20,7 @@
* Abstract constraint for EcomDev_PHPUnit constraints
* Contains flexible constaint types implementation
*
* @todo refactor failures for being 100% compatible with PHPUnit 3.6
*/
abstract class EcomDev_PHPUnit_Constraint_Abstract
extends PHPUnit_Framework_Constraint
......@@ -109,6 +110,7 @@ abstract class EcomDev_PHPUnit_Constraint_Abstract
// Type check
if (isset($this->_expectedValueValidation[$type][1])
&& $expectedValue !== null
&& !$this->_expectedValueValidation[$type][1]($expectedValue)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, $expectedValueType, $expectedValue);
}
......@@ -148,12 +150,29 @@ abstract class EcomDev_PHPUnit_Constraint_Abstract
/**
* Evaluates value by type.
* (non-PHPdoc)
*
* @see PHPUnit_Framework_Constraint::evaluate()
*
* @param mixed $other Value or object to evaluate.
* @param string $description Additional information about the test
* @param bool $returnResult Whether to return a result or throw an exception
* @return mixed
*/
public function evaluate($other)
public function evaluate($other, $description = '', $returnResult = false)
{
return $this->callProtectedByType('evaluate', $other);
$success = false;
if ($this->callProtectedByType('evaluate', $other)) {
$success = true;
}
if ($returnResult) {
return $success;
}
if (!$success) {
$this->fail($other, $description);
}
}
/**
......@@ -169,7 +188,12 @@ abstract class EcomDev_PHPUnit_Constraint_Abstract
if (in_array($this->_type, $this->_typesWithDiff)) {
throw new EcomDev_PHPUnit_Constraint_Exception(
$failureDescription,
PHPUnit_Util_Diff::diff($this->getExpectedValue(), $this->getActualValue($other)),
new PHPUnit_Framework_ComparisonFailure(
$this->getExpectedValue(),
$this->getActualValue($other),
$this->getExpectedValue(),
$this->getActualValue($other)
),
$description
);
} else {
......@@ -179,6 +203,23 @@ abstract class EcomDev_PHPUnit_Constraint_Abstract
}
}
/**
* Adds compatibility to PHPUnit 3.6
*
* @param mixed $other
* @param mixed $description (custom description)
* @param boolean $not
* @return string
*/
protected function failureDescription($other, $description, $not)
{
if (method_exists($this, 'customFailureDescription')) {
return $this->customFailureDescription($other, $description, $not);
}
return parent::failureDescription($other, $description, $not);
}
/**
* Returns a scalar representation of actual value,
* Returns $other if internal acutal value is not set
......@@ -198,7 +239,7 @@ abstract class EcomDev_PHPUnit_Constraint_Abstract
/**
* Returns a scalar representation of expected value
*
* @return string
* @return scalar
*/
protected function getExpectedValue()
{
......@@ -214,4 +255,4 @@ abstract class EcomDev_PHPUnit_Constraint_Abstract
{
return $this->callProtectedByType('text');
}
}
\ No newline at end of file
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -92,11 +92,11 @@ class EcomDev_PHPUnit_Constraint_Config extends PHPUnit_Framework_Constraint
* @param Varien_Simplexml_Config $config
* @see PHPUnit_Framework_Constraint::evaluate()
*/
public function evaluate($config)
public function evaluate($config, $description = '', $returnResult = false)
{
$nodeValue = $this->getNodeValue($config);
return $this->constraint->evaluate($nodeValue);
return $this->constraint->evaluate($nodeValue, $description, $returnResult);
}
/**
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -65,14 +65,14 @@ abstract class EcomDev_PHPUnit_Constraint_Config_Abstract
* (non-PHPdoc)
* @see EcomDev_PHPUnit_Constraint_Abstract::evaluate()
*/
public function evaluate($other)
public function evaluate($other, $description = '', $returnResult = false)
{
if ($other === false) {
// If node was not found, than evaluation fails
return false;
}
return parent::evaluate($other);
return parent::evaluate($other, $description, $returnResult);
}
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -139,7 +139,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
*
* @return string
*/
protected function textLayoutDefition()
protected function textLayoutDefinition()
{
$text = sprintf('file "%s" is defined in configuration for %s area', $this->_expectedValue, $this->_area);
......@@ -164,7 +164,7 @@ class EcomDev_PHPUnit_Constraint_Config_Layout
$this->setActualValue($assertion['actual']);
$this->_expectedValue = $assertion['expected'];
return $this->_actualValue !== $this->_expectedValue;
return $this->_actualValue === $this->_expectedValue;
}
/**
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
<?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>
*/
/**
* Setup resources configuration constraint
*
*/
class EcomDev_PHPUnit_Constraint_Config_Resource
extends EcomDev_PHPUnit_Constraint_Config_Abstract
{
const XML_PATH_RESOURCES_NODE = 'global/resources';
const TYPE_SETUP_DEFINED = 'setup_defined';
const TYPE_SETUP_SCHEME_EXISTS = 'setup_scheme_exists';
const TYPE_SETUP_DATA_EXISTS = 'setup_data_exists';
/**
* Name of the module for constraint
*
* @var string
*/
protected $_moduleName = null;
/**
* The module directory for constraint
*
* @var string
*/
protected $_moduleDirectory = null;
/**
* Constraint for evaluation of module config node
*
* @param string $nodePath
* @param string $type
* @param string $moduleDirectory
* @param mixed $expectedValue
*/
public function __construct($moduleName, $type, $moduleDirectory = null, $expectedValue = null)
{
$this->_expectedValueValidation += array(
self::TYPE_SETUP_DEFINED => array(false, 'is_string', 'string'),
self::TYPE_SETUP_SCHEME_EXISTS => array(false, 'is_string', 'string'),
self::TYPE_SETUP_DATA_EXISTS => array(false, 'is_string', 'string'),
);
$this->_typesWithDiff[] = self::TYPE_SETUP_DEFINED;
$this->_typesWithDiff[] = self::TYPE_SETUP_SCHEME_EXISTS;
$this->_typesWithDiff[] = self::TYPE_SETUP_DATA_EXISTS;
parent::__construct(
self::XML_PATH_RESOURCES_NODE,
$type,
$expectedValue
);
$this->_moduleName = $moduleName;
$this->_moduleDirectory = $moduleDirectory;
if (($this->_type === self::TYPE_SETUP_SCHEME_EXISTS || $this->_type === self::TYPE_SETUP_DATA_EXISTS)
&& !is_dir($moduleDirectory)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'real directory', $moduleDirectory);
}
}
/**
* Returns list of module setup resources
*
* @param Varien_Simplexml_Element $xml
* @return array
*/
protected function getModuleSetupResources(Varien_Simplexml_Element $xml)
{
$resourcesForModule = array();
foreach ($xml->children() as $resourceNode) {
if (isset($resourceNode->setup->module)
&& (string)$resourceNode->setup->module === $this->_moduleName) {
$resourcesForModule[] = $resourceNode->getName();
}
}
return $resourcesForModule;
}
/**
* Checks definition of expected resource name
*
* @param Varien_Simplexml_Element $other
*/
protected function evaluateSetupDefined($other)
{
$moduleResources = $this->getModuleSetupResources($other);
if ($this->_expectedValue === null) {
$this->_expectedValue = empty($moduleResources) ?
strtolower($this->_moduleName) . '_setup' :
current($moduleResources);
}
$this->setActualValue($moduleResources);
return in_array($this->_expectedValue, $this->_actualValue);
}
/**
* Represents constraint for definition of setup resources
*
* @return string
*/
public function textSetupDefined()
{
return sprintf('contains resource definition for %s module with %s name',
$this->_moduleName, $this->_expectedValue);
}
/**
* Set actual value for comparison from module sql/data directories
*
* @param string $type
* @return EcomDev_PHPUnit_Constraint_Config_Resource
*/
protected function setActualValueFromResourceDirectories($type = 'sql')
{
if (!is_dir($this->_moduleDirectory . DIRECTORY_SEPARATOR . $type)) {
$this->setActualValue(array());
return $this;
}
$dirIterator = new DirectoryIterator($this->_moduleDirectory . DIRECTORY_SEPARATOR . $type);
$resourceDirectories = array();
foreach ($dirIterator as $entry) {
/* @var $entry DirectoryIterator */
if ($entry->isDir() && !$entry->isDot()) {
$resourceDirectories[] = $entry->getBasename();
}
}
$this->setActualValue($resourceDirectories);
return $this;
}
/**
* Checks existence and definition of expected resource name schema directory
*
* @param Varien_Simplexml_Element $other
*/
protected function evaluateSetupSchemeExists($other)
{
$moduleResources = $this->getModuleSetupResources($other);
if ($this->_expectedValue === null) {
$this->_expectedValue = empty($moduleResources) ?
strtolower($this->_moduleName) . '_setup' :
current($moduleResources);
}
$this->setActualValueFromResourceDirectories('sql');
return in_array($this->_expectedValue, $moduleResources)
&& in_array($this->_expectedValue, $this->_actualValue);
}
/**
* Represents constraint for definition of setup resources
*
* @return string
*/
public function textSetupSchemeExists()
{
return sprintf(' schema directory is created for %s module with %s name',
$this->_moduleName, $this->_expectedValue);
}
/**
* Checks existence and definition of expected resource name data directory
*
* @param Varien_Simplexml_Element $other
*/
protected function evaluateSetupDataExists($other)
{
$moduleResources = $this->getModuleSetupResources($other);
if ($this->_expectedValue === null) {
$this->_expectedValue = empty($moduleResources) ?
strtolower($this->_moduleName) . '_setup' :
current($moduleResources);
}
$this->setActualValueFromResourceDirectories('data');
return in_array($this->_expectedValue, $moduleResources)
&& in_array($this->_expectedValue, $this->_actualValue);
}
/**
* Represents constraint for definition of setup resources
*
* @return string
*/
public function textSetupDataExists()
{
return sprintf(' data directory is created for %s module with %s name', $this->_moduleName, $this->_expectedValue);
}
/**
* Custom failure description for showing config related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that setup resources %s.',
$this->toString()
);
}
}
<?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>
*/
/**
* Setup resources configuration constraint
*
*/
class EcomDev_PHPUnit_Constraint_Config_Resource_Script
extends EcomDev_PHPUnit_Constraint_Config_Abstract
{
const XML_PATH_RESOURCES_NODE = 'global/resources';
const TYPE_SCRIPT_SCHEME = 'script_scheme';
const TYPE_SCRIPT_DATA = 'script_data';
const FILE_INSTALL_SCHEME = '/^(mysql4-install|install)-([\\d\\.]+)$/';
const FILE_UPGRADE_SCHEME = '/^(mysql4-upgrade|upgrade)-([\\d\\.]+)-([\\d\\.]+)$/';
const FILE_INSTALL_DATA = '/^(mysql4-data-install|data-install)-([\\d\\.]+)$/';
const FILE_UPGRADE_DATA = '/^(mysql4-data-upgrade|data-upgrade)-([\\d\\.]+)-([\\d\\.]+)$/';
/**
* Name of the module for constraint
*
* @var string
*/
protected $_moduleName = null;
/**
* The module directory for constraint
*
* @var string
*/
protected $_moduleDirectory = null;
/**
* Resource name where to look for scripts
*
* @var string
*/
protected $_resourceName = null;
/**
* Contraint for evaluation of module config node
*
* @param string $nodePath
* @param string $type
* @param string $moduleDirectory
* @param mixed $expectedValue
*/
public function __construct($moduleName, $type, $moduleDirectory, $resourceName = null, $expectedVersions = null)
{
$this->_typesWithDiff[] = self::TYPE_SCRIPT_SCHEME;
$this->_typesWithDiff[] = self::TYPE_SCRIPT_DATA;
parent::__construct(
self::XML_PATH_RESOURCES_NODE,
$type,
$expectedVersions
);
$this->_moduleName = $moduleName;
$this->_moduleDirectory = $moduleDirectory;
$this->_resourceName = $resourceName;
if (!is_dir($moduleDirectory)) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'real directory', $moduleDirectory);
}
}
/**
* Returns setup resource for module setup scripts
*
* @param Varien_Simplexml_Element $xml
* @return string
*/
protected function getResourceName(Varien_Simplexml_Element $xml)
{
foreach ($xml->children() as $resourceNode) {
if (isset($resourceNode->setup->module)
&& (string)$resourceNode->setup->module === $this->_moduleName) {
return $resourceNode->getName();
}
}
return false;
}
/**
* Returns list of scripts that are presented in resource directory
*
* @param string|array $directory
* @param string $fromVersion
*/
protected function parseVersions($directory)
{
if (is_array($directory)) {
// For multiple directories merge result together
$result = array();
foreach ($directory as $entry) {
$result = array_merge_recursive($result, $this->parseVersions($entry));
}
// Sort install scripts by version
usort($result['install'], array($this, 'compareVersions'));
// Sort upgrade scripts by version
usort($result['upgrade'], array($this, 'compareVersions'));
return $result;
}
$versions = array(
'scheme' => array(
'install' => array(),
'upgrade' => array()
),
'data' => array(
'install' => array(),
'upgrade' => array()
)
);
if (!is_dir($directory)) {
return $versions;
}
$directoryIterator = new DirectoryIterator($directory);
$matchMap = array(
self::FILE_INSTALL_SCHEME => array('scheme', 'install'),
self::FILE_UPGRADE_SCHEME => array('scheme', 'upgrade'),
self::FILE_INSTALL_DATA => array('data', 'install'),
self::FILE_UPGRADE_DATA => array('data', 'upgrade')
);
foreach ($directoryIterator as $entry) {
/* @var $entry SplFileInfo */
// We do not support scheme upgrade scripts with .sql
// file extension, since it is not the best practice.
if ($entry->isFile() && substr($entry->getBasename(), -4) === '.php') {
foreach ($matchMap as $pattern => $target) {
// Fulfill versions array
if (preg_match($pattern, $entry->getBasename('.php'), $match)) {
$versions[$target[0]][$target[1]][] = array(
'filename' => $entry->getBasename(),
'prefix' => $match[1],
'from' => $match[2],
'to' => isset($match[3]) ? $match[3] : null
);
}
}
}
}
return $versions;
}
/**
* Compares two versions array
*
* @param array $first
* @param array $next
* @return int
*/
protected function compareVersions($first, $next)
{
$result = version_compare($first['from'], $next['from']);
if ($result === 0) {
/* if file with type specified, it has more priority */
$result = (strpos($first['prefix'], 'mysql4') ? 1 : -1);
}
return $result;
}
/**
* Returns list of version scripts including expected and actual information
*
* @param array $versions
* @param string $from
* @param string $to
* @param string $scriptPrefix
* @return array with keys expected and actual
*/
protected function getVersionScriptsDiff($versions, $from = null, $to = null, $scriptPrefix = '')
{
if ($from === null && end($versions['install'])) {
$version = end($versions['install']);
$from = $version['from'];
reset($versions['install']);
} elseif ($from === null && reset($versions['upgrade'])) {
$version = reset($versions['upgrade']);
$from = $version['from'];
}
if ($to === null && end($versions['upgrade'])) {
$version = end($versions['upgrade']);
$to = $version['to'];
} elseif ($to === null) {
$to = $from;
}
$actualVersions = array();
$expectedVersions = array();
$latestVersionFound = null;
if (empty($versions['install']) && $from !== null) {
$expectedVersions[] = sprintf('install-%s.php', $scriptPrefix, $from);
$latestVersionFound = $from;
} elseif ($from !== null) {
foreach ($versions['install'] as $index=>$version) {
if (version_compare($version['from'], $from) <= 0
&& (!isset($versions['install'][$index+1]['from'])
|| version_compare($versions['install'][$index+1]['from'], $from) > 0)) {
$latestVersionFound = $version['from'];
$actualVersions[] = $version['filename'];
$expectedVersions[] = $version['filename'];
break;
}
}
} elseif (!empty($versions['install'])) {
$version = current($versions['install']);
$latestVersionFound = $version['from'];
$actualVersions[] = $version['filename'];
$expectedVersions[] = $version['filename'];
} else {
$expectedVersions[] = sprintf('%sinstall-%s.php', $scriptPrefix, $to);
$latestVersionFound = $to;
}
foreach ($versions['upgrade'] as $version) {
$fromCompare = version_compare($version['from'], $latestVersionFound);
if ($fromCompare < 0) {
continue;
}
if ($fromCompare > 0) {
$expectedVersions[] = sprintf('%supgrade-%s-%s.php', $scriptPrefix, $latestVersionFound, $version['from']);
}
$actualVersions[] = $version['filename'];
$expectedVersions[] = $version['filename'];
$latestVersionFound = $version['to'];
}
if ($to !== null && version_compare($latestVersionFound, $to) === -1) {
$expectedVersions[] = sprintf('%supgrade-%s-%s.php', $scriptPrefix, $latestVersionFound, $to);
} elseif ($to !== null && version_compare($latestVersionFound, $to) === 1 && $expectedVersions) {
array_pop($expectedVersions);
}
return array(
'actual' => $actualVersions,
'expected' => $expectedVersions
);
}
/**
* Checks structure of the schme setup scripts for a module
*
* @param Varien_Simplexml_Element $other
* @return boolean
*/
protected function evaluateScriptScheme($other)
{
if ($this->_resourceName === null) {
$this->_resourceName = $this->getResourceName($other);
}
$from = isset($this->_expectedValue[0]) ? $this->_expectedValue[0] : null;
$to = isset($this->_expectedValue[1]) ? $this->_expectedValue[1] : null;
$versions = $this->parseVersions(
$this->_moduleDirectory . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR . $this->_resourceName
);
$diff = $this->getVersionScriptsDiff($versions['scheme'], $from, $to);
$this->setActualValue($diff['actual']);
$this->_expectedValue = $diff['expected'];
return $this->_actualValue == $this->_expectedValue;
}
/**
* Text represetnation of scheme setup scripts versions chain
*
* @return
*/
public function textScriptScheme()
{
return 'scheme setup scripts are created in correct version chain order';
}
/**
* Checks structure of the data setup scripts for a module
*
* @param Varien_Simplexml_Element $other
* @return boolean
*/
protected function evaluateScriptData($other)
{
if ($this->_resourceName === null) {
$this->_resourceName = $this->getResourceName($other);
}
$from = isset($this->_expectedValue[0]) ? $this->_expectedValue[0] : null;
$to = isset($this->_expectedValue[1]) ? $this->_expectedValue[1] : null;
$versions = $this->parseVersions(
array(
$this->_moduleDirectory . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . $this->_resourceName,
$this->_moduleDirectory . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR . $this->_resourceName
)
);
$diff = $this->getVersionScriptsDiff($versions['data'], $from, $to);
$this->setActualValue($diff['actual']);
$this->_expectedValue = $diff['expected'];
return $this->_actualValue == $this->_expectedValue;
}
/**
* Text represetnation of scheme setup scripts versions chain
*
* @return
*/
public function textScriptData()
{
return 'data setup scripts are created in correct version chain order';
}
/**
* Custom failure description for showing config related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that setup resources %s.',
$this->toString()
);
}
}
<?php
/**
* Table alias constraint
*
*/
class EcomDev_PHPUnit_Constraint_Config_TableAlias
extends EcomDev_PHPUnit_Constraint_Config_Abstract
{
const XML_PATH_MODELS = 'global/models';
const TYPE_TABLE_ALIAS = 'table_alias';
/**
* Table alias name, e.g. the name of the table within resource
*
* @var string
*/
protected $_tableAliasName = null;
/**
* Table alias prefix,
* e.g. the prefix for tables of a particular resource model
*
* @var string
*/
protected $_tableAliasPrefix = null;
/**
* Constraint for evaluation of table alias
*
* @param string $tableAlias
* @param string $expectedTableName
* @param string $type
*/
public function __construct($tableAlias, $expectedTableName, $type = self::TYPE_TABLE_ALIAS)
{
if (!strpos($tableAlias, '/')) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'table alias', $tableAlias);
}
list($this->_tableAliasPrefix, $this->_tableAliasName) = explode('/', $tableAlias, 2);
$this->_expectedValueValidation += array(
self::TYPE_TABLE_ALIAS => array(true, 'is_string', 'string')
);
$this->_typesWithDiff[] = self::TYPE_TABLE_ALIAS;
parent::__construct(self::XML_PATH_MODELS, $type, $expectedTableName);
}
/**
* Evaluates table alias is mapped to expected table name
*
* @param Varien_Simplexml_Element $other
* @return boolean
*/
protected function evaluateTableAlias($other)
{
if (!isset($other->{$this->_tableAliasPrefix})) {
$this->setActualValue(false);
return false;
}
$modelNode = $other->{$this->_tableAliasPrefix};
if (!isset($modelNode->entities) && isset($other->{(string)$modelNode->resourceModel})) {
$modelNode = $other->{(string)$modelNode->resourceModel};
}
if (isset($modelNode->entities->{$this->_tableAliasName}->table)) {
$tableName = (string)$modelNode->entities->{$this->_tableAliasName}->table;
} else {
$tableName = false;
}
$this->setActualValue($tableName);
return $this->_actualValue === $this->_expectedValue;
}
/**
* Text representation of table alias constaint
*
* @return string
*/
protected function textTableAlias()
{
return 'is mapped to table name';
}
/**
* Custom failure description for showing config related errors
* (non-PHPdoc)
* @see PHPUnit_Framework_Constraint::customFailureDescription()
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf(
'Failed asserting that table alias "%s/%s" %s.',
$this->_tableAliasPrefix, $this->_tableAliasName,
$this->toString()
);
}
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -27,12 +27,16 @@ class EcomDev_PHPUnit_Constraint_Exception extends PHPUnit_Framework_Expectation
public function __construct($description, $diff = '', $message = '')
{
if (!is_scalar($diff)) {
$diff = print_r($diff, true);
if (!$diff instanceof PHPUnit_Framework_ComparisonFailure) {
if (!is_scalar($diff)) {
$diff = print_r($diff, true);
}
$this->diff = $diff;
$diff = null;
}
$this->diff = $diff;
parent::__construct($description, null, $message);
parent::__construct($description, $diff);
}
public function toString()
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -278,8 +278,6 @@ class EcomDev_PHPUnit_Constraint_Layout_Block extends EcomDev_PHPUnit_Constraint
return sprintf('block "%s" is an instance of %s', $this->_blockName, $this->_expectedValue);
}
/**
* Evaluates that layout block is a root level block
*
......@@ -305,4 +303,29 @@ class EcomDev_PHPUnit_Constraint_Layout_Block extends EcomDev_PHPUnit_Constraint
{
return sprintf('block "%s" is a root level one', $this->_blockName);
}
/**
* Evaluates that layout block is a child block of expected one
*
* @param EcomDev_PHPUnit_Constraint_Layout_Logger_Interface $other
* @return boolean
*/
protected function evaluateParentName($other)
{
$this->setActualValue(
$other->getBlockParent($this->_blockName)
);
return $this->_actualValue === $this->_expectedValue;
}
/**
* Text representation of a root level block assertion
*
* @return string
*/
protected function textParentName()
{
return sprintf('block "%s" is a child of expected block', $this->_blockName);
}
}
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......
......@@ -11,7 +11,7 @@
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @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>
*/
......@@ -44,6 +44,23 @@ class EcomDev_Utils_Reflection
$reflectionProperty->setValue((is_string($object) ? null : $object), $value);
}
/**
* Sets multiple restricted property values for an object
*
* @param string|object $object class name
* @param array $properties
*/
public static function setRestrictedPropertyValues($object, array $properties)
{
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
throw new RuntimeException('For setting of restricted properties via Reflection, PHP version should be 5.3.0 or later');
}
foreach ($properties as $property => $value) {
self::setRestrictedPropertyValue($object, $property, $value);
}
}
/**
* Gets protected or private property value
*
......
# EcomDev_PHPUnit definition
UnitTests.php UnitTests.php
app/etc/modules/EcomDev_PHPUnit.xml app/etc/modules/EcomDev_PHPUnit.xml
app/etc/local.xml.phpunit app/etc/local.xml.phpunit
app/code/community/EcomDev/PHPUnit app/code/community/EcomDev/PHPUnit
lib/EcomDev/PHPUnit lib/EcomDev/PHPUnit
lib/EcomDev/Utils lib/EcomDev/Utils
lib/Spyc lib/Spyc
# Copy local.xml.phpunit if it doesn't already exist
@shell \
LOCALXML=app/etc/local.xml.phpunit; \
if [ ! -f $PROJECT/$LOCALXML ]; then \
cp $MODULE/$LOCALXML $PROJECT/$LOCALXML; \
fi
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