assert dilemma in unit testing class - php

I would like to use PHP's assert function in my unit testing framework. It has the advantage of being able to see the expression being evaluated (including comments) within the error message.
The problem is that each method containing tests may have more than one assert statement, and I would like to keep track of how many actual assert statements have been run. assert does not give me a way to count how many times it has been run, only how many times it has failed (within the failure callback).
I tried to abstract the assert statement into a function so that I can add a counting mechanism.
private function assertTrue($expression) {
$this->testCount++;
assert($expression);
}
This does not work however because any variables within the expression are now out of scope.
$var = true;
$this->assertTrue('$var == true'); // fails
Any advice on how I can use assert in my unit testing while being able to count the number of actual tests?
The two ideas I have come up with are to make users count themselves
$this->testCount++;
assert('$foo');
$this->testCount++;
assert('$bar');
or make users put only one assert in each test method (I could then count the number of methods run). but neither of these solutions is very enforcable, and make coding more difficult. Any ideas on how to accomplish this? Or should I just strip assert() from my testing framework?

In PHPUnit, all of the assert*() methods take an additional $message parameter, which you can take advantage of:
$this->assertTrue($var, 'Expected $var to be true.');
If the assertion fails, the message is output with the failure in the post-test report.
This is more useful generally than outputting the actual expression because then you can comment on the significance of the failure:
$this->assertTrue($var, 'Expected result of x to be true when y and z.');

A bit of a cheeky answer here, but open vim and type:
:%s/assert(\(.+\));/assert(\1) ? $assertSuccesses++ : $assertFailures++;/g
(In principle, replace all assert() calls with assert() ? $success++ : $fail++;)
More seriously, providing a mechanism to count tests is really a responsibility a bit beyond the scope of the assert() function. Presumably you want this for an "X/Y tests succeeded" type indicator. You should be doing this in a testing framework, recording what each test is, its outcome and any other debug information.

You are restricted by the fact assert() must be called in the same scope the variables you are testing lie. That leaves -- as far as I can tell -- solutions that require extra code, modify the source before runtime (preprocessing), or a solution that extends PHP at the C-level. This is my proposed solution that involves extra code.
class UnitTest {
// controller that runs the tests
public function runTests() {
// the unit test is called, creating a new variable holder
// and passing it to the unit test.
$this->testAbc($this->newVarScope());
}
// keeps an active reference to the variable holder
private $var_scope;
// refreshes and returns the variable holder
private function newVarScope() {
$this->var_scope = new stdClass;
return $this->var_scope;
}
// number of times $this->assert was called
public $assert_count = 0;
// our assert wrapper
private function assert($__expr) {
++$this->assert_count;
extract(get_object_vars($this->var_scope));
assert($__expr);
}
// an example unit test
private function testAbc($v) {
$v->foo = true;
$this->assert('$foo == true');
}
}
Downfalls to this approach: all variables used in unit testing must be declared as $v->* rather than $*, whereas variables written in the assert statement are still written as $*. Secondly, the warning emitted by assert() will not report the line number at which $this->assert() was called.
For more consistency you could move the assert() method to the variable holder class, as that way you could think about each unit test operating on a test bed, rather than having some sort of magical assert call.

That's not something which unit-testing is intended to do (remember it originated in compiled langs).
And PHPs semantics do not help much with what you are trying to do either.
But you could accomplish it with some syntactic overhead still:
assert('$what == "ever"') and $your->assertCount();
Or even:
$this->assertCount(assert('...'));
To get the assertion string for succeeded conditions still, you could only utilize debug_backtrace and some heuristic string extraction.
This is not enforced much either (short of running a precompiler/regex over the test scripts). But I would look at this from the upside: not every check might be significant enough to warrant recording. A wrapper method thus allows opting out.

