Closed jim-edwards closed 1 year ago
Thanks for writing this up Jim. I suspect that the Transform
call here is not providing the replacement for the step And I assign the LOCAL variable name "TEST" the value "auto_RANDOMALPHANUMERIC_5"
but only for the data table values. I expect you have another step def somewhere that's also calling TestSys::Easy.current_session.helper.process_random_number
You're right that parameter types only work for regular steps, not for data tables. I think your workaround for now would be to refactor to extract a helper method out of your Transform
function:
Transform /table:.*/ do |table|
expand_placeholders_in table
end
module Helpers
def expand_placeholders_in(table)
table.map_headers! { |header| header.downcase.to_sym }
table.hashes.each do |row|
row.each do |column, value|
if row[column] =~ /_CONFIG_/
row[column]=TestSys::Easy.current_session.helper.add_config_settings(row[column])
end
if row[column] =~ /_UNIQ_/
row[column]=TestSys::Easy.current_session.helper.replace_uniq_strings(row[column])
end
if row[column] =~ /_LOCAL_/
row[column]=TestSys::Easy.current_session.helper.add_local_settings(row[column])
end
if row[column] =~ /_FEATURE_/
row[column]=TestSys::Easy.current_session.helper.add_feature_settings(row[column])
end
if row[column] =~ /_RANDOMHEX_/
row[column]=TestSys::Easy.current_session.helper.add_hex_string(row[column])
end
if row[column] =~ /_RANDOMALPHANUMERIC_/
row[column]=TestSys::Easy.current_session.helper.process_random_number(row[column])
end
if row[column].include? '\s'
row[column] = row[column].gsub('\s', ' ')
end
end
end
table
end
World(Helpers)
Then, you can use that helper function to manually expand the placeholders everywhere you take a table as a parameter:
Given /a step that takes a table:/ do |table|
expand_placeholders_in table
... # do stuff with the expanded table data
end
That would at least allow you to get rid of the dependency on Transform
and upgrade to a more modern version of Cucumber while we figure out how to implement this functionality again.
So in essence the issue here is that we cannot use the cukeexp parameter type because the capture is done anonymously (i.e. a {}
is not provided because it's a data table).
Instead of trying to make a fit b, why don't we come at this from a different way @mattwynne
Why don't we make the table "methods" and manipulability bits function outside, maybe through including a helper or setting a config option? Although they already are by default available in the cucumber world, so actually this point is redundant!
Also whilst I haven't tried it. In theory could you not capture the data table using a regex that included new lines (I appreciate that's not pretty)
@luke-hill yes, I think that's the essence of the problem.
I was just suggesting a workaround for the OP, given the way things are.
I'm sure we could add something, either as a standalone helper, or something in the DSL (e.g. TransformDataTables
) or as methods on the DataTable
instances, to help people do this. We need to understand a bit more about the use-cases, I think.
The primary use-case we are using it for is to allow variables to be set in the feature itself, which is replaced by the code to an actual value. For example:
Replace the string "auto_RANDOMALPHANUMERIC_5" with something like "auto_ABC4321_5". Or some other variable, doesn't have to just be random data.
@mattwynne The general case, turning a table into any other arbitrary object is useful. If an object is used in multiple step definitions it avoids the need to do so in each step.
The common/datatable module has several examples.
@luke-hill
Because ruby lacks types you'll need a way in the step definition to select which table transform should be used. Something like:
Given /a step that takes a table:/, expand_place_holders do |table|
... # do stuff with the expanded table data
end
Dunno if that works for ruby. In this case expand_place_holders
is a function that processes the table and has access to the world context.
So @jim-edwards you'd like a way to be able to map over the cells in the table and transform the values in some of them, ideally before they're passed to the step definition?
Sorry, missed the notification on this response. Yes, the idea is the variables can be "replaced", basically a search and replace. Ideally before the step is run, otherwise every single step must be modified to do the variable replacement (1,000s in our case). This is really useful for creating variables and reference them by name, so there can be for example, things loaded from the config file, command-line, or random values generated or even save/recall simple variables. All are possible with the previous system without having to specifically code the step to accept the variable itself.
Yeh i think adding these as module helpers and exposing them on the DataTable construct will be the easiest way forwards. Just a case of when/if we prioritise this.
Looking back at this, I've seen we have some methods in place already for altering the keys. symbolise_hashes
takes the input table and converts all the keys to downcased snakecased keys. I would therefore advocate either something locally in your repo or merged into the main whereby you extend the table cell class.
Closing this as two solutions have been specified that would be better solutions.
We have a Transform that loops through table entries and executes functions if the column itself contains some specific data (IE, its based on the result, not the regex). I am struggling to see how this could be done with ParameterType, doesn't seem possible.. Here is a sample of the code for reference:
The above allows the following values to be replaced in steps:
The above transform will do a match, find the RANDOMALPHANUMERIC because its set the value and call the function above, replacing it with the return value from the function.
It also works in a table as you show, for example:
Both of those appear to work. Note that neither use the "Example" framework of a test case to execute the same Scenario multiple times.