SimpleTester on CodeIgniter fails with "Class 'GroupTest' not found" - unit-testing

I'm trying to do a clean install SimpleTester on a new CodeIgniter application, following the instructions here: http://codeigniter.com/wiki/SimpleTester_-_Unit_testing_library
Everything's fine until step 6, when I add "simpletester" to the list of libraries that are autoloaded. As soon as I do that, visiting any page simply results in:
Fatal error: Class 'GroupTest' not found in
/path/to/app/application/libraries/simpletester.php on line 84
Grepping through the code for GroupTest I only see it referenced in comments, and in a readme file which states the following:
The GroupTest has been renamed TestSuite (see below).
It was removed completely in 1.1 in favour of this
name.
I tried modifying line 84 to replace GroupTest with TestSuite, but then I get the following error:
Fatal error: Call to undefined method TestSuite::addTestFile() in
/home/path/to/app/application/libraries/simpletester.php
on line 96
Is this a bug on their end? Has anyone seen this before?

I have run into the same issue. The GroupTest class can be found in test_case.php of version 1.0.1 of SimpleTest:
http://sourceforge.net/projects/simpletest/files/simpletest/simpletest_1.0.1/
Unfortunately, simply inserting v1.0.1 into the libraries folder doesn’t solve all the world’s problems. I no longer get the “Fatal error: Class ‘GroupTest’ not found ...” error, but I do get a segmentation fault and my site no longer works.
I have briefly tried to track down the issue but to no avail.
Note: I also responded on the CodeIgniter Wiki page containing the same question.

