40 comments

[ 841 ms ] story [ 1159 ms ] thread
There are a number of mock object libraries out there (mockery, shmock, phpunit's mock syntax, etc). This just looks like another builder syntax for making mocks / stubs with some fanciness around class extension - what's the benefit?

Also, how often is it useful to define a class at test time that is initialized by production code (from the section I Still Have Serious Dependency Issues!). This seems like an unlikely use case.

I wrote this library for two major reasons:

1) To avoid the complexity of existing frameworks. 2) To be able to quickly and easily test code with various kinds of dependencies.

It is predominately designed to test a single class in an extremely isolated context, not in the context of a full blown testing framework.

It is designed to be a stupid as possible with the intention of allowing the developer (myself) to define very strict test condition and very fine grain control.

I'm confused, what does this have to do with Aaron Swartz?
I assume you are trying to make a joke. But it's not very funny.
Not funny at all, but in all honesty, I am also keen to get back to the normal flow of things, I have paid my respects and I feel that perhaps 15 articles on the front page may have been enough for now, leave his friends to mourn as they will, if you over do anything people tire of it quickly.
(comment deleted)
You have really taken my comment in entirely the wrong light, I'm not complaining that his death has been treat with respect and reverence but you are right in that I am now mentally filtering the articles with "!(^Aaron$)" - I read the first few to pop up at ridiculous O'clock, and a few more when I woke, then I read a few more after lunch, then a few more before my tea, now I just read another before posting this, I was simply saying what a few others are thinking, that there are simply too many articles related to him - the high quality ones and the truly heart felt ones are being over shadowed by the "I once met Aaron in a coffee shop and he paid with 3 $0.25 coins!!!" type articles.

If you were a friend, I apologize for your loss, but please think rationally and don't project your feelings on me.

This library could use Composer support. I suppose I'll make a quick pull request.
I'm cool with that. Feel free to move the example.php into a separate subdirectory to make it cleaner too, but please fix the includes to point to whatever relative directory need be.
It's done, I didn't touch the file structure since Composer is smart enough to map classes even if the layout isn't PSR compliant.
Ok... I did have to increase version in composer.json though due to literal array syntax (hopefully not a deal breaker).
Sure thing, didn't notice before.
(comment deleted)
Noticing it's licensed under AGPL. I guess that means all projects that happen to include this (or something depending on it) would then be required to post full source code on the webpage, even if the project is for a single install?
Nope. If the project actually uses tests for its function and it is accessible they would be required to provide the source to anyone user who requested it.

Much like the regular GPL, AGPL is dependent on distribution.

If you create a project that uses it to perform testing on the project, unless your testing is a function of the actual project then you wouldn't have to do anything of the sorts.

If you created a testing platform online that used it to render services, then you would, yes.

Oh okay. I haven't really looked much into AGPL, I just assumed it was "infecting" the whole project sorta like the GPL.
Let me clarify, I don't think anyone's projects that are web facing actually use their testing library to perform the tasks. So for all intents and purposes their projects as they are "distributed" over a network are not linking to it even though it may exist in their source tree.

The only exception to this would be if the project is actually for testing, like say an online service that tests your code.

Also any private non-distributed use does not require source distribution.

Why is it AGPL then and not GPL? This seems to just create a minefield in the strange event when some test function needs to be exposed to the public for some reason. While this probably won't occur, if it does, suddenly the whole source needs to be released.

There does not seem to be any benefit to making this AGPL as it as the source release on use feature of AGPL is not intended to be used during regular usage.

Change it to GPL - it makes no practical difference, yet increases potential usage of the library at no cost.

GPL only applies to binary software. PHP is not compiled and linked.
You're correct...

I find this completely insane though! Everything is just 0s and 1s that are transformed and ultimately can be passed through the logic gates on a CPU to do math. Whether code is compiled or interpreted has no effect on the end goal - such as an instruction to the CPU to add two numbers.

Copyright is such a mess.

FWIW, I don't think that is correct. See comment above.
I tried to clarify above.

