Can anyone see the obvious msitake I've made?

K

Kev Jackson

Hi,

I'm hacking up some scripts and I have a lot of repetitive code ie:

#corporate name
@@ie.text_field:)id,
@test_data['pg_401']['corp_nm_fld']).value=@test_data['pg_401']['corp_nm']
@@ie.text_field:)id,
@test_data['pg_401']['corp_nm_kn_fld']).value=@test_data['pg_401']['corp_nm_kn']
#rep name
@@ie.text_field:)id,
@test_data['pg_401']['rep_j_pos_fld']).value=@test_data['pg_401']['rep_j_pos']
@@ie.text_field:)id,
@test_data['pg_401']['rep_nm_fld']).value=@test_data['pg_401']['rep_nm']
@@ie.text_field:)id,
@test_data['pg_401']['rep_nm_kn_fld']).value=@test_data['pg_401']['rep_nm_kn']
#telephone
@@ie.text_field:)id,
@test_data['pg_401']['tel_no_1_fld']).value=@test_data['pg_401']['tel_no_1']
@@ie.text_field:)id,
@test_data['pg_401']['tel_no_2_fld']).value=@test_data['pg_401']['tel_no_2']
...

It looks like a perfect place to use a macro to write out the call to
ie.text_field at run-time (especially because of the duplicated variables)

I've written a method_missing method in my base class and tried to
implement something like
@@ie.text_field:)id,
@test_data['pg_401']['tel_no_1_fld']).value=@test_data['pg_401']['tel_no_1']
=> text :id, :pg_401, :tel_no_1

This would dramatically reduce the amount of typing (and it'll reduce
the training time for the qc team who ultimately have to write these
scripts), and may allow me to refactor further so that the entire test
script could be constructed from a yml file on the fly - which would
save a *lot* of hassle.

Now I've changed @@ie to $ie as it makes more sense (watir and I only
want to be driving one ie window at once, so make it a global)

in my method_missing definition I have

when /text/=~m.id2name
#works
$ie.text_field:)id,
eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']").to_s).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']"))
#doesn't work args[0] = id
$ie.text_field("#{args[0].to_sym}",
eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']")).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']"))

What I want to do is to create a call to $ie.text_field with the correct
params - as you can see if I specify the symbol :id, it works perfectly
(not sure eval is the correct thing to use but it works), however if I
try to get the symbol from the args[] and then to_sym before executing,
I always get

testScenario(NewApplicationTest):
Watir::Exception::UnknownObjectException: Unable to locate object, using
id and
form:address1

However I've just tried (as I was typing this email)
$ie.text_field(eval("args[0].to_sym"),
eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']")).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']"))

And it works! :(

Can anyone explain why #{args[0].to_sym} is not actually evaluating to
the :id symbol, but eval(args[0].to_sym) does? Especially as the error
produced from watir is exactly the same as if I'd have typed:

$ie.text_field:)id, 'a_field_that_doesn't_exist')

Also if there is a better way to do this without using three eval calls
per method that I want to add (seems a little overkill to me)

Thanks
Kev
 
D

dblack

Hi --

Can anyone explain why #{args[0].to_sym} is not actually evaluating to the
:id symbol, but eval(args[0].to_sym) does? Especially as the error produced
from watir is exactly the same as if I'd have typed:

$ie.text_field:)id, 'a_field_that_doesn't_exist')

I'm not sure about that part, but I think the problem probably stems
from the fact that "#{'sym'.to_sym}" is a string. Anything inside the
#{...} construct gets to_s called on it, which trumps the internal
to_sym call.


David

--
David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
D

Dave Burt

Kev said:
Can anyone see the obvious msitake I've made?

It's "msitake" - should be "mistake" ;)

No, really...
...
@@ie.text_field:)id,
@test_data['pg_401']['tel_no_2_fld']).value=@test_data['pg_401']['tel_no_2']
..

It looks like a perfect place to use a macro to write out the call to
ie.text_field at run-time (especially because of the duplicated variables)

I've written a method_missing method in my base class and tried to
implement something like
@@ie.text_field:)id,
@test_data['pg_401']['tel_no_1_fld']).value=@test_data['pg_401']['tel_no_1']
=> text :id, :pg_401, :tel_no_1
...
Now I've changed @@ie to $ie as it makes more sense (watir and I only want
to be driving one ie window at once, so make it a global)

This is the obvious solution to me:

# call: text "pg_401", "tel_no_1"
def text(test_id, field_name)
$ie.text_field:)id, $test_data[test_id][field_name + '_fld']).value =
$test_data[test_id][field_name]
end
in my method_missing definition I have

when /text/=~m.id2name

That will match any method call with "text" in the name. Why do you want
that? Just define the method you want ("text").
#works
$ie.text_field:)id,
eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']").to_s).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']"))

You should not need eval to do this. Not at all. The above line is the same
as:
$ie.text_field:)id, ($test_data[args[1].to_s][args[2].to_s +
'_fld']).to_s).set(
$test_data[args[1].to_s][args[2].to_s])

Which you can simplify to this if you assume args[1] and args[2] are
strings:
$ie.text_field:)id, $test_data[args[1]][args[2] +
'_fld']).set($test_data[args[1]][args[2]])

Summary: less string interpolation, less to_s, and no eval. Keep it simple,
just deal with variables. You're just making it needlessly complicated and
confusing yourself.
#doesn't work args[0] = id
$ie.text_field("#{args[0].to_sym}",
eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']")).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']"))

Let's look at this: "#{args[0].to_sym}"

args[0] is being cast to Symbol, then back to String because it's being
interpolated into one.

Hint: "#{x}" is just a strange way of writing x.to_s. If you expect x to be
a string, it's the same as just plain old x. "Anything in between quotes"
will always give you a string.

So, removing the evals and string interpolations, we get:
$ie.text_field(args[0].to_sym.to_s, $test_data[args[1].to_s][args[2].to_s
+ '_fld']).set(
$test_data[args[1].to_s][args[2].to_s])

And then we can remove all the to_s: the first one is an error (the obvious
mistake you're trying to locate), and the rest are unnecessary if we assume
we're being passed a string:
$ie.text_field(args[0].to_sym, $test_data[args[1]][args[2] +
'_fld']).set(
$test_data[args[1]][args[2]])

A little easier on the eyes?
What I want to do is to create a call to $ie.text_field with the correct
params - as you can see if I specify the symbol :id, it works perfectly
(not sure eval is the correct thing to use but it works), however if I try
to get the symbol from the args[] and then to_sym before executing, I
always get

testScenario(NewApplicationTest):
Watir::Exception::UnknownObjectException: Unable to locate object, using
id and
form:address1

I would expect Watir to be a little more helpful by either accepting the
"id" that you're passing, or telling you that it doesn't know how to locate
objects using a string rather than the symbol it's expecting. I'll ask Bret
about improving this.

(As I explained earlier in this message, your "to_sym" was interpolated into
a string, so you were sending a string to text_field.)
However I've just tried (as I was typing this email)
$ie.text_field(eval("args[0].to_sym"),
eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']")).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']"))

And it works! :(

Can anyone explain why #{args[0].to_sym} is not actually evaluating to the
:id symbol, but eval(args[0].to_sym) does? Especially as the error
produced from watir is exactly the same as if I'd have typed:

"#{1 + 1}" is the same as (1 + 1).to_s, as I explained earlier.
eval("1 + 1") is the same as (1 + 1).

Cheers,
Dave
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top