formal argument cannot be a class variable in ruby - ruby

I've never used Ruby before, and am attempting to run a program written
long ago. I've installed Ruby 2.4.1 and the gem package [test-unit
3.4.3] OK, but when I try to run it, I get an error:
tcreporter.rb:156: formal argument cannot be a class variable
##tc_array.each do |##tc|
^
Is there something in particular I'm doing wrong?
Below is the code snippet :
class TCReporter
##m = nil; ##c = nil; ##tc = nil; ##status = 'p'; ##notes = nil; ##tlArr = []
##resultMapping = {'p'=>'PASS', 'f'=>'FAIL', 'b'=>'BLOCKED', 's'=>'SKIP','pr'=>'PREQFAIL', 'con'=>'CONERR', 'h'=>'HWSKIP', 'cor'=>'CORE'}
def self.report_result(currentTest, status, notes=nil)
if $trInit
##m = currentTest.split('(')[0] ###m is the test METHOD currently being executed in the framework.
##c = currentTest.split('(')[1].split(')')[0] ###c is the test CLASS currently being executed in the framework
if ##c =~ /(?:#{TESTRAIL_TEST_PREFIXES.join('|')})_\d*$/i #If there's a mapping on the test class then report a test class result.
##tc = ##c.scan(/(?:#{TESTRAIL_TEST_PREFIXES.join('|')})_\d*$/i)[0].upcase.sub('_', '-') #Get the TR class mapping
#When reporting at the test class level, the status always starts out as 'p' (PASS). If there's any
#non-passing status for any test method within the test class (blocked or failed) then use that result
#for reporting. Once the global status '##status' has been updated once then no more updating occurs.
if ##status == 'p' && status != 'p'
##status = status
##notes = notes
end
if eval("#{##c}.public_instance_methods.grep(/^test_/).sort.first") == ##m && eval("#{##c}.public_instance_methods.grep(/^test_/).sort.last") == ##m #The first test method is the last test method. All done, do a TestLink update.
begin
result = TR.report_tc_result(##tc, TESTRAIL_PROJECT, TESTRAIL_MILESTONE, TESTRAIL_PLAN, TESTRAIL_RUN, TESTRAIL_BUILD, ##status, (##notes ? ##notes : notes))
ensure
result.case_id = ##tc
result.class = ##c
result.method = ##m
if !result.success #success means a successful communication with testLink and test case was found and updated.
$trReport = ReportFile.new('tr_report.txt') if !$trReport
$trReport.puts "#{##tc}, #{TEST_ARGS.project}, #{TEST_ARGS.plan}, #{TEST_ARGS.build}, #{TEST_ARGS.platform}, #{##c}, #{##m}, #{status} 'class', #{result.message ||= result.exception}"
end
end
elsif eval("#{##c}.public_instance_methods.grep(/^test_/).sort.first") == ##m #A new test class is being evaluated. Set everything to default except status (use whatever the first test class returned).
##m = nil; ##c = nil; ##tc = nil; ##status = status
elsif eval("#{##c}.public_instance_methods.grep(/^test_/).sort.last") == ##m #Done with the test class. Time to report the test result.
begin
result = TR.report_tc_result(##tc, TESTRAIL_PROJECT, TESTRAIL_MILESTONE, TESTRAIL_PLAN, TESTRAIL_RUN, TESTRAIL_BUILD, ##status, (##notes ? ##notes : notes))
ensure
result.case_id = ##tc
result.class = ##c
result.method = ##m
if !result.success #success means a successful communication with testLink and test case was found and updated.
$trReport = ReportFile.new('tr_report.txt') if !$trReport
$trReport.puts "#{##tc}, #{TEST_ARGS.project}, #{"#{TEST_ARGS.milestone}, " if TEST_ARGS.milestone}#{TEST_ARGS.plan}, #{TEST_ARGS.build}, #{TEST_ARGS.platform}, #{##c}, #{##m}, #{status} 'class', #{result.message ||= result.exception}"
end
end
else #The test class is still being executed. Don't update TestLink yet, just check for a non-passing result.
if ##status == 'p' && status != 'p' #Update the test status if it's a non-pass result. Otherwise, use the earlier failed or blocked status.
##status = status
end
end
end
#If there's a mapping on a test method then report a test method result.
if ##m =~ /(?:#{TESTRAIL_TEST_PREFIXES.join('|')})_\d?[\d_]+$/i
##tc_array = ##m.scan(/(?:#{TESTRAIL_TEST_PREFIXES.join('|')})_\d?[\d_]+$/i)[0].upcase.sub('_', '-').split("_")
if ##tc_array.size > 1
tmp_prefix = ##tc_array[0].split("-").first
tmp_array = []
##tc_array.each do|tmp|
tmp_array << tmp_prefix + "-" + tmp.split("-").last
end
##tc_array = tmp_array
end
##tc_array.each do |##tc|
begin
result = TR.report_tc_result(##tc, TESTRAIL_PROJECT, TESTRAIL_MILESTONE, TESTRAIL_PLAN, TESTRAIL_RUN, TESTRAIL_BUILD, status, notes)
puts status
rescue => e
puts e
ensure
if result && !result.success
$trReport = ReportFile.new('tr_report.txt') if !$trReport
$trReport.puts "#{##tc}, #{TEST_ARGS.project}, #{"#{TEST_ARGS.milestone}, " if TEST_ARGS.milestone}#{TEST_ARGS.plan}, #{TEST_ARGS.build}, #{TEST_ARGS.platform}, #{##c}, #{##m}, #{status} 'class', #{result.message ||= result.exception}"
end
end
end
end
end
end
Thanks in advance

This is fixed now after making "tc" as local variable.

Related

ShadowingOuterLocalVariable rubocop error

here is my code, and here is my error. I think dont need to more descriptions here:
#terminal-error (error on object "= ->(object) do "
lib/form_object/base.rb:18:30: W: Lint/ShadowingOuterLocalVariable: Shadowing outer local variable - object.
need_validation = ->(object) do
def valid?
valid_attributes = []
attributes.each do |attribute_name, _attributes|
attribute_set = self.class.attribute_set[attribute_name]
object = self[attribute_name]
need_validation = ->(object) do
(object.class < FormObject::Base || attribute_set.options[:validate]) && object.respond_to?(:valid?)
end
if need_validation.call(object)
valid_attributes << object.valid?
elsif object.is_a?(Array)
object.each do |nested|
valid_attributes << nested.valid? if need_validation.call(nested)
end
end
end
valid_attributes << super
valid_attributes.all?
end
It's a warning from a lint that you run, which detects cases where you shadow (i.e. hide) another local variable, from an outer scope.
You have:
object = self[attribute_name]
need_validation = ->(object) do
(object.class < FormObject::Base || attribute_set.options[:validate]) && object.respond_to?(:valid?)
end
So the first variable object could not be referred to inside the lambda, as the argument is also called object.
You can remove this warning by simply renaming the parameter of your lambda:
need_validation = ->(obj) do
(obj.class < FormObject::Base || attribute_set.options[:validate]) && obj.respond_to?(:valid?)
end

Code not actually asserting in RSpec?

I'm new to Ruby and in various open source software I've noticed a number of "statements" in some RSpec descriptions that appear not to accomplish what they intended, like they wanted to make an assertion, but didn't. Are these coding errors or is there some RSpec or Ruby magic I'm missing? (Likelihood of weirdly overloaded operators?)
The examples, with #??? added to the suspect lines:
(rubinius/spec/ruby/core/array/permutation_spec.rb)
it "returns no permutations when the given length has no permutations" do
#numbers.permutation(9).entries.size == 0 #???
#numbers.permutation(9) { |n| #yielded << n }
#yielded.should == []
end
(discourse/spec/models/topic_link_spec.rb)
it 'works' do
# ensure other_topic has a post
post
url = "http://#{test_uri.host}/t/#{other_topic.slug}/#{other_topic.id}"
topic.posts.create(user: user, raw: 'initial post')
linked_post = topic.posts.create(user: user, raw: "Link to another topic: #{url}")
TopicLink.extract_from(linked_post)
link = topic.topic_links.first
expect(link).to be_present
expect(link).to be_internal
expect(link.url).to eq(url)
expect(link.domain).to eq(test_uri.host)
link.link_topic_id == other_topic.id #???
expect(link).not_to be_reflection
...
(chef/spec/unit/chef_fs/parallelizer.rb)
context "With :ordered => false (unordered output)" do
it "An empty input produces an empty output" do
parallelize([], :ordered => false) do
sleep 10
end.to_a == [] #???
expect(elapsed_time).to be < 0.1
end
(bosh/spec/external/aws_bootstrap_spec.rb)
it "configures ELBs" do
load_balancer = elb.load_balancers.detect { |lb| lb.name == "cfrouter" }
expect(load_balancer).not_to be_nil
expect(load_balancer.subnets.sort {|s1, s2| s1.id <=> s2.id }).to eq([cf_elb1_subnet, cf_elb2_subnet].sort {|s1, s2| s1.id <=> s2.id })
expect(load_balancer.security_groups.map(&:name)).to eq(["web"])
config = Bosh::AwsCliPlugin::AwsConfig.new(aws_configuration_template)
hosted_zone = route53.hosted_zones.detect { |zone| zone.name == "#{config.vpc_generated_domain}." }
record_set = hosted_zone.resource_record_sets["\\052.#{config.vpc_generated_domain}.", 'CNAME'] # E.g. "*.midway.cf-app.com."
expect(record_set).not_to be_nil
record_set.resource_records.first[:value] == load_balancer.dns_name #???
expect(record_set.ttl).to eq(60)
end
I don't think there is any special behavior. I think you've found errors in the test code.
This doesn't work because there's no assertion, only a comparison:
#numbers.permutation(9).entries.size == 0
It would need to be written as:
#numbers.permutation(9).entries.size.should == 0
Or using the newer RSpec syntax:
expect(#numbers.permutation(9).entries.size).to eq(0)

Strange behavior using CSV class [duplicate]

I'm working on the EventReporter project to help learn Ruby.
Here's what I've got so far:
require 'CSV'
puts 'Welcome to Event Reporter!'
print 'Enter command: '
command = gets.chomp
def clean(attribute, type)
if (type == 'regdate')
elsif (type == 'first_name')
elsif (type == 'last_name')
elsif (type == 'email_address')
elsif (type == 'homephone')
homephone = attribute
homephone = homephone.to_s.gsub(/\D/, '')
if (homephone.length < 10)
homephone = '0000000000'
elsif (homephone.length == 11)
if (homephone[0] == '1')
homephone[0] = ''
else
homephone = '0000000000'
end
elsif (homephone.length > 11)
homephone = '0000000000'
end
return homephone
elsif (type == 'street')
elsif (type == 'city')
elsif (type == 'state')
elsif (type == 'zipcode')
zipcode = attribute.to_s.rjust(5, "0")[0..4]
return zipcode
end
return attribute
end
queue = []
while (command != 'q') do
command = command.split
if (command[0] == 'load')
command[1] ? filename = command[1] : filename = 'event_attendees.csv'
attendees = CSV.open filename, headers: true, header_converters: :symbol
puts "Loaded #{filename}"
elsif (command[0] == 'find')
attribute = command[1]
criteria = command[2]
# REACHES HERE SECOND TIME AROUND
puts "#{command[0]} #{command[1]} #{command[2]}"
attendees.each do |attendee|
# ISNT REACHING HERE SECOND TIME AROUND
puts 'TEST'
# get cleaned attendee attribute
attendee_attribute = clean(attendee[attribute.to_sym], attribute)
# see if it matches the criteria input
if criteria.to_s.downcase.strip == attendee_attribute.to_s.downcase.strip
# if it does, add the attendee to the queue
puts 'Match!'
queue << attendee
end
end
end
print 'Enter command: '
command = gets.chomp
end
It seems that the attendees.each isn't being executed the second time through the while loop. Why is this?
~/practice/event_manager >> ruby 'lib/event_reporter.rb'
Welcome to Event Reporter!
Enter command: load
Loaded event_attendees.csv
Enter command: find zipcode 11111
find zipcode 11111
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
Enter command: find zipcode 11111
find zipcode 11111
Enter command: q
~/practice/event_manager >>
According to the docs, the CSV object behaves basically like a regular IO object. They keep track of their current position in the file which is advanced by reading through it, generally line by line. So on your first attendees.each, you read through the entire file. Subsequent calls to .each will try to read the next line, but there is not any since we are already at the end of the file hence your loop does not execute anymore.
You can fix this by rewinding the underlying IO instance to the beginning of the file, using #rewind. In your specific case, put it after iterating through the attendees.
attendees.each do |attendee|
# ...
end
attendees.rewind

Ruby CSV.each in while loop not executing second time through

I'm working on the EventReporter project to help learn Ruby.
Here's what I've got so far:
require 'CSV'
puts 'Welcome to Event Reporter!'
print 'Enter command: '
command = gets.chomp
def clean(attribute, type)
if (type == 'regdate')
elsif (type == 'first_name')
elsif (type == 'last_name')
elsif (type == 'email_address')
elsif (type == 'homephone')
homephone = attribute
homephone = homephone.to_s.gsub(/\D/, '')
if (homephone.length < 10)
homephone = '0000000000'
elsif (homephone.length == 11)
if (homephone[0] == '1')
homephone[0] = ''
else
homephone = '0000000000'
end
elsif (homephone.length > 11)
homephone = '0000000000'
end
return homephone
elsif (type == 'street')
elsif (type == 'city')
elsif (type == 'state')
elsif (type == 'zipcode')
zipcode = attribute.to_s.rjust(5, "0")[0..4]
return zipcode
end
return attribute
end
queue = []
while (command != 'q') do
command = command.split
if (command[0] == 'load')
command[1] ? filename = command[1] : filename = 'event_attendees.csv'
attendees = CSV.open filename, headers: true, header_converters: :symbol
puts "Loaded #{filename}"
elsif (command[0] == 'find')
attribute = command[1]
criteria = command[2]
# REACHES HERE SECOND TIME AROUND
puts "#{command[0]} #{command[1]} #{command[2]}"
attendees.each do |attendee|
# ISNT REACHING HERE SECOND TIME AROUND
puts 'TEST'
# get cleaned attendee attribute
attendee_attribute = clean(attendee[attribute.to_sym], attribute)
# see if it matches the criteria input
if criteria.to_s.downcase.strip == attendee_attribute.to_s.downcase.strip
# if it does, add the attendee to the queue
puts 'Match!'
queue << attendee
end
end
end
print 'Enter command: '
command = gets.chomp
end
It seems that the attendees.each isn't being executed the second time through the while loop. Why is this?
~/practice/event_manager >> ruby 'lib/event_reporter.rb'
Welcome to Event Reporter!
Enter command: load
Loaded event_attendees.csv
Enter command: find zipcode 11111
find zipcode 11111
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
TEST
Enter command: find zipcode 11111
find zipcode 11111
Enter command: q
~/practice/event_manager >>
According to the docs, the CSV object behaves basically like a regular IO object. They keep track of their current position in the file which is advanced by reading through it, generally line by line. So on your first attendees.each, you read through the entire file. Subsequent calls to .each will try to read the next line, but there is not any since we are already at the end of the file hence your loop does not execute anymore.
You can fix this by rewinding the underlying IO instance to the beginning of the file, using #rewind. In your specific case, put it after iterating through the attendees.
attendees.each do |attendee|
# ...
end
attendees.rewind

Get current Step form Scenario outline

I am trying to access the current step name in for a scenario outline test. The code below works for regular scenarios but fails for scenario outlines.
AfterStep do |scenario|
#step = scenario.steps.find { |s| s.status == :skipped }
#puts step.keyword + step.name
case scenario
when Cucumber::Ast::Scenario
step = scenario.steps.find { |s| s.status == :skipped }
puts step.keyword + ' ' + step.name
#Works correctly
when Cucumber::Ast::OutlineTable::ExampleRow
# **!!!!Exception below!!!**
step = scenario.scenario_outline.steps.find { |s| s.status == :skipped }
puts step.keyword + ' ' + step.name
end
end
Exception:
NoMethodError: undefined method `steps' for #<Cucumber::Ast::OutlineTable::ExampleRow:0x007fe0b8214bc0>
Does anyone know how to resolve this? Or if this is possible?
Try the following way:
Before do |scenario|
...
# step counter
#step_count = 0
end
AfterStep do |step|
current_feature = if scenario.respond_to?('scenario_outline')
# execute the following code only for scenarios outline (starting from the second example)
scenario.scenario_outline.feature
else
# execute the following code only for a scenario and a scenario outline (the first example only)
scenario.feature
end
# call method 'steps' and select the current step
# we use .send because the method 'steps' is private for scenario outline
step_title = current_feature.feature_elements[0].send(:steps).to_a[#step_count].name
p step_title
# increase step counter
#step_count += 1
end
It has to work fine for both 'scenario' and 'scenario outline'
This did not work for me. I had to make some minor changes:
step_title = step.steps.to_a[#step_count].gherkin_statement.name
Updates circa 10/2018
Before do |scenario|
# the scenario in after step is Cucumber::Core::Test::Result::Passed and does not have the data
#scenario = scenario
# step counter
#step_count = 0
end
AfterStep do
feature = #scenario.feature # works for outlines too
if feature.feature_elements[0].respond_to?(:steps)
step_title = feature.feature_elements[0].send(:steps).to_a[#step_count].to_s
else
step_title = feature.feature_elements[0].send(:raw_steps).to_a[#step_count].to_s
end
puts "[finished step] #{step_title}"
# increase step counter
#step_count += 1
end

Resources