Codeception Functional and Acceptance Tests
Implementation of state safe functional and acceptance tests.
Example for Functional and/or Acceptance tests
use SuiteCRM;
class SigninCest extends StateCheckerCestAbstract
{
public function tryToTest(AcceptanceTester $I)
{
$I->wantTo('test my page');
}
}
Implementation of state checker Codeception tests, class StateCheckerPHPUnitTestCaseAbstract extends PHPUnit_Framework_TestCase and override setUp() and tearDown() methods so if you want to call these methods in the inheritance test classes you should call parent::setUp() and parent::tearDown() in it.
Implementation of state checker Codeception tests, class StateCheckerUnitAbstract extends Codeception\Test\Unit and override _before() and _after() methods so if you want to call these methods in the inheritance test classes you should call parent::_before() and parent::_after() in it.
Implementation of state checker Codeception tests, it uses _before() and _after() methods so if you want to call these methods in the heritance test classes you should call parent::_before() and parent::_after() in it.
Used in state checker Codeception tests.
Used in state checker tests.
$ vendor/bin/codecept run unit -f --steps -vvv --debug
$ vendor/bin/codecept run unit -f --steps -vvv --debug /path/to/YourTest.php
By default the state checker tests store and check the system state only before and after the test classes.
You can manipulate this behavior in your config_override.php
with
$sugar_config['state_checker']['test_state_check_mode']
value OR
just simply switch on/off the developer mode in administration panel.
See more at class SuiteCRM\StateCheckerConfig
Slow working but give a detailed information about which test method change the state in the class.
You can manipulate this behavior in your config_override.php
with
$sugar_config['state_checker']['test_state_check_mode']
value OR
just simply switch on/off the developer mode in administration panel.
See more at class SuiteCRM\StateCheckerConfig
State Safe Tests
StateSaver
and StateChecker
-
State check library for SuperGlobals, FileSystem and DataBase etc.
(Implemented for: PHP Unit tests and Codeception Cests.)
-
State saver library - helper classes for developers.
Keep the system global environment state clean, especially in tests.
If a test leaves some extra data in the database, file system or super globals etc. this could change the behaviour of the other test processes. When you write a new test make sure it is state safe, which means tests should not leave any 'garbage' data in the test environment state such as database, file system, superglobals etc..
Unit test should be stateless, developers can change class StateCheckerConfig
properties in local instance to make sure Unit tests don’t change the system state.
PHPUnit tests have to extend SuiteCRM\StateCheckerPHPUnitTestCaseAbstract
instead of PHPUnit_Framework_TestCase
.
Codeception Cests should extend SuiteCRM\StateCheckerCestAbstract
class.
(note: don’t forget to call parent::_before() and parent::_after() if you want to override these methods in your tests)
The following classes help you to write state-safe code (tests), of course you can use some of these classes in any case where you have to change and restore anything in the global system state:
Saves and checks the system state and reports any state change in the following:
See also SuiteCRM\StateChecker
class.
use SuiteCRM;
$_POST['foo'] = 'bar';
// create a new instance of StateChecker:
$stateSaver = new StateSaver();
// save all superglobals
$stateSaver->pushGlobals();
$_POST['foo'] = 'bazz';
// restore super globals
$stateSaver->popGlobals();
echo $_POST['foo']; // output: bar
use SuiteCRM;
// create a new instance of StateChecker:
$stateSaver = new StateSaver();
$stateSaver->pushTable('stufftable');
// modify your database table here. (insert/update/delete..)
...
$stateSaver->popTable('stufftable');
// restore your database table 'stufftable' here.
Example output when the test redefines superglobals:
"/usr/bin/php" "/var/www/html/SuiteCRM/vendor/bin/codecept" "run" "unit" "-f" "--steps" "-vvv" "--debug"
Cannot load Xdebug - extension already loaded
Codeception PHP Testing Framework v2.4.0
Powered by PHPUnit 4.8.36 by Sebastian Bergmann and contributors.
Unit Tests (1583) --------------------------------------------------------------
Modules: Asserts, \Helper\Unit
--------------------------------------------------------------------------------
- configTest: Test_config
✖ configTest: Test_config (16.57s)
--------------------------------------------------------------------------------
Time: 29.52 seconds, Memory: 2288.50MB
There was 1 failure:
---------
1) configTest: Test_config
Test tests/unit/configTest.php:test_config
Incorrect state hash: Hash doesn't match at key "globals::_POST"
...
`file_put_contents('foo.txt', rand(0, 1234));`
"/usr/bin/php" "/var/www/html/SuiteCRM/vendor/bin/codecept" "run" "unit" "-f" "--steps" "-vvv" "--debug"
Cannot load Xdebug - extension already loaded
Codeception PHP Testing Framework v2.4.0
Powered by PHPUnit 4.8.36 by Sebastian Bergmann and contributors.
Unit Tests (1583) --------------------------------------------------------------
Modules: Asserts, \Helper\Unit
--------------------------------------------------------------------------------
- configTest: Test_config
✖ configTest: Test_config (10.79s)
--------------------------------------------------------------------------------
Time: 23.12 seconds, Memory: 1875.00MB
There was 1 failure:
---------
1) configTest: Test_config
Test tests/unit/configTest.php:test_config
Incorrect state hash: Hash doesn't match at key "filesys::/var/www/html/SuiteCRM/foo.txt".
...
StateSaver class is a helper library, typically for test scripts but usable everywhere:
// Save state
// Create an instance of StateChecker
$state = new \SuiteCRM\StateSaver();
$state->pushGlobals(); // saving superglobals
$state->pushTable('your_module_stuffs'); // saving a database table
$state->pushFile('your_file.txt');
// Tests
// Do some test changes in superglobals
$_POST['foo'] = 'bar';
// Test changes in database tables (example only)
$stuff = BeanFactory::getBean('YourModuleStuff', '{your-module-stuff-id}');
$stuff->your_property = 'baz';
$stuff->save();
// Some changes in your test file:
file_put_contents('your-file.txt', 'New contents here: ' . rand(1, 10000));
// Clean up
$state->popFile('your_file.txt');
$state->popTable('your_module_stuffs'); // restore table
$state->popGlobals(); // restore globals
// ... here you should get the restored super globals, database tables and files.
/**
* Retrieve if any error occurred in storing/restoring processes.
*
* @return array
*/
public function getErrors();
/**
* Clear all collected error information about latest storing/restoring processes.
*/
public function clearErrors();
/**
* Retrieve if any error occurred in storing/restoring processes and
* clear all collected error information about latest storing/restoring processes.
*
* @return array
*/
public function getErrorsClear();
/**
* Save any value into state store at a key and namespace.
*
* @param mixed $value
* @param string $key
* @param string $namespace
*/
public function push($value, $key, $namespace);
/**
* Restore any value from state store at a key and namespace.
*
* @param string $key
* @param string $namespace
* @return mixed
*/
public function pop($key, $namespace);
/**
* Save a global variable into storage at an optional namespace.
*
* @param string $key
* @param string $namespace
*/
public function pushGlobal($key, $namespace = 'GLOBALS');
/**
* Restore a global value from storage at an optional namespace.
*
* @param string $key
* @param string $namespace
*/
public function popGlobal($key, $namespace = 'GLOBALS');
/**
* Save all super globals which are specified in configuration.
* @see StateCheckerConfig
*
* pushGlobals
*/
public function pushGlobals();
/**
* Restore all super globals which are specified in configuration.
* @see StateCheckerConfig
*
* popGlobals
*/
public function popGlobals();
/**
* Save all defined global variable name.
* (note: this function does not store the values, so use it carefully)
*
* pushGlobalKeys
*/
public function pushGlobalKeys();
/**
* Restore all defined global variable name.
* (note: this function does not restore the values, so use it carefully)
*
* popGlobalKeys
*/
public function popGlobalKeys();
/**
* Save Error Reporting Level into the store at an optional key and namespace.
* (note: error level should not be changed for any reason, so use it for own risk)
*
* @param string $key
* @param string $namespace
*/
public function pushErrorLevel($key = 'level', $namespace = 'error_reporting');
/**
* Restore Error Reporting Level from the store at an optional key and namespace.
* (note: error level should not be changed for any reason, so use it for own risk)
*
* @param string $key
* @param string $namespace
*/
public function popErrorLevel($key = 'level', $namespace = 'error_reporting');
/**
* Save all data from a database table into store at an optional namespace.
*
* @param string $table
* @param string $namespace
* @throws StateSaverException
*/
public function pushTable($table, $namespace = 'db_table');
/**
* Restore all data into a database table from store at an optional namespace.
*
* @param string $table
* @param string $namespace
*/
public function popTable($table, $namespace = 'db_table');
/**
* Save a file contents.
*
* @param string $filename
* @throws StateSaverException
*/
public function pushFile($filename);
/**
* Restore a file contents.
*
* @param string $filename
* @return boolean
* @throws StateSaverException
*/
public function popFile($filename);
PHP Configuration options:
/**
* Getter for PHP Configuration Options
* @see more at StateCheckerConfig::$phpConfigOptionKeys
*
* @return array
*/
public static function getPHPConfigOptions();
/**
* Setter for PHP Configuration Options
* @see more at StateCheckerConfig::$phpConfigOptionKeys
*
* @param array $configOptions
* @throws StateSaverException
*/
public static function setPHPConfigOptions($configOptions);
/**
* Store PHP Configuration Options
* @see more at StateCheckerConfig::$phpConfigOptionKeys
*
* @param string $key
* @param string $namespace
*/
public function pushPHPConfigOptions($key = 'all', $namespace = 'php_config_options');
/**
* Restore PHP Configuration Options
* @see more at StateCheckerConfig::$phpConfigOptionKeys
*
* @param string $key
* @param string $namespace
*/
public function popPHPConfigOptions($key = 'all', $namespace = 'php_config_options');
Simple Exception to catch and handle the state changes.
Saves and checks the system state and reports any state change in the following:
- Database
- File system
- Super globals
- PHP error reporting level
- PHP configuration options
See more about the SuiteCRM\StateChecker
configuration in the SuiteCRM\StateCheckerConfig
class.
use SuiteCRM;
// saving a hash of the current state at this point.
$stateChecker = new StateChecker();
// ... do something to change the current system state
try {
// getting a hash of the current state or
// throws an exception if the state doesn't match with the previously saved state.
$hash = $stateChecker->getStateHash();
} catch (StateCheckerException $e) {
// state is changed!
// use the following exception to detect / debug the problem: (optional)
$info = $e->getMessage();
}
Simple Exception to catch and handle the state changes.
Configuration of SuiteCRM\StateChecker and StateChecker Tests classes such as:
SuiteCRM\StateCheckerPHPUnitTestCaseAbstract
SuiteCRM\StateCheckerUnitAbstract
SuiteCRM\StateCheckerCestAbstract
SuiteCRM\StateCheckerConfig configuration options have default values and each is available in
$sugar_config['state_checker'][$key]
.
Each configuration value is available with a getter method:
SuiteCRM\StateCheckerConfig::get($key)
where $key
could be any of the following:
The SuperGlobals Collection determines which super globals are stored and restored.
$value = SuiteCRM\StateCheckerConfig::get('globalKeys')
array('_POST', '_GET', '_REQUEST', '_SESSION', '_SERVER', '_ENV', '_FILES', '_COOKIE')
SuiteCRM config overrides:
$sugar_config['state_checker']['global_keys']
Array of regexp for excluding files from state checking.
Tests won’t check hash for these files so won’t fail.
$value = SuiteCRM\StateCheckerConfig::get('fileExludeRegexes')
array(
'/\/\.git\//',
'/\/cache\//',
'/\.log$/',
'/\/tests\/_output\//',
'/\/blowfish\//',
'/\/upload\//',
'/\/vendor\//',
'/\/sugarfield_jjwg_maps_/',
'/\/vardefs.ext.php$/',
'/\/modules\/AOD_Index\/Index\/Index\//',
'/\/travis\/build\//',
)
SuiteCRM config overrides:
$sugar_config['state_checker']['file_exclude_regexes']
Automatically run state collection in StateChecker constructor.
$value = SuiteCRM\StateCheckerConfig::get('autoRun')
SuiteCRM config overrides:
$sugar_config['state_checker']['auto_run']
Saves trace info on state-hash mismatch
(Slow running but gives more information about the error location, use in development only)
$value = SuiteCRM\StateCheckerConfig::get('saveTraces')
SuiteCRM config overrides:
$sugar_config['state_checker']['save_traces']
Redefine memory limit
(For more memory expensive tasks, for e.g collection stack trace information when $saveTraces
is ON,
use in development only)
$value = SuiteCRM\StateCheckerConfig::get('redefineMemoryLimit')
SuiteCRM config overrides:
$sugar_config['state_checker']['redefine_memory_limit']
Stores more information about hash-mismatch, which part has state of globals/filesys/database.
(Slow working but gives more information about the error location, use in development only)
$value = SuiteCRM\StateCheckerConfig::get('storeDetails')
SuiteCRM config overrides:
$sugar_config['state_checker']['store_details']
Enum specified that tests need to check system state for Test Cases behaviour, possible values:
SuiteCRM\StateCheckerConfig::RUN_NEVER
: State check and save never runs.
SuiteCRM\StateCheckerConfig::RUN_PER_TEST
: State check runs after each test methods.
SuiteCRM\StateCheckerConfig::RUN_PER_CLASSES
: State check runs after each test class.
Note: Mode RUN_PER_CLASSES
affects PHPUnit Test Cases only
Note: Developer mode overrides this value.
$value = SuiteCRM\StateCheckerConfig::get('testStateCheckMode')
SuiteCRM\StateCheckerConfig::RUN_PER_CLASSES
SuiteCRM config overrides:
$sugar_config['state_checker']['test_state_check_mode']
Test using StateChecker
(Slow working but gives more information about the error location, use in development only)
$value = SuiteCRM\StateCheckerConfig::get('testsUseStateChecker')
SuiteCRM config overrides:
$sugar_config['state_checker']['tests_use_state_checker']
testsUseAssertionFailureOnError
Test shows up an assertion failure when there is a hash-mismatch,
use $testsUseStateChecker
also, $testsUseAssertionFailureOnError
applied only if $testsUseStateChecker = true
(use in development only)
$value = SuiteCRM\StateCheckerConfig::get('testsUseAssertionFailureOnError')
SuiteCRM config overrides:
$sugar_config['state_checker']['tests_use_assertion_failure_on_error']
Tests won’t check hash for these keys so won’t fail
(It should be empty)
$value = SuiteCRM\StateCheckerConfig::get('testsFailureExcludeKeys')
SuiteCRM config overrides:
$sugar_config['state_checker']['tests_failure_exclude_keys']
State saver needs to know which PHP configuration options to save/restore.
$value = SuiteCRM\StateCheckerConfig::get('phpConfigOptionKeys')
array('max_execution_time', 'display_errors', 'display_startup_errors')
SuiteCRM config overrides:
$sugar_config['state_checker']['php_configuration_option_keys']