Grab scenario information in Before and After hooks? - ruby

Right now I am trying to grab the information from the current scenario (description, file path, name, etc.). I try to get the scenario information in the before hook like this
Before do |scenario|
puts scenario.name
puts scenario.description
#etc.
end
however things like scenario.description are not available for use. This is because when running in both Before and After hook, scenario is being called as Cucumber::RunningTestCase::Scenario instead part of the core AST module, like feature. I want to be able to access the scenario from Cucumber::Core::Ast::Scenario and Cucumber::Core::Ast::OutlineTable::ExampleRow, where values like current scenario description is available. Is it possible to get access to Cucumber::Core::Ast::Scenario in before and after hooks instead of Cucumber::RunningTestCase::Scenario, or another way to grab information like scenario name, description, file path, etc.? This is using the latest version of the cucumber and cucumber core gems (2.4 and 1.5). In addition, I am also no longer to able to access information about the current step, and step count.

Before do |scenario|
all_sources = scenario.outline? ? scenario.scenario_outline.all_source : scenario.all_source
end
From the all_source variable you will have access to several objects from ::Ast
Scenario Outline:
Cucumber::Core::Ast::Feature
Cucumber::Core::Ast::ScenarioOutline
Cucumber::Core::Ast::Examples
Cucumber::Core::Ast::ExamplesTable::Row:
Cucumber::Core::Ast::ExpandedOutlineStep
Scenario:
Cucumber::Core::Ast::Feature
Cucumber::Core::Ast::Scenario
Cucumber::Core::Ast::Step
From these you should be able to get data about file path, descriptions, comments, tags, hooks, line numbers and so on.

Related

How can I gather all the tags for a Feature file?