It's hard to give an answer without knowing how your framework has been built, but I'll give it a shot.
Instead of directly call the methods of your unit testing class ( methods like assertTrue() ), you could use the magic method of PHP __call(). Using this, you could increase an internal counter everytime assertTrue() method is called. Actually, you can do whatever you want, every time any method is called.
Remember that __call() is invoked if you try to call a method that does not exist. So you would've to change all your methods names, and call them internally from __call(). For instance, you'd have a method called fAssertTrue(), but the unit testing class would use assertTrue(). So since assertTrue() is not defined, __call() method would be invoked, and there you would call fAssertTrue().

Since you're passing the expression already (which might lead, correct me if I'm wrong, to quoting hell):
$this->assertTrue('$var == true'); // fails with asset($expression);
Why not add a tiny extra layer of complexity, and avoid the quoting hell, by using a closure instead?
$this->assertTrue(function() use ($var) {
return $var == true;
}); // succeeds with asset($expression());

Simple:
$this->assertTrue($var == true);
(without quotes!)
It will be evaluated in caller space, so assertTrue() will be passed just false or true.
As others have pointed out, this might not be the best way of testing, but that's another question entirely... ;)

Related

How to test a method which calls itself?

Given this code:
function testMe($a)
{
if ($a)
{
return 1;
}
else
{
return $this->testMe(true);
}
}
testMe() cannot be mocked, because then I cant call it. On the other hand, it must be mocked…
I'd say your question has some philosophical potential. I'll try to answer it the way you ask it but before, allow me to comment on your comprehension:
testMe() cannot be mocked, because then I cant call it. On the other hand, it must be mocked… [italics by me]
The unfinished sentence is wrong. You probably sensed it already because you didn't finish it. In a unit test you don't mock the unit. So you put the unit under test, and the unit is the method. That is the smallest part (unit) that can be tested.
What perhaps actually creates a bit of confusion is the recursion within the method.
So you actually ask how to unit-test recursion or a single method call within that recursion. But do you really need to test it?
I would say no. And that is because the recursion is an implementation detail of the method. From the outside it should not make any difference if you exchange the internal algorithm from recursion to a stack based loop for example.
But despite the fact I say you don't need that (and I hope you already have understood the argumentation I outlined), it technically is possible for your very specific scenario to test such a method-call without re-writing the code under test by re-binding $this. Then you can replace the subject under test ($this) with a mock when called. So that you have two methods: The one to test and the mocked one that is accessible via $this->testMe().
This could be done by instantiating the subject under test, create a mock, use PHP's reflection to obtain the closure of testMe() then re-bind $this on the closure to the mock and then call the closure for your test assertions.
I would not call this a unit-test any longer because as I outlined earlier, you're testing internals / privates, so you can use it more to actually test fragments of the recursion under certain circumstances and other similar detailed things that will more actually proof / debug fragments of code. You normally only need that under very specific circumstances when code is really high valuable.
Don't use your little confusion about the recursion to think this is an entirely important place to test on it's own. But if you want to get your fingers dirty, it's perhaps something worth to play with to learn about PHP reflection, closures and re-binding $this.

How to detect dynamic declarated fields on objects with codesniffer in PHP