What I am trying to get at is that traditionally web software is not distributed at all. That is, the software itself is never provided to the user and the user just interfaces with it externally.

The point regarding binary stuff was as it applies to distributed projects because if PHP or any other interpreted language is "distributed" in a traditional sense, it is already in source code.

I feel as though the confusion here is because people are looking at the initial distribution to other developers and thinking that's it. But that distribution completely allows for a developer to "link to it", modify it, and keep it behind closed doors if it is never distributed. And it isn't if it's sitting behind a web server... someone is just interfacing with it through a completely open protocol.

The point of the AGPL is to say that someone who is using a program, regardless of the fact that the program itself is never being distributed to them, has a right to get the source.

(comment deleted)
That sounds like a very dangerous opinion to present as if it were a fact.

Is it not more a matter of whether a piece of software is a "derivative" of the GPL software?

Looks like even the FSF does not have a clear black&white answer to this question: http://www.gnu.org/licenses/gpl-faq.html#MereAggregation: "if the semantics of the communication are intimate enough, exchanging complex internal data structures, that too could be a basis to consider the two parts as combined into a larger program"

I remember the mysql guys used to claim that any software connecting to a mysql server would be "infected" with GPL, at least if it was written to depend on the official mysql client libraries, even if the software in question didn't actually copy a single character from any mysql distributions. (?)

I misspoke, what I should have said is that GPL's distribution clause only pertains to binary software.

clearly if you provide someone a piece of GPL software (such as a perl script to do something useful on their server) it's GPL so it's free software and it's already source code.

The point is that the Affero clause is very clearly targets software that is being used over a network connection rather than being distributed.

It is not possible in the least that the "semantics of the communication are intimate enough" to qualify -- the semantics of the communication are HTTP, an open standard used for extremely varied purposes.

I'm quite sure the MySQL guys are simply wrong on that, but even if they're not, it's clearly not the case for HTTP.

Well, the question here is if the PHP code someone wrote to power a public web site would be considered to be a partly derivative or combined work of the AGPL testing library, wouldn't it?

Just a leftover test function inside the main app referencing this library would probably be enough to consider it a derivative or combined work, no?

(Not sure how HTTP comes into play regarding the linking and combining of a project and this AGPL library?)

I think the terms are difficult to understand. In the general case who knows what a library author intended or how think they understand the license??

(Also, claiming GPL only pertains to binary software sounds really quite imprecise too. Just because you receive source code does not mean you can use it or distribute it in any way you see fit. You would still need to abide by whatever license accompanies the non-binary software)

I'm not sure why you would have a test function in the main app as opposed to separate testing - but yes, it would.

The intention of the AGPL is clear in my opinion and not really up for author interpretation. If someone is accessing code on a server (binary or interpreted), they have a right to obtain and modify that source code.

Aside from SaaS testing suites, I do not know of any examples where test code is accessed by users over a network.

It is, thus, 100% OK to use this source code to test a closed source project.

If the GPL had the same added clause as the AGPL, then there would be a serious number of infringing web apps.

The first sentence of the wikipedia page explains it best: "Both versions of the AGPL were designed to close a perceived application service provider "loophole" (the "ASP loophole") in the ordinary GPL, where by using but not distributing the software, the copyleft provisions are not triggered."

No use == no copyleft requirement, and I would hope it's pretty clear that simply by having a piece of AGPL software in the same directory as another piece of software that it is not inherently using it.

OK then I guess we agree in this instance. :)

I'd just like to clarify the problem I see with this: When the library is added to the project and is on the include-path (in the IDE, whatever), I think there's a non-zero risk that some developer on the project ends up putting a reference to it in the main app. At least it's something one needs to be careful about.

GPL does not "infect" a whole project either.

GPL only requires you distribute source if you distribute the binary.

It is designed so that users maintain the right to modify software that they use.

The only difference with the Aferro clause is that it considers network use of web software to be distribution and pertains to obfuscated software (i.e. server side source) even if it's not binary.

