How to pass arguments to a test function in laravel throw console - laravel

I'm playing around with test in Laravel, and I want to test the same function with different users I've created. Is there a way to pass the id as an argument throw laravel console? I mean, writing something like:
/** #test */
public function my_test_function($id)
{
$user = User::find($id);
..........................}
And then calling with:
php artisan test --filter my_test_function ....... plus something to pass the id.

The cli arguments are accesible in the global namespace. You can retrieve and dump them with something like:
/** #test */
public function my_test()
{
global $argv;
var_dump($argv);
$this->assertTrue(true);
}
However, phpunit shouldn't allow for arbitrary parameters
$ vendor/bin/phpunit -u 1
PHPUnit 9.5.4 by Sebastian Bergmann and contributors.
Unknown option "-u"
You can resort to piggyback on a harmless option. For example, if you mean to pass an integer to match the user_id (as you probably do), you could probably do
$ vendor/bin/phpunit --exclude-group 14
As long as you don't have a real test group called '14', and have the dump display:
array (3) [
0 => string (15) "vendor/bin/pest"
1 => string (15) "--exclude-group"
2 => string (2) "14"
]
You don't need to write your own parsing rules to handle those arguments, but it's still -as I said- piggybacking and it could break in several ways. Before going further with that approach, I'd reccomend using an environment variable defined right before the executable
$ APP_USER_ID=14 vendor/bin/phpunit
which you can retrieve with
/** #test */
public function my_test()
{
var_dump(getenv('APP_USER_ID'));
$this->assertTrue(true);
}
the dump will display the value you're looking for without involving arguments parsing
string (2) "14"

Related

How to quickly write debug output from within a PHP Spec test method

I have inherited some phpspec tests.
The test is testing the value of a method called "getFatalErrors" and reporting failure with:
expected [array:1], but got [array:1].
I would like to see the actual contents of the array.
I have tried to hack the phpspec test class by adding lines like:
<?php
namespace spec;
use MyClass;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MyClassSpec extends ObjectBehavior
{
public function it_returns_a_path_problem($args,\XMLFileWrapperTest $testWrapper)
{
echo "foo";
...
var_dump(print_r($this->getFatalErrors()->getWrappedObject(), true));
...
fwrite(STDOUT, "foo");
print_r($this->getFatalErrors()->getWrappedObject(), true)
$this->display("foo");
}
}
--
But I can never get any output to show on my CLI output.
How can I make some arbitrary text appear in my test output so that I 'see' what is going on as I become more familiar with PHPSpec?
Try a different formatter.
When the formatter pretty is selected either in phpspec.yml using the line
formatter.name: pretty
or when executing the test runner with format flag
vendor/bin/phpspec run --format=pretty
then echo output is visible in the terminal.
Have you tried to tail the error log and in your function to add something like
error_log( print_r( $this->getFatalErrors()->getWrappedObject(), 1 ) ); or error_log( print_r( $this->getFatalErrors(), 1 ) ); ?
Usually, it works, as the output is written in your server error log and you can use the terminal or console to tail on that file and see in real time the result.
Just run phpspec with the -v flag, it will be more verbose.
According to the phpspec documentation on Matchers > Inline Matcher, it is possible...
to print a more verbose error message
to do this you can throw
FailureException
So, this implies that it is possible to throw FailureException to output custom messages from within your PHPSpec Example methods.
I tried this and it let me write the phrase "foo message" to my test output:
<?php
namespace spec;
use PhpSpec\ObjectBehavior;
[...]
use PhpSpec\Exception\Example\FailureException;
class MyClassSpec extends ObjectBehavior
{
public function it_tests_something()
{
[...]
throw new FailureException("foo message");
}
}

How can my command pass through optional arguments to another Artisan command?