I am trying to leverage the tag names that are associated with a feature file in my cucumber ruby Framework. Below is what I am currently doing to gather the tag names using a Before hook, but unfortunately more code other than just the tags are being collected.
Before do |scenario|
#feature_tags = scenario.feature.tags
end
Take for example this sample feature file snippet:
#regression #etc
Feature: File description for something
Background:
* etc etc etc
Scenario: Description for something
* etc etc etc
What is currently being captured with the above hook is:
[#<Cucumber::Core::Ast::Tag "#regression" (features/long/file/path.feature:1)>,
#<Cucumber::Core::Ast::Tag "#etc" (features/long/file/path.feature:1)>]
Is there any way that I can isolate simply the tag names ie: "#regression" ?
Try the below.
scenario.source_tag_names

How do I programmatically set a content_security_policy?

I'm configuring the Content Security Policy for our Rails 5.2 app. I need to whitelist some domains in our CSP. I'd like to put the list of domains elsewhere so I can reference them in other places in the application, then generate the CSP headers programmatically from that list.
Looking at the source code for the Content Security Policy configuration mechanisms in Rails 5, it looks like there's some magic metaprogramming going on, so it's not clear to me how to accomplish what I need to do. It looks like the functions I need to call to set headers might be picky about how exactly they want to be called. In particular, it's not clear to me if I can pass them arrays or safely call them multiple times, or if they do some metaprogramming magic that only works if the domains are passed in as individual function arguments.
Can I pass in an array to the header I want to set, like this?
whitelisted_domains = ['https://example.com', 'self']
Rails.application.configure do
config.content_security_policy do |csp|
csp.child_src whitelisted_domains
end
end
Or can I call the same function multiple times, like this?
whitelisted_domains = ['https://example.com', 'self']
Rails.application.configure do
config.content_security_policy do |csp|
whitelisted_domains.each {|domain| csp.child_src domain}
end
end
If neither of those will work, what's the best way of accomplishing what I want to do?
From what I can tell from sourcecode and documentation, it takes an array. From the edgeguides at rails, posting following
Rails.application.config.content_security_policy do |policy|
policy.default_src :self, :https
...
end
and the sourcecode, using *sources as param; it believe it takes any number of arguments, meaning you could do something along the lines of;
whitelisted_domains = ['https://example.com', 'self']
Rails.application.configure do
config.content_security_policy do |csp|
csp.child_src(*whitelisted_domains)
end
end
https://blog.sqreen.io/integrating-content-security-policy-into-your-rails-applications-4f883eed8f45/
https://edgeguides.rubyonrails.org/security.html#content-security-policy
Sourcecode of define_method for each directive
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/content_security_policy.rb#L151
(note: None of this has been tested in a Rails app, simple looking guides and source code of Rails)

Using git log object in ruby

I'm modifying a ruby gem.
Currently returning a git log object between 2 revision numbers correctly:
def log(repo, prev_rev, this_rev)
repo.log.between(prev_rev, this_rev)
end
And storing the commit message using:
gitlog_item.each do |commit|
#message = commit.message
My question is what other information is available from this object? Specifically I'm looking for something that can identify the commit uniquely such as an ID, or date & time.
If you want to see the entirety of what your gitlog_item contains, you can simply inspect it, like so:
puts gitlog_item.inspect
That'll output the entire object to your console, so you can see everything that's available to you in that object.
This should be the documentation you are looking for.
Methods sha and committer_data seems to do for you.

HP UFT API Test - Saving Response/Checkpoint values

Is there a way to capture and store (or write to a file) the values returned in the Response? (Checkpoint values)
Using HP UFT 11.52
Thanks,
Lynn
I figured it out. In UFT API under Standard Activities, there are File function modules including "Write to File". I added the module to the test, set the path and other properties, passed the variable to the file and it worked! Couldn't be easier.
I mentioned this on my other answer , you can also write it programatically if you have dynamic array response please refer below:
https://stackoverflow.com/a/28012383/3972994
After running a test, in the test folder, you can find a Snapshots/LastIteration directory.
In it you can find the return value for each step saved in a txt file.
Pay attention that if you data drive the step, only the last iteration will be saved to file.
However, in the Test's log (Test dir/Log/vtd_user.log) you can find all the iterations persisted
Thanks,
Yossi
You do not need to use the standard activities if you do this
var iResponse = this.Activity.responsebody;
System.IO.File.WriteLines(#"directorypath&FileName);
the above will write the response to the file and rewrite it for every run

Is it better idea to save elements in yml file?

I'm writing automated tests using Selenium WebDriver with Ruby. So, I'm thinking to keep elements in another file and actual code in another file. And for Ruby, I found yaml gem which allows to store data and access it. Hence I stored elements in lib.yml and test code in test.rb as following:
lib/lib.yml
homepage:
frame: 'mainPage'
email: 'loginPage-email'
password: 'loginPage-password'
login_button: 'btnLogin'
tests/test.rb
require 'selenium-webdriver'
require 'yaml'
driver = Selenium::WebDriver.for :firefox
driver.get 'http://www.abc.com'
config = YAML.load_file('./lib/lib.yml')
driver.switch_to.frame(config['homepage']['frame'])
email = driver.find_element(:id, config['homepage']['email'])
password = driver.find_element(:id, config['homepage']['password'])
email.clear
email.send_keys 'abc#gmail.com'
password.clear
password.send_keys 'password'
driver.find_element(:id, config['homepage']['login_button']).click
driver.quit
This way maintenance becomes easier. I just want to make sure if doing so is a good way or not. I'm asking because I'm trying this first time and don't know what difficulties I'll run into if I choose this for larger project.
I know, using Page object model, we can achieve same thing. But I don't know about Page object. So should I avoid using yml gem and directly go for page object gem?
Also, can someone explain how using yml will not be good idea(if it's not)?
Note:
In above code, config['homepage']['something'] is repetitive code. I'll write method to avoid repetition for that.
Yeah this definitely is useful... It keeps the changes to minimum when there is UI change in future.. You always have just one place to edit... Is there any data you have to pass to your code? How are storing the automation data passed to your test.. The only concern might be you might end up with too many yaml files which could be difficult to keep track...
In your specific case I don't see how this adds much value. Half of the settings (frame, login_button) won't change for your tests, so I suggest leaving them directly in the code where they are used. The html structure is not something that usually changes.
The other two values (email, password) seem like they might change when you want to try out different users (i.e. different cases). If you have one test with several example inputs then I suggest using a more readable solution as Cucumber.
(I'd suggest using capybara anyway for testing browser interaction, as it abstracts away many details of the underlying driver)
Apart from that, yaml is usually the ruby way for storing configuration.
I added one more step: Declared locator (id, name etc) in the yaml itself.
Ex:(yaml)
Declared env.rb which load the environment from yaml files
env.yml:
LOGIN:
UserName: {id: UserName}
Password: {id: Password}
RememberME: {id: RememberMe}
Submit: {xpath: "//input[#value='Log On']"}
Then added "pages\Login.rb"
#Loads all objects from yaml
def get_objects
username=#browser.find_element( $object_array['LOGIN']['UserName'])
password=#browser.find_element( $object_array['LOGIN']['Password'])
remember_me=#browser.find_element( $object_array['LOGIN']['RememberME'])
submit= #browser.find_element($object_array['LOGIN']['Submit'])
end
#Added methods in this class like
def loginas(uname,pass)
username.send_keys uname
password.send_keys pass
remember_me.click
submit.click
end #loginas_siteadmin
Created Tests file Login_tests.rb
lp=LoginPage::new(#browser)
lp.navigate
lp.loginas('SiteAdmin','password123')
This way your scripts and maintainable and most importantly you are free of any other external gem or dependency.

Resources