Added new cool matcher into my framework WatirSplash - #in

Hello!

I’ve just added a new cool matcher #in into my framework WatirSplash
and thought that this could be integrated into RSpec directly actually
if there’s any interest.

WatirSplash uses Watir (or Watir-like) frameworks for testing web
pages via browser. If you’re not familiar with it then here is a short
example how you had to test ajax-heavy application before:

browser.link(:id => “someid”).click

let’s wait up to 5 seconds for div to become visible

browser.wait_until(5) {browser.div(:id => “otherid”).visible?}

It was quite cumbersome and i thought about adding and #in matcher to
all matchers so i can do something like this instead:

clicking the link changed div’s text from “before” to “after” in a

maximum of 2 seconds
expect {
link.click
}.to change {div.text}.from(“before”).to(“after”).in(2)

clicking link makes div as present in a maximum of 2 seconds

link.click
div.should be_present.in(2)

clicking link makes div as visible in a maximum of 2 seconds

expect {
link.click
}.to make {div.visible?}.in(2)

use ActiveSupport for adding more meaning to numbers

require “active_support”
div.should exist.in(2.minutes)

What do you guys think? Should i add that also into rspec-expectations
to make spec-ing easier where timing is involved? :slight_smile:

Jarmo P.

On Apr 16, 2011, at 4:56 PM, Jarmo P. wrote:

browser.link(:id => “someid”).click

require “active_support”
div.should exist.in(2.minutes)

What do you guys think? Should i add that also into rspec-expectations
to make spec-ing easier where timing is involved? :slight_smile:

Jarmo P.

I think I like the idea of a timing constraint, but #in seems too
general to me. In fact, ActiveSupport is adding an #in? predicate [1] to
Object that lets you specify that an object is in a collection:

4.in?([2,3,4])

Also, I’m not sure if I’d want this to be a matcher extension or
something built into rspec core. I’m open to ideas though. Anybody else?

[1] Add support for Object#in? in Active Support by sikachu · Pull Request #258 · rails/rails · GitHub

On Sun, Apr 17, 2011 at 10:01 AM, David C.
[email protected]wrote:

example how you had to test ajax-heavy application before:
link.click

I think I like the idea of a timing constraint, but #in seems too general
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Definitely matcher extension.

What does the “matcher extension” mean? E.g. some separate gem, which
adds that method?

Didn’t know that ActiveSupport adds #in? to Object, but it doesn’t
conflict with matcher’s #in anyway.

Jarmo

On 18 Apr 2011, at 13:49, Jarmo P. wrote:

What does the “matcher extension” mean? E.g. some separate gem, which
adds that method?

Didn’t know that ActiveSupport adds #in? to Object, but it doesn’t
conflict with matcher’s #in anyway.

I think the point is that it clashes conceptually, since they give quite
different meanings to the same word.

Maybe #within_duration would be a more unambiguous name for the matcher
method?

clicking the link changed div’s text from “before” to “after” in a