I had the same problem with a current project and found that the problem is that GroupTest was replaced with TestSuite which works a little differently.
This is the library code I use:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
$libraryDir = APPPATH . 'libraries/simpletest';
if(!is_dir($libraryDir))
exit("Simpletest must be located in \"$libraryDir\"");
require_once $libraryDir . '/unit_tester.php';
require_once $libraryDir . '/mock_objects.php';
require_once $libraryDir . '/collector.php';
class SimpleTester
{
/**
* What reporter should be used for display.
* Could be either HtmlReporter, SmallReporter, MinimalReporter or ShowPasses.
*/
public $Reporter = 'MinimalReporter';
private $testDir;
private $testTitle;
private $fileExtension;
public function __construct($params = false)
{
$ci =& get_instance();
$ci->config->load('simpletester');
if($params == false) {
$params['runFromIPs'] = $ci->config->item('runFromIPs');
$params['testDir'] = $ci->config->item('testDir');
$params['fileExtension'] = $ci->config->item('fileExtension');
$params['autorun'] = $ci->config->item('autorun');
$params['reporter'] = $ci->config->item('reporter');
$params['testTitle'] = $ci->config->item('testTitle');
}
if(isset($params['runFromIPs']) && strpos($params['runFromIPs'], $ci->input->server('SERVER_ADDR') === FALSE))
{
// Tests won't be run automatically from this IP.
$params['autorun'] = FALSE;
}
// Check if call was an AJAX call. No point in running test
// if not seen and may break the call.
$header = 'CONTENT_TYPE';
if(!empty($_SERVER[$header])) {
// #todo Content types could be placed in config.
$ajaxContentTypes = array('application/x-www-form-urlencoded', 'multipart/form-data');
foreach ($ajaxContentTypes as $ajaxContentType) {
if(false !== stripos($_SERVER[$header], $ajaxContentType))
{
$params['autorun'] = FALSE;
break;
}
}
}
$this->testDir = $params['testDir'];
$this->testTitle = $params['testTitle'];
$this->fileExtension = $params['fileExtension'];
if(isset($params['reporter']))
$this->Reporter = $params['reporter'];
if($params['autorun'] == TRUE)
echo $this->Run();
}
/**
* Run the tests, returning the reporter output.
*/
public function Run()
{
// Save superglobals that might be tested.
if(isset($_SESSION)) $oldsession = $_SESSION;
$oldrequest = $_REQUEST;
$oldpost = $_POST;
$oldget = $_GET;
$oldfiles = $_FILES;
$oldcookie = $_COOKIE;
$test_suite = new TestSuite($this->testTitle);
// Add files in tests_dir
if(is_dir($this->testDir))
{
if($dh = opendir($this->testDir))
{
while(($file = readdir($dh)) !== FALSE)
{
// Test if file ends with php, then include it.
if(substr($file, -(strlen($this->fileExtension)+1)) == '.' . $this->fileExtension)
{
$test_suite->addFile($this->testDir . "/$file");
}
}
closedir($dh);
}
}
// Start the tests
ob_start();
$test_suite->run(new $this->Reporter);
$output_buffer = ob_get_clean();
// Restore superglobals
if(isset($oldsession)) $_SESSION = $oldsession;
$_REQUEST = $oldrequest;
$_POST = $oldpost;
$_GET = $oldget;
$_FILES = $oldfiles;
$_COOKIE = $oldcookie;
return $output_buffer;
}
}
// Html output reporter classes //////////////////////////////////////
/**
* Display passes
*/
class ShowPasses extends HtmlReporter
{
function ShowPasses()
{
$this->HtmlReporter();
}
function paintPass($message)
{
parent::paintPass($message);
print "<span class=\"pass\">Pass</span>: ";
$breadcrumb = $this->getTestList();
array_shift($breadcrumb);
print implode("->", $breadcrumb);
print "->$message<br />\n";
}
function _getCss()
{
return parent::_getCss() . ' .pass {color:green;}';
}
}
/**
* Displays a tiny div in upper right corner when ok
*/
class SmallReporter extends HtmlReporter
{
var $test_name;
function ShowPasses()
{
$this->HtmlReporter();
}
function paintHeader($test_name)
{
$this->test_name = $test_name;
}
function paintFooter($test_name)
{
if($this->getFailCount() + $this->getExceptionCount() == 0)
{
$text = $this->getPassCount() . " tests ok";
print "<div style=\"background-color:#F5FFA8; text-align:center; right:10px; top:30px; border:2px solid green; z-index:10; position:absolute;\">$text</div>";
}
else
{
parent::paintFooter($test_name);
print "</div>";
}
}
function paintFail($message)
{
static $header = FALSE;
if(!$header)
{
$this->newPaintHeader();
$header = TRUE;
}
parent::paintFail($message);
}
function newPaintHeader()
{
$this->sendNoCacheHeaders();
print "<style type=\"text/css\">\n";
print $this->_getCss() . "\n";
print "</style>\n";
print "<h1 style=\"background-color:red; color:white;\">$this->test_name</h1>\n";
print "<div style=\"background-color:#FBFBF0;\">";
flush();
}
}
/**
* Minimal only displays on error
*/
class MinimalReporter extends SmallReporter
{
function paintFooter($test_name)
{
if($this->getFailCount() + $this->getExceptionCount() != 0)
{
parent::paintFooter($test_name);
print "</div>";
}
}
}
Works fine for me I haven't tested all the different reporters yet though. But the default one works fine.
And this is how I use it:
$this->load->library('simpletester');
echo $this->simpletester->Run();
And my config file is:
$config['testDir'] = APPPATH . 'tests';
$config['runFromIPs'] = '127.0.0.1';
$config['reporter'] = 'HtmlReporter';
$config['autorun'] = false;
$config['fileExtension'] = 'php';
$config['testTitle'] = 'My Unit Tests';

Related

How to write PHPunit test code with external object (having DAO)?

