Jump to page: 1 2
Thread overview
A technique to mock "static interfaces" (e.g. isInputRange)
May 25, 2016
Atila Neves
May 25, 2016
Alex Parrill
May 26, 2016
Atila Neves
May 29, 2016
Era Scarecrow
May 29, 2016
Seb
May 26, 2016
Atila Neves
May 26, 2016
Gary Willoughby
May 26, 2016
Atila Neves
May 26, 2016
Jacob Carlborg
May 27, 2016
Atila Neves
May 27, 2016
Jacob Carlborg
May 29, 2016
Atila Neves
May 30, 2016
Jacob Carlborg
May 25, 2016
There was talk in the forum of making it easier to come up instantiations of say, an input range for testing purposes. That got me thinking of how mocking frameworks make it easy to pass in dependencies without having to write a whole new "test double" type oneself. How would one do that for what I've started calling "static interfaces"? How would one mock an input range?

There's no way to inspect the code inside the lambda used in isInputRange or any other similar template constraint (.codeof would be awesome, but alas it doesn't exist), but a regular OOP interface you can reflect on... and there's even one called InputRange in Phobos... hmmm.

The result is in the link below. The implementation is a bit horrible because I cowboyed it. I should probably figure out how to make it more template mixin and less of the string variety, but I was on a roll. Anyway, take a look at the unit test at the bottom first and complain about my crappy implementation later:


https://gist.github.com/atilaneves/b40c4d030c70686ffa3b8543018f6a7e


If you have an interface already I guess you could just mock that, but then you wouldn't be able to test templated code with it. This technique would fix that problem.


Interesting? Crazy? Worth adding to unit-threaded? Phobos (after much cleaning up)?


Atila



May 25, 2016
On Wednesday, 25 May 2016 at 21:38:23 UTC, Atila Neves wrote:
> There was talk in the forum of making it easier to come up instantiations of say, an input range for testing purposes. That got me thinking of how mocking frameworks make it easy to pass in dependencies without having to write a whole new "test double" type oneself. How would one do that for what I've started calling "static interfaces"? How would one mock an input range?
>
> There's no way to inspect the code inside the lambda used in isInputRange or any other similar template constraint (.codeof would be awesome, but alas it doesn't exist), but a regular OOP interface you can reflect on... and there's even one called InputRange in Phobos... hmmm.
>
> The result is in the link below. The implementation is a bit horrible because I cowboyed it. I should probably figure out how to make it more template mixin and less of the string variety, but I was on a roll. Anyway, take a look at the unit test at the bottom first and complain about my crappy implementation later:
>
>
> https://gist.github.com/atilaneves/b40c4d030c70686ffa3b8543018f6a7e
>
>
> If you have an interface already I guess you could just mock that, but then you wouldn't be able to test templated code with it. This technique would fix that problem.
>
>
> Interesting? Crazy? Worth adding to unit-threaded? Phobos (after much cleaning up)?
>
>
> Atila

Have you looked at std.typecons.AutoImplement at all? http://dlang.org/phobos/std_typecons.html#.AutoImplement

It seems to do something similar to what you're doing, though it generates a subclass rather than a struct (for the purposes of testing contracts and stuff, I don't think it matters too much).
May 25, 2016
+1 having a look at AutoImplement

For testing ranges, I usually use https://github.com/dlang/phobos/blob/master/std/internal/test/dummyrange.d
even though its internal ;-)

anyway, more and better testing always good.

p.s. I think at some point we have to build some (the perfect) mocking framework with dependency injection and all the other awesome stuff. But before that can happen we have to lose the fear of classes and OO. Please no OT!

May 26, 2016
On Wednesday, 25 May 2016 at 21:38:23 UTC, Atila Neves wrote:
> There was talk in the forum of making it easier to come up instantiations of say, an input range for testing purposes. That got me thinking of how mocking frameworks make it easy to pass in dependencies without having to write a whole new "test double" type oneself. How would one do that for what I've started calling "static interfaces"? How would one mock an input range?

I have a mocking framework here:

https://github.com/nomad-software/dunit

Maybe that is useful? The only problem with mine is that it needs to be injected inside an interface. Like this:

interface InputRange(T) {
    @property T front();
    void popFront();
    @property bool empty();

    mixin Mockable!(InputRange!(T));
}

auto mock = InputRange.getMock()
May 26, 2016
On Wednesday, 25 May 2016 at 21:52:37 UTC, Alex Parrill wrote:
> On Wednesday, 25 May 2016 at 21:38:23 UTC, Atila Neves wrote:
>> [...]
>
> Have you looked at std.typecons.AutoImplement at all? http://dlang.org/phobos/std_typecons.html#.AutoImplement

I'd never seen it before, thanks! Doesn't do the same thing - I was trying to get a struct that could be passed to generic algorithms, and that could be programmed like a regular mock. My example only shows return value programming, but it was a quick and dirty prototype.

Atila
May 26, 2016
On Wednesday, 25 May 2016 at 22:07:07 UTC, Robert burner Schadek wrote:
> +1 having a look at AutoImplement
>
> For testing ranges, I usually use https://github.com/dlang/phobos/blob/master/std/internal/test/dummyrange.d
> even though its internal ;-)

Internal, and not really a mock. I used a range as an example - anything with an accompanying interface would be supported.

> anyway, more and better testing always good.

Indeed :)

>
> p.s. I think at some point we have to build some (the perfect) mocking framework with dependency injection and all the other awesome stuff. But before that can happen we have to lose the fear of classes and OO. Please no OT!

What's wrong with dmocks revived (I've never used it)? I'm not afraid of classes, I was just trying to extend mocking to static interfaces since there's so much emphasis on them in D. Regular mocking is boring and easily doable :P

Atila


May 26, 2016
On Thursday, 26 May 2016 at 08:08:01 UTC, Gary Willoughby wrote:
> On Wednesday, 25 May 2016 at 21:38:23 UTC, Atila Neves wrote:
>> There was talk in the forum of making it easier to come up instantiations of say, an input range for testing purposes. That got me thinking of how mocking frameworks make it easy to pass in dependencies without having to write a whole new "test double" type oneself. How would one do that for what I've started calling "static interfaces"? How would one mock an input range?
>
> I have a mocking framework here:
>
> https://github.com/nomad-software/dunit
>
> Maybe that is useful? The only problem with mine is that it needs to be injected inside an interface. Like this:

That's a showstopper for me.

Atila
May 26, 2016
On Thursday, 26 May 2016 at 09:42:59 UTC, Atila Neves wrote:
> Internal, and not really a mock. I used a range as an example - anything with an accompanying interface would be supported.

I see, I thought as much

> What's wrong with dmocks revived (I've never used it)? I'm not afraid of classes, I was just trying to extend mocking to static interfaces since there's so much emphasis on them in D. Regular mocking is boring and easily doable :P

I was not clear. I mean, D has a community has to get past its GC Angst.


May 26, 2016
On 2016-05-25 23:38, Atila Neves wrote:

> Interesting? Crazy? Worth adding to unit-threaded? Phobos (after much
> cleaning up)?

Interesting, yes. Crazy, not enough :). Here's an example of replacing functions and replacing methods on individual objects [1].

I'm trying to do something like you can do in Ruby where there are mocking frameworks allowing you to replace any method with a new implementation, both on a class and object level. Not sure how bad it actually is to do something like this :)

One advantage of this technique is that the code does not need to be adapted for testing. For example, no need to make a function into a template just to be able to pass in a mock object/struct. Or if a function you would like to test writes to a file as a side effect for some reason. Just replace the "write" function with a dummy function that does nothing to avoid creating the file when running the test.

[1] https://dpaste.dzfl.pl/bfd933702ed6

-- 
/Jacob Carlborg
May 27, 2016
On Thursday, 26 May 2016 at 20:03:50 UTC, Jacob Carlborg wrote:
> On 2016-05-25 23:38, Atila Neves wrote:
>
>> [...]
>
> Interesting, yes. Crazy, not enough :). Here's an example of replacing functions and replacing methods on individual objects [1].
>
> [...]

I get an SSL warning for that link.

Atila
« First   ‹ Prev
1 2