After a refactoring, we had something like this in one of our classes:
class FooBar
{
// $foo was $bla before
private $foo;
public function setBlubbOnArrayOnlyOnce($value)
{
// $this->bla was forgotten during refactoring. Must be $this->foo
if(!isset($this->bla['blubb'])) {
$this->foo['blubb'] = $value;
}
}
}
So in the end $this->foo['blubb'] was always set, not only once.
This happens because of the magic methods of PHP. We don't want it to be possible to access fields dynamically, so I thought I just add a codesniffer rule. But I didn't found any and asked me why.
PHPStorm shows a field declared dynamically notice there, but I want this to automatically fail with codesniffer (or something similar) during our deployment cycle.
Has anybody an idea on this? Is there a good rule? Should I write my own and how? Or would it be bad practice to disable it?
Disclaimer: We use tests, but sometimes you miss things... It would be good to prevent this in the first place. Also, please don't come up with overwriting the magic methods. I don't want to have a trait/abstract whatever in every class.
This is not a codesniffer or phpstorm problem. And you cant want fix this problem with codesniffer or IDE. IDE, codesniffer, phpdocumentor, etc. -- this is "statically" analyse. And for dynamic analyse you can use e.g. phpunit.
If you want check existence of property you must use property_exists() function.
class X
{
public function __get($name)
{
$this->{$name} = null;
return $this->{$name};
}
}
$x = new X();
var_dump(property_exists($x, 'foo')); // false
var_dump($x->foo); // NULL
var_dump(property_exists($x, 'foo')); // true
Or may be you can use reflection for property http://php.net/manual/en/class.reflectionproperty.php
If you want check for "isset" you must known:
var_dump(isset($x), $x); // false + NULL with notice
$x = null;
var_dump(isset($x), $x); // false + NULL
unset($x);
var_dump(isset($x), $x); // false + NULL without notice
When you shure for this case of check you can use isset()
But you should always first check for existence of property. Otherwise you can have undefined behaviour of your code.
After a refactoring
It would be good to prevent this in the first place.
You can only catch these kind of refactoring errors by running tests after each refactoring step. This error will also bubble up, because foo['blubb'] is set to a specific value and this should cause an unwanted effect in another test - not only in the test for the setter logic.
We use tests, but sometimes you miss things...
Yes, its quite common that the coverage is not high enough.
That's why having a good test coverage is the starting point for all refactorings.
These two lines were not "green" in your coverage report:
if(!isset($this->bla['blubb'])) {
$this->foo['blubb'] = $value;
Also, please don't come up with overwriting the magic methods. I don't want to have a trait/abstract whatever in every class.
You have excluded it, but that's one way to catch the properties: by using the magic function __set() (for inaccessible vars) or property_exists() or the use of Reflection* classes to find.
Now, that its too late, you want another tool to catch the error, ok:
The tool would need to parse the PHP file and its parents (because of variable scope) and find $this->bla without a prior public|private|protected variable (class property) declaration. This will not indicate the exact type of error, just that "bla" was accessed without declaration.
Its possible to implement this as a CodeSniffer rule.
You can also give http://phpmd.org/ or https://scrutinizer-ci.com/ a try.
And, in case you are using PHP7: https://github.com/etsy/phan
tl;tr
Its complicated to determine the exact error and its context without running, evaluating and analyzing the underlying code. Just think about "dynamic variable names" and you know why: you don't even know the name of the property by looking at the source-code, because its build dynamically during program flow. A static analyzer wouldn't catch that.
A dynamical analyzer has to track all things, here $this-> accesses and would take the context into account: !isset(x). Context evaluation can find lots of common coding mistakes. In the end you can build a report: saying that $this->bla was accessed only 1 time and that indicates either that
a dynamically declared property was introduced, but never re-used, with the suggestion that you might drop it or declare it as class property
OR with added context evaluation: that and when this variable was accessed from inside a isset() - that a non-existing key of a non-declared property was accessed, without a prior set(), etc.
Now in 2017, you'are looking for tool PHPStan. I link short intro I wrote for first time users.
It does exactly what you need!

Am I setting myself up for failure using a static method in a Laravel Controller?

I am quite new to OOP, so this is really a basic OOP question, in the context of a Laravel Controller.
I'm attempting to create a notification system system that creates Notification objects when certain other objects are created, edited, deleted, etc. So, for example, if a User is edited, then I want to generate a Notification regarding this edit. Following this example, I've created UserObserver that calls NotificationController::store() when a User is saved.
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
NotificationController::store($data);
}
}
In order to make this work, I had to make NotificationController::store() static.
class NotificationController extends \BaseController {
public static function store($data)
{
// validation omitted from example
$notification = Notification::create($data);
}
I'm only vaguely familiar with what static means, so there's more than likely something inherently wrong with what I'm doing here, but this seems to get the job done, more or less. However, everything that I've read indicates that static functions are generally bad practice. Is what I'm doing here "wrong," per say? How could I do this better?
I will have several other Observer classes that will need to call this same NotificationController::store(), and I want NotificationController::store() to handle any validation of $data.
I am just starting to learn about unit testing. Would what I've done here make anything difficult with regard to testing?
I've written about statics extensively here: How Not To Kill Your Testability Using Statics. The gist of it as applies to your case is as follows:
Static function calls couple code. It is not possible to substitute static function calls with anything else or to skip those calls, for whatever reason. NotificationController::store() is essentially in the same class of things as substr(). Now, you probably wouldn't want to substitute a call to substr by anything else; but there are a ton of reasons why you may want to substitute NotificationController, now or later.
Unit testing is just one very obvious use case where substitution is very desirable. If you want to test the UserObserver::saved function just by itself, because it contains a complex algorithm which you need to test with all possible inputs to ensure it's working correctly, you cannot decouple that algorithm from the call to NotificationController::store(). And that function in turn probably calls some Model::save() method, which in turn wants to talk to a database. You'd need to set up this whole environment which all this other unrelated code requires (and which may or may not contain bugs of its own), that it essentially is impossible to simply test this one function by itself.
If your code looked more like this:
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
$this->NotificationController->store($data);
}
}
Well, $this->NotificationController is obviously a variable which can be substituted at some point. Most typically this object would be injected at the time you instantiate the class:
new UserObserver($notificationController)
You could simply inject a mock object which allows any methods to be called, but which simply does nothing. Then you could test UserObserver::saved() in isolation and ensure it's actually bug free.
In general, using dependency injected code makes your application more flexible and allows you to take it apart. This is necessary for unit testing, but will also come in handy later in scenarios you can't even imagine right now, but will be stumped by half a year from now as you need to restructure and refactor your application for some new feature you want to implement.
Caveat: I have never written a single line of Laravel code, but as I understand it, it does support some form of dependency injection. If that's actually really the case, you should definitely use that capability. Otherwise be very aware of what parts of your code you're coupling to what other parts and how this will impact your ability to take it apart and refactor later.