I'm trying to write test code for monosilic code like below.
Q1. How to write test code which has access to DB?
Q2. How to refactor these code testable?
Q3. Is there any way to write test code with fewer change to production code?
I need your help!
Thanks!!
Example Production Code)
<?
class Sample_Model_Service_A
{
private $_result
private $_options
private $_someValue
public function __construct($params, $ids, $data) {
$this->_options = Sample_Model_Service_B::getOption($data);
}
private function setSomeValue() {
// some code shaping $_params to $someValue with $this->_options
$this->_someValue= $someValue;
}
// want to write test for this function
// changed this function's logic
private function setResult() {
// some code shaping $_someValue to $result
$this->_result = $result;
}
public function getter() {
retrn $this->_result;
}
}
?>
<?
class Sample_Model_Service_B
{
// get option from DB
public static function getOption($data) {
$dao = new Model_Dao_Option();
$option = $dao->getOption($data['id']);
return $option;
}
}
?>
My Test Code so far)
public function testsetResult()
{
// just make sure these variables are defined
$params = $ids = $data = [];
// try to make test for private function
$sample = new Sample_Model_Service_A($params, $ids, $data);
$reflection = new ReflectionClass($sample);
// get Method
$method = $reflection->getMethod('setresult');
$method->setAccessible(true);
// wondering how to get $result
$result = $method->invoke($sample);
// assert
$this->assertSame($result);
}
Mockery solved my issue.
Sample Code)
/**
* #dataProvider sampleProvider
*/
public function testsetResult($sampleData)
{
// mock Sample_Model_Service_B
$mockSample_Model_Service_B = Mockery::mock('alias:' . Sample_Model_Service_B::class);
$mockSample_Model_Service_B->shouldReceive('getOption')->andReturn($sampleData['option']);
$sample = new Sample_Model_Service_A($sampleData['params'], $sampleData['ids'], $sampleData['data']);
$sample->setResult();
$result = $sample->getter();
// assert
$this->assertSame($result, $sampleData['result']);
}

Magento 2.3.3 dashboard keeps loading

I have installed latest version of magento in my localhost.
After login to admin panel dashboard keeps loading.
Here is the image-
Please help to solve this error.
First Go to magento root directory then :
vendor/magento/framework/view/element/tempalate/file/validator.php (dont exactly copy this url just follow this path)
open this file using any editor and change this line
$realPath = $this->fileDriver->getRealPath($path); //you can comment this out
with this one
$realPath = str_replace('\\','/',$this->fileDriver->getRealPath($path));
then goto to
app/etc/di.xml
and search for view_preprocessed
you will find a whole line like this :
Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink
and change the Symlink with Copy
Magento 2.3
go to \lib\internal\Magento\Framework\View\Element\Template\File
go to the function isPathInDirectories and replace the function with following
protected function isPathInDirectories($path, $directories)
{
if (!is_array($directories)) {
$directories = (array)$directories;
}
//$realPath = $this->fileDriver->getRealPath($path);
$realPath = str_replace('\\','/',$this->fileDriver->getRealPath($path));
foreach ($directories as $directory) {
//$realDirectory = $this->fileDriver->getRealPath($directory);
$realDirectory = str_replace('\\','/',$this->fileDriver->getRealPath($directory));
if ($realDirectory && 0 === strpos($realPath, $realDirectory)) {
return true;
}
}
return false;
}
go to app/etc/di.xml then search for view_preprocessed
you will find a whole line like this :
Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink and change to Magento\Framework\App\View\Asset\MaterializationStrategy\Copy
#1. go to vendor/magento/framework/View/Element/Template/File/Validator.php#
#2. go to the function isPathInDirectories and replace the function with following:#
protected function isPathInDirectories($path, $directories)
{
if (!is_array($directories)) {
$directories = (array)$directories;
}
//$realPath = $this->fileDriver->getRealPath($path);
$realPath = str_replace('\\','/',$this->fileDriver->getRealPath($path));
foreach ($directories as $directory) {
//$realDirectory = $this->fileDriver->getRealPath($directory);
$realDirectory = str_replace('\\','/',$this->fileDriver->getRealPath($directory));
if ($realDirectory && 0 === strpos($realPath, $realDirectory)) {
return true;
}
}
return false;
}
#3. go to app/etc/di.xml then search for view_preprocessed
you will find a whole line like this :
Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink and change to
Magento\Framework\App\View\Asset\MaterializationStrategy\Copy #