(Updated question to show that it's not like the linked questions)
I wrote a Laravel command (shown in its entirety below) that basically is a wrapper for Dusk so that I can be sure to call certain other functions beforehand. (Otherwise, I inevitably would forget to reset my testing environment.)
It works perfectly when I run php artisan mydusk.
namespace App\Console\Commands;
class DuskCommand extends BaseCommand {
protected $signature = 'mydusk {file?} {--filter=?}';
protected $description = 'refreshAndSeedTestingDb, then run Dusk suite of tests';
public function handle() {
$this->consoleOutput($this->description);
$resetTestingEnv = new ResetTestingEnv();
$resetTestingEnv->refreshAndSeedTestingDb();
$this->consoleOutput('refreshAndSeedTestingDb finished. Now will run Dusk...');
$file = $this->argument('file');//What to do with this?
return \Artisan::call('dusk', ['--filter' => $this->option('filter')]);
}
}
As you can see, I've already read these docs and understand how to write the $signature to accept optional arguments.
My goal is to be able to sometimes run php artisan mydusk and also be able to optionally add arguments such as when I might want to call something like php artisan mydusk tests/Browser/MailcheckTest.php --filter testBasicValidCaseButtonClick (which would pass the tests/Browser/MailcheckTest.php --filter testBasicValidCaseButtonClick arguments through to the normal dusk command).
How can I edit the last 2 lines of my handle() function so that $file gets passed to dusk?
You can have a look at these links too it might help you.
Stack Answer 1
Stack Answer 2
I was surprised to learn from my experiments that my original function actually works as I desired, and I can remove the inert line ($file = $this->argument('file');).
Passing the file argument through \Artisan::call() actually does not seem to be necessary at all.
#fubar's answer seems to have made the same mistaken assumptions as I originally did.
As #Jonas Staudenmeir hinted in a comment, Laravel\Dusk\Console\DuskCommand uses arguments from $_SERVER['argv'].
Use signature without '--' to provide arguments
return \Artisan::call('dusk', ['file' => $file , '--filter' => $this->option('filter')]);
The documentation does give an example but it is not stated clearly (it assumes you followed all the statements in the sections above)
For the signature below
protected $signature = 'email:send {user} {--queue}';
It gives (on very far below) this example as calling an Artisan command from other commands
public function handle()
{
$this->call('email:send', [
'user' => 1, '--queue' => 'default'
]);
}
https://laravel.com/docs/5.6/artisan#calling-commands-from-other-commands

View nested objects under Tinker

On Laravel Tinker when I run this:
>>> $customers = App\Customer::all();
I get a list of objects such as:
=> Illuminate\Database\Eloquent\Collection {#811
all: [
App\Customer {#815
id: 3,
favorite: 6,
user: App\User {#232 ...11},
zip: 11221
}
...
]
My question is how do I expand the user value where it has {#232 ...11}?
the tinker function of artisan is based almost entirely off of the psysh
see: https://github.com/bobthecow/psysh/
also: https://psysh.org/
inside psysh is a command called dump, dump is an implementation of symfony's var-dumper a newer kind of var_dump.
dump -h
shows:
Usage: dump [--depth DEPTH] [-a|--all] [--]
Arguments: target A target object or primitive to dump.
Options: --depth Depth to parse. (default: 10) --all (-a) Include
private and protected methods and properties.
Help: Dump an object or primitive. This is like var_dump but way
awesomer. e.g.
>>> dump $_
>>> dump $someVar
>>> dump $stuff->getAll()
for myself running with the argument --depth does not satisfy my object which is also rather large. so we see that psysh has a dependency on symfony's var-dumper.
see: https://github.com/symfony/var-dumper
also: https://symfony.com/doc/current/components/var_dumper.html
the advanced section states
The dump() function is just a thin wrapper and a more convenient way
to call VarDumper::dump(). You can change the behavior of this
function by calling VarDumper::setHandler($callable). Calls to dump()
will then be forwarded to $callable.
By adding a handler, you can customize the Cloners, Dumpers and
Casters...
A cloner is used to create an intermediate representation of any PHP
variable. Its output is a Symfony\Component\VarDumper\Cloner\Data
object that wraps this representation...
A cloner applies limits when creating the representation, so that one
can represent only a subset of the cloned variable. Before calling
cloneVar(), you can configure these limits:
setMaxItems()
Configures the maximum number of items that will be cloned past the minimum nesting depth. Items are counted using a breadth-first
algorithm so that lower level items have higher priority than deeply
nested items. Specifying -1 removes the limit. setMinDepth()
Configures the minimum tree depth where we are guaranteed to clone all the items. After this depth is reached, only setMaxItems items
will be cloned. The default value is 1, which is consistent with older
Symfony versions. setMaxString()
Configures the maximum number of characters that will be cloned before cutting overlong strings. Specifying -1 removes the limit.
see: https://symfony.com/doc/current/components/var_dumper/advanced.html
so what I am doing is creating a folder inside app named VarDumpFull then adding into file /app/VarDumpFull/VarDumpFull.php the following code
<?php
namespace App\VarDumpFull;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
class VarDumpFull
{
public function __construct($var)
{
$cloner = new VarCloner();
$dumper = new CliDumper();
$cloner->setMaxItems(-1);
$cloner->setMaxString(-1);
$dumper->dump($cloner->cloneVar($var));
}
}
you can run this easily like so:
new VarDumpFull($variable_to_be_dumped);
remember to run to update your classes.
composer dump-autoload
You need to iterate over the collection to work with user property. If you want to do that in Tinker:
foreach ($customers as $customer) {
echo $customer->user->name;
}
If you just want to see the data structure, you can do this in Tinker:
$customers->first()->user
First of all you should load relationship:
$customers = App\Customer::with('user')->get();
but I assume you did it because you have user relationship visible on your output.
To get array representation of your customers together with relationships you should use:
foreach ($customers as $customer)
{
dump($customer->toArray());
}
obviously result won't be the same as you dump the whole collection but you will get all model attributes together with relations and I think this is what you want here.

Routing with 2 optional parameters where either one can be chosen

I am using a route with 2 optional parameters and I would like that either one of them can be chosen because they are used in a where clause. The where clause can be used on the first parameter OR the second one.
I tried this:
Route::get('activityperemployee/employee_id/{employee_id?}/month/{month?}', ['uses'=>'Ajax\ActivityAjaxController#getActivityPerEmployee','as'=>'ajaxactivityperemployee']);
but the problem is I can't find the page anymore if I don't set up both of the parameters.
The problem is the first parameter {employee_id?}. You cannot use it in this way becasue if You won't pass any params You'll get url like:
activityperemployee/employee_id//month
which won't find your route.
I think You should make required at least {employee_id} (without question mark) and always passing first parameter.
I suggest to use a get variable.
If you have multiple optional parameters
Route::get('test',array('as'=>'test','uses'=>'HomeController#index'));
And inside your Controller
class HomeController extends BaseController {
public function index()
{
// for example /test/?employee_id=1&month=2
if(Input::has('id'))
echo Input::get('id'); // print 1
if(Input::has('page'))
echo Input::get('page'); // print 2
//...
}
}
Hope this works for you! More information at https://stackoverflow.com/a/23628839/2859139

Get return variable or variable from one function to another function in controller

I am wondering if it is allowed to access/get/use the variable from one function to another function within one controller?
Thank you.
Try Something like this.
class Index extends CI_Controller {
protected $var1;
public function index() {
$this->setVar1();
echo $this->var1; // print $var1
}
public function setVar1() {
$this->var1 = 1;
}
}
$superduper = 'superduper' ;
available only locally within the method (function)
or passed like
$this->reviews->insertToReviews($superduper) ;
versus
$this->superduper = 'superduper' ;
as soon as $this->variablename is declared in a controller its instantly available to:
any method in the controller
any method in any model that is called by the controller
any view file called by the controller
so without passing the variable - in a view you can use
echo 'my lunch is ' . $this->superduper ;
but often its better to explicitly pass values to the view especially if they are unique to the method - it makes it easier to see what is going on. so in that case in controller:
$data['superduper'] = $this->superduper ;
and in view
echo 'my lunch is ' . $superduper ;
Now when anyone looks at the method in the controller - we can see that superduper is being passed to $data. the point is that even though you can avoid passing variable names to methods or the view by declaring $this->somename - if you pass them locally it can make it easier to see what is going on.
The flip side is something like:
$this->error_message = "Error retrieving database records";
is awesome. you can have error messages in any method and they will be automatically available no matter what else happens. so then in your view file have something like
if($this->error_message != '') { echo $this->error_message ;}
this is especially helpful while you are building the site.

Resources