Are there advantages to using __get/__set instead of traditional getter/setter methods except for less code?

coming from Java, I only have a few vacational visits to PHP. Looking at magic get and set methods, my (Java influenced) tummy starts hurting: It looks as if you were accessing properties directly (although, of course, you are actually are using __get and __set).
So - except for less code you have to write, are there any advantages to using magic getter and setter methods instead of traditional getX()/setX() methods? Should I start using them when coding PHP?
Thanks and best!
The only benefit of __get() is the possibility of less code, but even then it's not necessarily the case. For example, if you have a set of 10 private members and you want the getter to reveal 5, you have to write __get() so that if one of the psuedo-visible members is called, you send it. Otherwise, you either issue an error (that would otherwise come naturally without __get() or return a value such as null that may not actually be helpful.
I must excoriate anyone who suggests using getters and setters in general at all. This usually indicates a problem with architecture. Explain the conceptual difference between the two following code blocks, for instance:
class _ {
public $_;
}
vs.
class _ {
private $_;
public function get_() {
return $this->_;
}
}
There isn't a difference.
However, as many will point out the advantage of having a getter is that this allows you to modify the return value in some way transparently to make it useful for the recipient. However, we come back to architecture problems. You should never have to expose the contents of a class for any reason at all. Instead, you should tell the class to perform an action (which may vary based on its state). Using getters generally lends to querying the class' state and performing an action externally based on the viewed state.
I have essentially the same arguments against __set() and setters, but there is one nice thing that __set() lets you do:
class _ {
private $_ = array();
public function __set($key, $val) {
$this->_[$key] = $val;
}
}
This lets you type the very nice $_obj->key = 'val'. Note that there is not much difference from this and adding another method such as add() that takes the key and value and does the same thing, I just prefer the object setter notation.
__get__ and __set__ are fully dynamic. So for example you can start a database request if they are called to enable lazy loading. Of course, you could do this with getters and setters, too, but then you would have to do this every time. You can also do something like AOP because every property call gets passed through one single method. So all in all __get__/__set__ offer more flexilibility against time they take to process. You can do really advanced/cool stuff with it.
The advantages are that when you're refactoring, direct assignments / reads can be handled without the need to immediately change the complete codebase too, the code can be somewhat shorter, and people can create strings somewhat more easily (for example: $title="<title>{$obj->title}</title>"; vs. $title='<title>'.$obj->getTitle().'</title>';.
However, __get & __set methods can become large and unwieldy fairly quickly, and when coding properly & explicitly, it is in my opinion better to use explicit set/getX() methods to make clear functions are called, and the minor increase of code verbosity is as far as I'm concerned justified as one can easily see what actually calls a function and what doesn't. A possible exception could be when you are building a decorator for another class/object, but that's about it.
there is few difference between getter and setter methods and __set() and __get() methods! these are magic methods!
__set() use when you wanna assign undefined state to a object and so __get() also use to fetch value of undefined state!
setter and getter are used to assign or fetch value of defined states
except for less code you have to write, are there any advantages to using magic getter and setter >methods instead of traditional getX()/setX() methods? Should I start using them when coding PHP?
Given that less code to write it's already a strong reason to start use them.
the other reason is that you can add a common behaviour to all your getter/setter
function __set() {
//> Do some code in common between all setter
//> set your var here
}
When writing getX()/setX() for each attribute, practically speaking, you'll have at a minimum, 7 lines of code. This is assuming that your opening method brace is on the same line as the definition and you only put a single line of code into the method, then you have your closing brace on its own line.
For a non-trivial object, multiply that by 6 (YMMV). That is 42 lines just for attribute access/mutation. That does not include input validation or normalization. For an alternative, check out: https://github.com/metaphp/attributes
There are overheads in dynamic programming (e.g. using magic methods). An old benchmark: Benchmarking magic
As PHP is a dynamic (and not a completely enterprise) language, reducing code lines and missing some nanoseconds seems good idea in many cases (for debugging, scalability, reducing errors and etc).

