-
-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extended expect syntax and more #73
Conversation
I did rebase and squashed changes to one commit for your convenience. |
I like this, a lot! |
{Answer, Expects} | ||
catch | ||
_:Error -> | ||
throw({"Undefined expectation", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should simulate a function_clause
error instead of throwing our own custom exception here. Creating an expectation that only accepts [1001]
as arguments should be considered to be faking a function equivalent to f(1001) -> ...
.
Internal data representatin needs to be changed to allow support for hamcrest argument matchers and argument dependent sequences and loops. Extend expect syntax to allow Arg patterns The syntax of expect function was extended to allow defining expectition through a list of Arg patterns like ['_', 1, blah] and define results as any of sequence, loop, or value. Fix merge mistake
Exports one per line; Corrected when clauses; Code kept to 80 chars per line; One liners formatted to one line.
Deprecate obsolete functions to encourage usage of the new API, that is expect/3,4 + seq/1,loop/1,/val/1.
Match specification compilation was moved to the calling process to be make matching more time efficient.
@eproxus, I removed rebar.config and .gitignore changes from the original commit and that whipped out almost all your comments. Fortunately I managed to address all of them anyway. Please take a look. |
@eproxus have you had a chance to take a look at the changes? |
Sorry for the late reply. I'm planning to pull this in ASAP, I'll keep you posted. |
@eproxus just want to let you know that I've got another pull request coming that is based on this one. It will introduce 'honest' mocks that is mocks that allow you to create expectations for exported functions only. That will for example make your unit test fail if a module, mocked in your unit test, was updated to add a new parameter to a function that you have expectations for, hereby detecting the fact that you forgot to update your module and unit test earlier. |
%% function. Values of `ret_spec' are constructed by {@link seq/1}, | ||
%% {@link loop/1}, and {@link val/1} functions. They are used to specify | ||
%% return values in {@link expect/3} and {@link expect/4} functions. | ||
-type ret_spec() :: term(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the opaque
directive: -opaque my_opaq_type() :: Type.
(see http://www.erlang.org/doc/reference_manual/typespec.html#id75447)
Also, you've managed to make creation of expect functions faster. 👍 Before:
After:
Note however that the "shortcut" versions of the expects (e.g. |
Glad to hear about the performance though it was not intentional. I addressed the most of your comments as good as I could manage at such late hour :) |
Seems like this is it :) |
@eproxus I do not want to sound pushy but is it possible to speed up code inspection a little? I have got 3 more pull requests coming. |
Extended expect syntax and more
Sorry for the incredibly long lag on my responses. I've now merged this into develop so we can let it brew for a while. Nice work! :-) |
Thanks! ...to be continued :-) |
With this patch I would like to suggest the following changes:
Previously sequences of return values could be defined through special sequence and loop functions. This patch introduces an alternative syntax that allows defining return specifications right in the expect function. Consider:
meck:expect(Mod, f, 1, meck:val(a)), % equivalent to meck:expect(Mod, f, 1, a)
?assertEqual(a, Mod:f(1001)),
?assertEqual(a, Mod:f(1001)),
meck:expect(Mod, f, 1, meck:seq([a, b])),
?assertEqual(a, Mod:f(1001)),
?assertEqual(b, Mod:f(1001)),
?assertEqual(b, Mod:f(1001)),
meck:expect(Mod, loop, 1, meck:loop([a, b])),
?assertEqual(a, Mod:loop(1001)),
?assertEqual(b, Mod:loop(1001)),
?assertEqual(a, Mod:loop(1001)),
Previously expectations can be defined either as func-name/arity or as func-name/anon-func. This patch introduces the third way which is defining an expectations through a list of arg pattern/values just like defining an ordiry function but shorter. Consider:
meck:expect(Mod, f, [{[1, 1], a},
{[1, ''], b},
{['', '_'], c}]),
?assertEqual(a, Mod:f(1, 1)),
?assertEqual(b, Mod:f(1, 2)),
?assertEqual(c, Mod:f(2, 2)).
Combining return specifications and argument patterns you can create quite sophisticated expectations. Consider:
meck:expect(Mod, f, [{[1, 1], meck:seq([a, b, c])},
{[1, ''], meck:loop([d, e])},
{['', '_'], meck:val(f)}]),
?assertEqual(d, Mod:f(1, 2)),
?assertEqual(f, Mod:f(2, 2)),
?assertEqual(e, Mod:f(1, 2)),
?assertEqual(a, Mod:f(1, 1)),
?assertEqual(d, Mod:f(1, 2)),
?assertEqual(b, Mod:f(1, 1)),
?assertEqual(c, Mod:f(1, 1)),
?assertEqual(f, Mod:f(2, 2)),
?assertEqual(c, Mod:f(1, 1)),
?assertEqual(e, Mod:f(1, 2)),
?assertEqual(c, Mod:f(1, 1)).
Besides internal data structure redesign made in the scope of this patch allows easier introduction of hamcrest patterns into the expectation definition.
Adam, please consider this changes and provide your comments.