How set console argument in symfony 3 console command testing

I am unable to set Argument while creating Unit test case in Symfony 3.4 console command application
My Console command
php bin\console identification-requests:process input.csv
My Console code
protected function execute(InputInterface $input, OutputInterface $output)
{
// Retrieve the argument value using getArgument()
$csv_name = $input->getArgument('file');
// Check file name
if ($csv_name == 'input.csv') {
// Get input file from filesystem
$csvData = array_map('str_getcsv', file($this->base_path.$csv_name));
$formatData = Helpers::formatInputData($csvData);
// Start session
$session = new Session();
$session->start();
foreach ($csvData as $key => $data) {
if (!empty($data[0])) {
$validation = Validator::getInformationData($data, $formatData[$data[1]]);
if (!empty($validation)) {
$output->writeln($validation);
} else {
$output->writeln('valid');
}
}
}
} else {
$output->writeln('Invalid file!');
}
}
I tried the following test code
$kernel = static::createKernel();
$kernel->boot();
$application = new Application($kernel);
$application->add(new DocumentCommand());
$command = $application->find('identification-requests:process')
->addArgument('file', InputArgument::REQUIRED, "input.csv");
$commandTester = new CommandTester($command);
$commandTester->execute(array(
'command' => $command->getName()
));
$output = $commandTester->getOutput();
$this->assertContains('valid',$output);
When I run unit test it showing the following error message
There was 1 error:
1) Tests\AppBundle\Command\DocumentCommandTest::testExecute
Symfony\Component\Console\Exception\LogicException: An argument with name "file" already exists.
I think you should put your input in the command tester and not in the command finder, in this case you are trying to create another parameter for that command, and that's why it's telling you that it is existing already.
try this
$command = $application->find('identification-requests:process');
$commandTester = new CommandTester($command);
$commandTester->execute(array(
'command' => $command->getName(),
'file' => 'input.csv'
));

Doctrine: how to curb circular references