Unit testing singleton pattern method __clone() in php

I'm currently working on unit testing of a custom class I made, which is based on the singleton design pattern. Based on the code coverage report I have 95.45% of it covered. I am using PHPUnit to do the unit testing and I have been through this article
by Sebastian Bergmann.
The only problem I am left with is testing against class cloning throught the magic method __clone(). I have set that method as private to avoid instantiation
private final function __clone()
{}
What would be the best way to write a test to make sure that the singleton isn't "clonable". (The same test could eventually be used to test the __constructor())
Not really a question but is it just me or the tests runs awfully slow on a windows box compared to a *nix box?
Keep in mind that code coverage is not a measure of how correct your program is, nor does 100% coverage mean you've executed every code path. For example, the ternary operator
a ? b : c
and compound boolean expressions
if (a < 1 || b > 6)
are counted as single statements even though you may execute only a portion of them due to short-circuiting. Also, omitting the braces around single-statement if, while, etc. blocks turns the whole thing into a single statement.
The following will appear as a single statement in the code coverage report so you can't tell if you've executed both cases (true and false).
if (...)
foo();
I feel that
private final function __clone() { }
is too simple to fail. Testing that the method throws an exception (using reflection no less which your clients won't do) is testing the PHP interpreter--out of scope in my book.
[For the record, I too get a little OC when it comes to reaching 100% code coverage, but keeping the above facts in mind helps to alleviate it so I can move on to writing better code.]
Call clone or constructor and check if excpetion has been thrown.

Categories