Yeah, that's why I put it in quotes, I just assumed that if the AGPL library was included in the project, then the whole project had to abide by the AGPL.
Since this library requires PHP 5.4, I'm not sure why it bothers with this syntax:

    Parody\Mime::create('Vendor\Class\Project')
    -> onCall('method') -> expect('argument one') ->  give('response one')
    -> onCall('method') -> expect('argument two') -> give('response two')
    -> resolve();
When one could just use anonymous functions to give the same result with less API-as-code.

    Parody\Mime::create('Vendor\Class\Project')
    -> onCall('method', function($param) {
      if ($param == 'argument one') return 'response one';
      if ($param == 'argument two') return 'response two';
    ) -> resolve();
This is more flexible, less code for the framework, and easier to learn.
Expectations and responses (provided by give()) are actually held internally. Your syntax is cleaner for very simple responses, however will become increasingly complex, particularly when the response itself is determined by a callback. Adding more params would clutter your example terribly. Also, the mime's are passed to callbacks which provide response so that additional functionality can be added, see this recent use-case:

Parody\Mime::create('App\Text') -> onCall('create') -> expect('WTF' . DS . 'Yo') -> give(function($mime) { return $mime -> onCall('underscorize') -> give('wtf' . DS . 'yo') -> resolve(); });

That seems exceedingly clever -- too clever. I'd make some of that functionality a named function and call it from my callback. It took me way too long to figure out what your code did.
I'm not sure I follow. Could you give a hypothetical example?

It's difficult to tell if you are only referring to the passing of the original Mime as an argument... which if you are, I presume is more a limitation of documentation. While it may be clever, it's a pretty standard use of callbacks to have arguments passed to them that may be useful inside.

Obviously, it would make sense to pass an instance of the object as the first argument to every callback.

A mocked class stands in for the original class. All the methods are stubs. Sometimes you need to provide functionality for the stub methods. Isn't it most logical to use a function to provide a stub method's body?

It's my opinion that all the stuff PHPUnit unit does with mocks (and JUnit as it's based on) is because Java didn't have anonymous functions. So you had to call methods to essentially construct code for the stub method body. But if you can provide actual code than all that API is unnecessary.

In 99% of cases I would wager you don't want your stubs to perform much logic at all. You want their returns to be a static as possible. The more logic your stubs perform the greater chance your test may fail due to an error in your test logic.

This is purposeful. The point of passing the original mime object in two-fold. It is first that it allows you to manipulate the object further when and only when the method is called. This is extremely useful for mocking/stubbing very dynamic objects whose behavior may change based on a method call. Secondly, it allows you to return the mimicked object.

Think of a method, for example that might expect two arguments, set a number of properties, and then return itself. Now imagine it has a second method, which may also alter one of those properties and return something else completely. This is pretty straightforward to do with parody:

    Mime::create('Vendor\Project\Class')
        ->onCall('method1')->expect('arg1', 2)->give(function($mime) {
            $mime->onGet('property1')->give('totally');
            $mime->onGet('property2')->give('possible');

            return $mime;
        })
        ->onCall('method2')->give(function($mime) {
            $mime->onGet('property1')->give('new value');

            return TRUE;
        });
I am not readily familiar with the syntax of other frameworks... but this seems a lot more flexible than passing arguments to the callback and forcing untested logic into the callbacks.

As I mentioned in another comment -- this is designed for very strict and context sensitive test cases. In principle, everything you should ever expect when calling a method is to give something and get something back, and maybe that it modifies a property. All of this is possible here, the logic of how it transforms what you get to what it gives is irrelevant, you should know the answer to both as a developer. And by removing that logic from the code, you "fake" only the very explicit expectations of the code you're pretending to be.

I think I finally see where you're going with this -- that's very interesting and clever (in a good way). I might suggest that you need better documentation/examples -- it took me a while to see what was going on.
I completely agree with this, and the documentation will be forthcoming on the GitHub wiki - so please follow and keep and eye out. There will also be an article at some point soon on Nettuts which will give a pretty complete example of it mimicking a new object instantiation to resolve a static dependency on an example class being tested.