I have devices being parts of brands and repairs being part of devices. Now I'm trying to get a simple AJAX call which will allow me to search for a device by either brand name or device name. Unfortunately, I get circular references. Even when I've written a handler for circular references to limit it to one, I still get too much information in my objects.
Consider the following return from serialize on my DQL query:
[{"0":{"id":1,"name":"iPhone
1","logo":"iPhone1","brand":{"id":2,"name":"Apple","logo":"apple","devices":["iPhone
1",{"id":2,"name":"iPhone","logo":"iphone","brand":"Apple","deletedAt":null,"repairs":[]}],"deletedAt":null},"deletedAt":null,"repairs":[]},"name":"Apple"},{"0":{"id":2,"name":"iPhone","logo":"iphone","brand":{"id":2,"name":"Apple","logo":"apple","devices":[{"id":1,"name":"iPhone
1","logo":"iPhone1","brand":"Apple","deletedAt":null,"repairs":[]},"iPhone"],"deletedAt":null},"deletedAt":null,"repairs":[]},"name":"Apple"}]
Here I don't even need repairs at all. However, since it is referenced in the PartEntity, I still get a bunch of unnecessary repair info. How can I limit the data I get out of an object?
my Controller code:
public function ajaxShowDevicesAction(Request $request) {
//if ($request->isXmlHttpRequest()) {
$data = $request->query->get('data');
$result = "";
if ($data) {
$result = $this->getDoctrine()->getManager()->getRepository('AppBundle:Device')->findAllByBrandOrName($data);
}
if ($result) {
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$normalizers[0]->setCircularReferenceHandler(function ($object) {
return $object->getName();
});
$serializer = new Serializer($normalizers, $encoders);
$jsoncontent = $serializer->serialize($result, 'json');
$response = new Response($jsoncontent);
return $response;
}
// else { # unsure how to give a "no results" response
// $response = new Response(json_encode(array()));
// $response->headers->set('Content-Type', 'application/json');
// return $response;
// }
// } else {
// throw new HttpException(403, "Ajax access only");
// }
}
You can use
setCircularReferenceLimit()
method for normalizers.
Handling Circular References

Using Persistent Flash Message Library for ColdFusion

I am trying to use a library for showing Flash Messages https://github.com/elpete/flashmessage But I am having trouble getting it working correctly. The documentation isn't that great and I am new to ColdFusion. I want to have the ability to have persistent error messages across pages. Specifically during checkout so when the user needs to go back or a validation error occurs the message will appear. According to the documentation:
The FlashMessage.cfc needs three parameters to work:
A reference to your flash storage object. This object will need
get(key) and put(key, value) methods. A config object with the
following properties: A unique flashKey name to avoid naming
conflicts. A reference to your containerTemplatePath. This is the view
that surrounds each of the individual messages. It will have
references to a flashMessages array and your messageTemplatePath. A
reference to your messageTemplatePath. This is the view that
represents a single message in FlashMessage. It will have a reference
to a single flash message. The name is chosen by you in your container
template. Create your object with your two parameters and then use it
as normal.
I am getting the error
the function getMessages has an invalid return value , can't cast null value to value of type [array]
I had this script somewhat working at one point but it seems very finicky. I believe it is my implementation of it. I am hoping someone here can help me figure out where I went wrong. Or give me some pointers because I am not sure I am even implementing it correctly.
This is What I have in my testing script:
<cfscript>
alertStorage = createObject("component", 'alert');
config = {
flashKey = "myCustomFlashKey",
containerTemplatePath = "/flashmessage/views/_templates/FlashMessageContainer.cfm",
messageTemplatePath = "/flashmessage/views/_templates/FlashMessage.cfm"
};
flash = new flashmessage.models.FlashMessage(alertStorage, config);
flash.message('blah');
flash.danger('boom');
</cfscript>
And inside of alert.cfc I have:
component {
public any function get(key) {
for(var i = 1; i < ArrayLen(session[key]); i++) {
return session[key][i];
}
}
public any function put(key, value) {
ArrayAppend(session.myCustomFlashKey, value);
return true;
}
public any function exists() {
if(structKeyExists(session,"myCustomFlashKey")) {
return true;
} else {
session.myCustomFlashKey = ArrayNew();
return false;
}
}
}
The Flash Message Component looks like this:
component name="FlashMessage" singleton {
/**
* #flashStorage.inject coldbox:flash
* #config.inject coldbox:setting:flashmessage
*/
public FlashMessage function init(any flashStorage, any config) {
instance.flashKey = arguments.config.flashKey;
singleton.flashStorage = arguments.flashStorage;
instance.containerTemplatePath = arguments.config.containerTemplatePath;
instance.messageTemplatePath = arguments.config.messageTemplatePath;
// Initialize our flash messages to an empty array if it hasn't ever been created
if (! singleton.flashStorage.exists(instance.flashKey)) {
setMessages([]);
}
return this;
}
public void function message(required string text, string type = "default") {
appendMessage({ message: arguments.text, type = arguments.type });
}
public any function onMissingMethod(required string methodName, required struct methodArgs) {
message(methodArgs[1], methodName);
}
public any function render() {
var flashMessages = getMessages();
var flashMessageTemplatePath = instance.messageTemplatePath;
savecontent variable="messagesHTML" {
include "#instance.containerTemplatePath#";
}
setMessages([]);
return messagesHTML;
}
public array function getMessages() {
return singleton.flashStorage.get(instance.flashKey, []);
}
private void function setMessages(required array messages) {
singleton.flashStorage.put(
name = instance.flashKey,
value = arguments.messages
);
}
private void function appendMessage(required struct message) {
var currentMessages = getMessages();
ArrayAppend(currentMessages, arguments.message);
setMessages(currentMessages);
}
}