expect {
Jarmo P.
[1]Add support for Object#in? in Active Support by sikachu · Pull Request #258 · rails/rails · GitHub


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

cheers,
Matt

[email protected]
07974 430184

On Apr 18, 4:21pm, David C. [email protected] wrote:

but it doesn’t
conflict with matcher’s #in anyway.

It conflicts with the name :slight_smile: It’s a problem when we have one name that means
completely different things in different contexts.

It depends :slight_smile: That’s the point of OOP that the methods with the same
name can mean different things if they’re in different context (e.g.
class). And it’s #in vs #in?. Anyway i’m of course open for all
suggestions.

I’ll see how #within_duration feels like in different situations. I
like the shortness of #in :slight_smile:

Cheers,
David

Jarmo

On Apr 18, 2011, at 9:39 AM, Jarmo P. wrote:

On Apr 18, 4:21 pm, David C. [email protected] wrote:

but it doesn’t
conflict with matcher’s #in anyway.

It conflicts with the name :slight_smile: It’s a problem when we have one name that means
completely different things in different contexts.

It depends :slight_smile: That’s the point of OOP that the methods with the same
name can mean different things if they’re in different context (e.g.
class).

Disagree 100%. The point of polymorphism is that a client can talk to
different objects in the same way and expect the same range of results,
whereas the actual implementation can differ from object to object. That
has nothing to do with the idea that #in in one context means “I am in
this array” and in another context means “I’d better finish within this
time.” These are completely different concepts at an abstract level.

And it’s #in vs #in?. Anyway i’m of course open for all
suggestions.

It would still confuse people.

I’ll see how #within_duration feels like in different situations. I
like the shortness of #in :slight_smile:

What do you think of within(n).seconds { … }?

David

On Apr 18, 5:59pm, David C. [email protected] wrote:

What do you think of within(n).seconds { … }?

I’m not sure i understand it fully taking into account the examples
above. Let me try to write them below:
expect {
link.click
}.to change {div.text}.from(“before”).to(“after”).within(2).seconds

link.click
div.should be_present.within(2).seconds

expect {
link.click
}.to make {div.visible?}.within(2).seconds

And what ought to be the syntactic sugar methods for timeframes:
#seconds, #minutes, #hours?

That syntax doesn’t sound too bad, but i see that you wanted to do it
slightly differently by having a block for within(2).seconds… I
think that this removes some of the usages for currently existing
matchers as i’ve shown above.

WDYT?

Jarmo

On Apr 18, 2011, at 7:49 AM, Jarmo P. wrote:

WatirSplash uses Watir (or Watir-like) frameworks for testing web
maximum of 2 seconds
link.click

Definitely matcher extension.

What does the “matcher extension” mean? E.g. some separate gem, which
adds that method?

Not in this case. I meant something like this:

new method in rspec-core

within(2).seconds do
obj.do_expensive_operation
end

vs this:

new method in rspec-expectations

obj.should do_expensive_operation.within(2).seconds

Didn’t know that ActiveSupport adds #in? to Object,

Next release will have it - it’s already in git.

but it doesn’t
conflict with matcher’s #in anyway.

It conflicts with the name :slight_smile: It’s a problem when we have one name that
means completely different things in different contexts.

Cheers,
David

ps - I moved your post to the bottom - please bottom or inline post,
especially on threads that are already moving in that direction.

On Apr 19, 2011, at 3:00 AM, Jarmo P. wrote:

On Apr 18, 5:59 pm, David C. [email protected] wrote:

What do you think of within(n).seconds { … }?

I’m not sure i understand it fully taking into account the examples
above. Let me try to write them below:
expect {
link.click
}.to change {div.text}.from(“before”).to(“after”).within(2).seconds

OK - I think I understand this better from this example. The idea here
is that the matcher should keep asking if div.text == “after” until it
returns true or 2 seconds have passed, whichever comes first, after
which it fails. Correct? If so, then this is different from what I was
envisioning with “within(2).seconds { … }”

I’m resistant to adding this because it opens up a lot of complications
(like how to handle should_not, for one), so I’d prefer to see some
experience with it first.

Have you looked at writing an extension gem that adds this behavior? I
think that would be a great way to go with this, because users could
just add a gem dependency and have access to it, and if it became widely
used we could always talk about merging it later.

WDYT?

David

No opinions on this anymore?

Jarmo

On Apr 19, 4:08pm, David C. [email protected] wrote:

OK - I think I understand this better from this example. The idea here is that
the matcher should keep asking if div.text == “after” until it returns true or 2
seconds have passed, whichever comes first, after which it fails. Correct? If so,
then this is different from what I was envisioning with “within(2).seconds { …
}”

When div.text == “after” before timeout of 2 seconds, then it passes
of course, but i guess you just typed it wrong here. What did you
envision then, could you explain, since it seems that i didn’t fully
understand it either.

I’m resistant to adding this because it opens up a lot of complications (like
how to handle should_not, for one), so I’d prefer to see some experience with it
first.

#should_not just waits the time of specified timeout and fails if the
should_not is not satisfied before… if it is satisfied before
timeout, then matcher succeeds.

For example:
h = {:special => true}
Thread.new {sleep 0.5; h.delete :special}
h.should_not have_key(:special).in(1)

h = {:special => true}
expect {
h.should_not have_key(:special).in(0.1)
}.to raise_error

Did i get it wrong in here and should these situations behave somehow
differently instead?

How is currently situations like these handled with RSpec or is
everything asynchronous specc-ed with using mocks?

Have you looked at writing an extension gem that adds this behavior? I think
that would be a great way to go with this, because users could just add a gem
dependency and have access to it, and if it became widely used we could always
talk about merging it later.

I haven’t planned to just release a gem with this minor extension.
Does it really make sense to introduce a completely new gem, which
just adds this functionality?

WDYT?

David

Jarmo