Commit 01c3f715 authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

! closes feature #56 "Set mock to Magento factories"

! closes feature #55 "Create mock by class alias"
parent d6d016a1
...@@ -32,6 +32,9 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -32,6 +32,9 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// Admin store code // Admin store code
const ADMIN_STORE_CODE = 'admin'; const ADMIN_STORE_CODE = 'admin';
const REGISTRY_PATH_LAYOUT_SINGLETON = '_singleton/core/layout';
const XML_PATH_LAYOUT_MODEL_FOR_TEST = 'phpunit/suite/layout/model';
/** /**
* Old configuration model to be returned back * Old configuration model to be returned back
* after unit tests are finished * after unit tests are finished
...@@ -122,8 +125,15 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -122,8 +125,15 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
*/ */
public function initTest() public function initTest()
{ {
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
// If garbage collector is not enabled,
// we enable it for tests
if (!gc_enabled()) {
gc_enable();
}
}
$this->_config = Mage::getConfig(); $this->_config = Mage::getConfig();
$this->_config->setOptions($options);
$this->_initBaseConfig(); $this->_initBaseConfig();
$this->_initCache(); $this->_initCache();
...@@ -152,6 +162,12 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -152,6 +162,12 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
Mage_Core_Model_Resource_Setup::applyAllDataUpdates(); Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
} }
$layoutModel = Mage::getModel(
$this->getConfig()->getNode(self::XML_PATH_LAYOUT_MODEL_FOR_TEST)
);
Mage::register(self::REGISTRY_PATH_LAYOUT_SINGLETON, $layoutModel, true);
return $this; return $this;
} }
......
...@@ -31,6 +31,13 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config ...@@ -31,6 +31,13 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
*/ */
protected $_scopeSnapshot = null; protected $_scopeSnapshot = null;
/**
* List of replaced instance creation
*
* @return array
*/
protected $_replaceInstanceCreation = array();
/** /**
* Load config data from DB * Load config data from DB
* *
...@@ -47,6 +54,62 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config ...@@ -47,6 +54,62 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
return $this; return $this;
} }
/**
* Replaces creation of some instance by mock object
*
*
* @param string $type
* @param string $classAlias
* @param PHPUnit_Framework_MockObject_MockObject|PHPUnit_Framework_MockObject_MockBuilder $mock
* @return EcomDev_PHPUnit_Model_Config
*/
public function replaceInstanceCreation($type, $classAlias, $mock)
{
$this->_replaceInstanceCreation[$type][$classAlias] = $mock;
return $this;
}
/**
* Flushes instance creation instruction list
*
* @return EcomDev_PHPUnit_Model_Config
*/
public function flushReplaceInstanceCreation()
{
$this->_replaceInstanceCreation = array();
return $this;
}
/**
* Overriden for test case model instance creation mocking
*
* (non-PHPdoc)
* @see Mage_Core_Model_Config::getModelInstance()
*/
public function getModelInstance($modelClass='', $constructArguments=array())
{
if (!isset($this->_replaceInstanceCreation['model'][$modelClass])) {
return parent::getModelInstance($modelClass='', $constructArguments=array());
}
return $this->_replaceInstanceCreation['model'][$modelClass];
}
/**
* Overriden for test case model instance creation mocking
*
* (non-PHPdoc)
* @see Mage_Core_Model_Config::getModelInstance()
*/
public function getResourceModelInstance($modelClass='', $constructArguments=array())
{
if (!isset($this->_replaceInstanceCreation['resource_model'][$modelClass])) {
return parent::getResourceModelInstance($modelClass='', $constructArguments=array());
}
return $this->_replaceInstanceCreation['resource_model'][$modelClass];
}
/** /**
* Loads scope snapshot * Loads scope snapshot
* *
......
<?php
// Loading Spyc yaml parser,
// becuase Symfony component is not working propertly with nested
require_once 'Spyc/spyc.php';
class EcomDev_PHPUnit_Model_Expectation
implements EcomDev_PHPUnit_Model_Expectation_Interface
{
/**
* List of created data object ids by path format
*
* @var array
*/
protected $_dataObjectIds = array();
/**
* Loaded data from Yaml files
*
* @var Varien_Object
*/
protected $_loadedData = null;
/**
* Data object used for managing
* expectation data
*
* @var string
*/
protected $_dataObjectClassAlias = 'ecomdev_phpunit/expectation_object';
/**
* Returns class alias for fixture data object
*
* @return string
*/
public function getDataObjectClassAlias()
{
return $this->_dataObjectClassAlias;
}
/**
* Retrieves data object for a particular path format
*
* @see EcomDev_PHPUnit_Model_Expectation_Interface::getDataObject()
*/
public function getDataObject($pathFormat = null, $args = array())
{
if ($pathFormat === null) {
return $this->_loadedData;
}
$argsHash = $pathFormat . '_' . md5(serialize($args));
// Check already created objects by path
if (!isset($this->_dataObjectIds[$argsHash])) {
if ($args) {
array_unshift($args, $pathFormat);
$dataPath = call_user_func_array('sprintf', $args);
} else {
$dataPath = $pathFormat;
}
$data = $this->_loadedData->getData($dataPath);
if (!is_array($data)) {
throw new InvalidArgumentException(
'Argument values for specifying special scope of expectations should be presented '
. ' in expectation file and should be an associative list (path: "' . $dataPath . '")'
);
}
$this->_dataObjectIds[$argsHash] = Mage::objects()->save(
Mage::getModel($this->getDataObjectClassAlias(), $data)
);
}
return Mage::objects($this->_dataObjectIds[$argsHash]);
}
/**
* Applies loaded data
*
* @see EcomDev_PHPUnit_Model_Test_Loadable_Interface::apply()
*/
public function apply()
{
// For now it does nothing :(
return $this;
}
/**
* Removes objects created in object cache
* Clears loaded data property
*
* @see EcomDev_PHPUnit_Model_Test_Loadable_Interface::discard()
*/
public function discard()
{
foreach ($this->_dataObjectIds as $objectId) {
Mage::objects()->delete($objectId);
}
$this->_dataObjectIds = array();
$this->_loadedData = null;
return $this;
}
/**
* Check that expectations is loaded
*
* @return boolean
*/
public function isLoaded()
{
return $this->_loadedData !== null;
}
/**
* Loads expected data from test case annotations
*
* @see EcomDev_PHPUnit_Model_Test_Loadable_Interface::loadByTestCase()
*/
public function loadByTestCase(EcomDev_PHPUnit_Test_Case $testCase)
{
$expectations = $testCase->getAnnotationByName('loadExpectation');
if (!$expectations) {
$expectations[] = null;
}
$expectationData = array();
foreach ($expectations as $expectation) {
if (empty($expectation)) {
$expectation = null;
}
$expectationFile = $testCase->getYamlFilePath('expectations', $expectation);
if (!$expectationFile) {
$text = 'There was no expectation defined for current test case';
if ($expectation) {
$text = sprintf('Cannot load expectation %s', $expectation);
}
throw new RuntimeException($text);
}
$expectationData = array_merge_recursive(
$expectationData, Spyc::YAMLLoad($expectationFile)
);
}
$this->_loadedData = new Varien_Object($expectationData);
return $this;
}
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for fixture model
* Can be used for creation of
* absolutely different implementation of fixture,
* then current one.
*
*/
interface EcomDev_PHPUnit_Model_Expectation_Interface extends EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/**
* Returns data object with expectations
*
* @param string $pathFormat
* @param array $args arguments for format function
* @return EcomDev_PHPUnit_Model_Expectation_Object
*/
public function getDataObject($pathFormat = null, $args = array());
/**
* Check is expectation loaded
*
* @return boolean
*/
public function isLoaded();
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Expectation data object used for retrieving of data from expectations array
* Created to make possible iteration of expected data,
* for instance if you have list of orders
*
*/
class EcomDev_PHPUnit_Model_Expectation_Object
extends Varien_Object
implements Iterator
{
protected $_createdObjectIds = array();
/**
* Current key in iterator
*
* @var array
*/
protected $_iterationKeys = array();
/**
* If current element is an array,
* then it will be automatically wrapped by
* the same class instance as this one
*
* @see Iterator::current()
* @return null|int|string|boolean|decimal|EcomDev_PHPUnit_Model_Expectation_Object
*/
public function current()
{
if ($this->key() === null) {
return null;
}
$current = $this->_data[$this->key()];
if (is_array($current)) {
$newObject = new self($current);
$this->_createdObjectIds = Mage::objects()
->save($current);
return $newObject;
}
return $current;
}
/* (non-PHPdoc)
* @see Iterator::key()
*/
public function key()
{
return current($this->_iterationKeys);
}
/* (non-PHPdoc)
* @see Iterator::next()
*/
public function next()
{
next($this->_iterationKeys);
}
/* (non-PHPdoc)
* @see Iterator::rewind()
*/
public function rewind()
{
$this->_iterationKeys = $this->keys();
}
/* (non-PHPdoc)
* @see Iterator::valid()
*/
public function valid()
{
return key($this->_iterationKeys) !== null;
}
/**
* Object destructor removes
* created objects from object pool
*
*
*/
public function __destruct()
{
if (!empty($this->_createdObjectIds)) {
foreach ($this->_createdObjectIds as $objectId) {
Mage::objects()->delete($objectId);
}
}
}
/**
* Returns data array keys
*
* @return array
*/
public function keys()
{
return array_keys($this->_data);
}
/**
* Returns data array values
*
* @return array
*/
public function values()
{
return array_values($this->_data);
}
}
...@@ -26,7 +26,9 @@ require_once 'Spyc/spyc.php'; ...@@ -26,7 +26,9 @@ require_once 'Spyc/spyc.php';
* Created for operations with different fixture types * Created for operations with different fixture types
* *
*/ */
class EcomDev_PHPUnit_Model_Fixture extends Mage_Core_Model_Abstract class EcomDev_PHPUnit_Model_Fixture
extends Mage_Core_Model_Abstract
implements EcomDev_PHPUnit_Model_Fixture_Interface
{ {
// Configuration path for eav loaders // Configuration path for eav loaders
const XML_PATH_FIXTURE_EAV_LOADERS = 'phpunit/suite/fixture/eav'; const XML_PATH_FIXTURE_EAV_LOADERS = 'phpunit/suite/fixture/eav';
...@@ -114,6 +116,36 @@ class EcomDev_PHPUnit_Model_Fixture extends Mage_Core_Model_Abstract ...@@ -114,6 +116,36 @@ class EcomDev_PHPUnit_Model_Fixture extends Mage_Core_Model_Abstract
return $this; return $this;
} }
/**
* Loads fixture from test case annotations
*
* @param EcomDev_PHPUnit_Test_Case $testCase
* @return EcomDev_PHPUnit_Model_Fixture
*/
public function loadByTestCase(EcomDev_PHPUnit_Test_Case $testCase)
{
$fixtures = $testCase->getAnnotationByName(
'loadFixture',
array('class', 'method')
);
foreach ($fixtures as $fixture) {
if (empty($fixture)) {
$fixture = null;
}
$filePath = $testCase->getYamlFilePath('fixtures', $fixture);
if (!$filePath) {
throw new RuntimeException('Unable to load fixture for test');
}
$this->loadYaml($filePath);
}
return $this;
}
/** /**
* Load YAML file * Load YAML file
* *
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for fixture model
* Can be used for creation of
* absolutely different implementation of fixture,
* then current one.
*
*/
interface EcomDev_PHPUnit_Model_Fixture_Interface extends EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/**
* Sets fixture options
*
* @param array $options
* @return EcomDev_PHPUnit_Model_Fixture_Interface
*/
public function setOptions(array $options);
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Layout model that adds additional functionality
* for testing the layout itself
*
*/
class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
{
/**
* List of replaced blocks creation
*
* @return array
*/
protected $_replaceBlockCreation = array();
/**
* Replaces creation of some block by mock object
*
* @param string $classAlias
* @param PHPUnit_Framework_MockObject_MockObject|PHPUnit_Framework_MockObject_MockBuilder $mock
* @return EcomDev_PHPUnit_Model_Layout
*/
public function replaceBlockCreation($classAlias, $mock)
{
$this->_replaceBlockCreation[$classAlias] = $mock;
return $this;
}
/**
* Flushes instance creation instruction list
*
* @return EcomDev_PHPUnit_Model_Layout
*/
public function flushReplaceBlockCreation()
{
$this->_replaceBlockCreation = array();
return $this;
}
/**
* Overriden for possibility of replacing a block by mock object
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::_getBlockInstance()
*/
protected function _getBlockInstance($block, array $attributes=array())
{
if (!isset($this->_replaceBlockCreation[$block])) {
return parent::_getBlockInstance($block, $attributes);
}
return $this->_replaceBlockCreation[$block];
}
/**
* Resets layout instance properties
*
* @return EcomDev_PHPUnit_Model_Layout
*/
public function reset()
{
$this->setXml(simplexml_load_string('<layout/>', $this->_elementClass));
$this->_update = Mage::getModel('core/layout_update');
$this->_area = null;
$this->_helpers = array();
$this->_directOutput = false;
$this->_output = array();
foreach ($this->_blocks as $block) {
// Remove references between blocks
$block->setParentBlock(null);
$block->setMessageBlock(null);
$block->unsetChildren();
}
$this->_blocks = array();
$this->flushReplaceBlockCreation();
return $this;
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for loadable test environment data
*
*/
interface EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/**
* Loads external data by test case instance
*
* @param EcomDev_PHPUnit_Test_Case $testCase
* @return EcomDev_PHPUnit_Model_Test_Loadable_Interface
*/
public function loadByTestCase(EcomDev_PHPUnit_Test_Case $testCase);
/**
* Applies external data
*
* @return EcomDev_PHPUnit_Model_Test_Loadable_Interface
*/
public function apply();
/**
* Reverts applied data
*
* @return EcomDev_PHPUnit_Model_Test_Loadable_Interface
*/
public function discard();
}
...@@ -51,9 +51,16 @@ ...@@ -51,9 +51,16 @@
<helpers>Helper</helpers> <helpers>Helper</helpers>
<blocks>Block</blocks> <blocks>Block</blocks>
</groups> </groups>
<!-- Test suite that will be used for creation of each of the tests --> <layout>
<test_suite>EcomDev_PHPUnit_Test_Suite_Group</test_suite> <model>ecomdev_phpunit/layout</model>
</layout>
<expectation>
<!-- Default model for loading of expectations -->
<model>ecomdev_phpunit/expectation</model>
</expectation>
<fixture> <fixture>
<!-- Default model for loading of fixtures -->
<model>ecomdev_phpunit/fixture</model>
<eav> <eav>
<!-- Here goes the list of fixture loaders for EAV <!-- Here goes the list of fixture loaders for EAV
If no fixture loader is specified for entity, then default will be used If no fixture loader is specified for entity, then default will be used
......
<?php <?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
class EcomDev_Utils_Reflection class EcomDev_Utils_Reflection
{ {
......
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