Watir-webdriver: get same screenshot images for all failed scenarios - ruby

I've set screenshots to be taken when a scenario fails, but my html report shows the same screenshot on all failed scenarios. Can anyone help and let me know how I can get unique screenshots taken for each failed scenario.
Here is my code in my env.rb:
After do |scenario|
if scenario.failed?
#browser.driver.save_screenshot("screenshot.png")
embed("screenshot.png", "image/png")
end

You are saving the screenshot to the same file each time (ie overwriting the previous screenshot each time). The report has also linked all the images to the same place. This is why you get the same image everywhere.
You need to provide a unique name for the screenshot.
For example, you could timestamp (with date and time) the images:
After do |scenario|
if scenario.failed?
screenshot_file = "screenshot-#{Time.now.strftime('%Y%m%d-%H%M%S')}.png"
#browser.driver.save_screenshot(screenshot_file)
embed(screenshot_file, "image/png")
end
end

Justin has the answer, But while timestamps are fine, they make it harder when looking at the files to know which one was for what scenario. When I run tests while creating and debugging, I often don't even look at the html report, I just look at the generated screenshot, so in that case it is doubly useful to have more logical names.
So the code I use looks like this, and embeds using the scenario name
After do |scenario|
if scenario.failed?
screenshot = "./FAILED_#{scenario.name.gsub(' ','_').gsub(/[^0-9A-Za-z_]/, '')}.png"
#browser.driver.save_screenshot(screenshot)
encoded_img = #browser.driver.screenshot_as(:base64)
embed("data:image/png;base64,#{encoded_img}",'image/png')
end
end
An even more robust approach, dealing with scenario outlines and appending timestamp is described in this 'Two Four One' blog posting so far I've not needed to go that far, but I may pull in stuff from it to deal with scenario outlines.

for the ones using RSpec, there is a really nice implementation of HtmlFormatter in the watir-rspec project

Related

Capybara / Ruby / Cucumber - Making the command Expect to be highlighted in the evidence

I'm generating evidences every time that I run a cucumber scenario. It is working fine, however I would like to improve it a little bit more.
My idea is highlight all the "expect" commands into the evidence to make clear the result.
I'm using a hook to generate the evidence, so I think I have to do something there.
After do
shot_file = page.save_screenshot("log/screenshot.png")
shot_b64 = Base64.encode64(File.open(shot_file, "rb").read)
embed(shot_b64, "image/png", "Screenshot")
end
So, when I declare a expect command I would like to see it in the evidence highlighted.
expect(find(".nav-a.nav-a-2.nav-truncate")).to have_content "Hello, my name"
Any idea guys?
Thank you very much!
You can use the below javascript to highlight the border of the element before taking the screenshot.
element.style.border = '0.5em solid red';
Here is the sample video.

Importing CSV as test data in Cucumber?

We are trying to incorporate CSV into Cucumber to get the benefit of CSV files, but when researching online I see no official documentation on this feature but only "Import scenario outline 'examples' from CSV?".
I am not sure if this comes to any conclusions yet. Is it currently any built-in way to use CSV in Cucumber?
If currently there is no built-in way to import CSV, and I have to write the own parsing method, I think my question will be, in the step definition, how do I hook up the variables with the definition in scenario? For example:
Scenario: do something
Given I eat number as <number> cucumbers
and the cucumber is produced at date as <date>
When the cucumber is expired
Then I should have diarrhea
data.csv
number,date
1,2012-01-01
1,2012-11-03
in the steps.rb, if I do:
CSV.foreach("path/to/data.csv") do |row|
...
How to I map row.number`row.date` to the number\date in the feature file?
In order to use the Examples functionality in cucumber I think you'd have to do some significant metaprogramming that would probably reduce the maintainability and readability of your features. I'd probably accomplish this by wrapping you current steps in another step definition like so:
Scenario: do something
Given I load some data
Then expired cucumbers should give me diarrhea
and the define the step definitions
Then 'I load some data' do
#data = []
CSV.foreach("path/to/data.csv", headers: true) do |row|
#data << row
end
end
Then 'expired cucumbers should give me diarrhea' do
#data.each do |row|
step %Q|I eat number as #{row[:number]} cucumbers|
step %Q|the cucumber is produced at date as #{row[:date]}|
step %Q|the cucumber is expired|
setp %Q|I should have diarrhea|
end
end
The only problem with this is that if one scenario fails, it may take an extra debugging step to figure out which one is failing. Since these steps are run, more or less, under the hood. You could do this pretty easily by printing the row to STDOUT from the step definition:
Then 'expired cucumbers should give me diarrhea' do
#data.each do |row|
puts "row", row.inspect
step %Q|I eat number as #{row[:number]} cucumbers|
step %Q|the cucumber is produced at date as #{row[:date]}|
step %Q|the cucumber is expired|
setp %Q|I should have diarrhea|
end
end
That should give you some indication of which row is giving you trouble.
Erata: I understand your desire to be able to maintain a data sheet separate from the features so that someone like a Project Manager can come up with edge cases and then have those run against the behavior of the code. But I'd almost be more willing to allow them to edit the feature on github and allow CI to run those examples they added to the example table rather than do this approach. In either case its probably something good for regression, but probably really painful to develop code against. This type of testing is sort of the aim of http://fitnesse.org/ and that might be a project of inspiration for you.

Multiple Converters/Generators in Jekyll?

I would like to write a Jekyll plugin that makes all posts available in PDF format by utilizing Kramdown's LaTeX export capabilities. For each post in Markdown format, I'd like to end up with the normal .html post along with a .tex file containing the LaTeX markup and finally a .pdf.
Following the documentation for creating plugins, I see two ways of approaching the problem, either with a Converter or with a Generator.
Converter plugins seem to run after the built-in Converters, so the .markdown files have all been converted to .html by the time they reach the Converter.
When I try to implement a Generator, I am able to use fileutils to write a file successfully, but by the end of Jekyll's cycle, that file has been removed. It seems there's a StaticFile class which you can use to register new output files with Jekyll, but I cannot find any real guidance on how to use it.
If you take a look at the ThumbGenerator class in this: https://github.com/matthewowen/jekyll-slideshow/blob/master/_plugins/jekyll_slideshow.rb you'll seen a similar example. This particular plugin makes thumbnail sized versions of all images in the site. Hopefully it gives a useful guide to how you can interact with Jekyll's StaticFile class (though I'm not a Ruby pro, so forgive any poor style).
Unfortunately, there isn't really documentation for this - I gleaned it from reading through the source.
I wrote this a few months ago and don't particularly remember the details (which is why I gave an example rather than a workthrough), but if this doesn't get you on the right track let me know and I'll try to help.
I try to do the same but with direct html->pdf conversion.
It did not work inside a gitlab-ci pipeline at this time, nonetheless it work on my workstation (see here) with a third possibility : a hook !
(here with pdfkit)
require 'pdfkit'
module Jekyll
Jekyll::Hooks.register :site, :post_write do |post|
post.posts.docs.each do |post|
filename = post.site.dest + post.id + ".pdf"
dirname = File.dirname(filename)
Dir.mkdir(dirname) unless File.exists?(dirname)
kit = PDFKit.new(post.content, :page_size => 'Letter')
kit.stylesheets << './css/bootstrap.min.css'
kit.to_file(filename)
end
end
end

Generalizing Cucumber/Capybara Tests

I wrote a feature to test the default configuration of my web app using Cucumber and Capybara. Part of the feature looked like this:
And the page has a photo labeled "Device"
And the page has a checkbox labeled "Device"
And I check "Device"
And I submit the form
Then the resulting page has no photo labeled "Device"
It worked great. I want users who have installed and configured the web app on their own servers to be able to run the test to help confirm that their configuration is correct. And "Device" is a string in the default config file that the user can change. It's an element in an array and they can add to or remove from the array when configuring their instance of the app.
Is this a sensible use of the tools or am I abusing Cucumber and/or Capybara? If it's sensible, how would I do it? If it's a bad idea, what tools might I use for this instead, if anything?
Here's how I got it to work. I'm just not sure this is the best way to do it.
For this to work, the feature would have to look more like this:
And the page has at least 3 photos, let us call the last one "third_photo"
In the corresponding step definition, I use an XPath to pull out the corresponding label string for the first photo and assign it to a Hash object stored in a class variable.
And /^I the page has at least (\d*) photos, let us call the last one "([^\"]*)"$/ do |n, name|
if ! defined?(#note)
#note = Hash.new;
end
#note[name] = find(:xpath, '//ol[#id="menu"]/li[' +n+ ']/a').text;
end
Subsequent step definitions can now access the value, whatever it was.
So, another feature might be:
Then I uncheck "third_item"
And the corresponding step definition might be:
Then /I uncheck "([^\"]*)"/ do |item|
uncheck(#note[item])
end
But I don't feel good about it. If nothing else, I imagine there might be a name collision with another instance variable defined outside the step definitions.
It feels like I'm either Doing It Wrong or else I'm Using The Wrong Tool. What is the right way to do this?
Don't know what you are fishing after, but it feels like your tests and implementation are quite tightly coupled. Maybe that's the feeling you are having, that it seems like you are describing your app in tests.
I don't have a good answer to your questions, merely because I don't "understand" it. I would however urge you to try to decouple your tests from your implementation and see if there's any abstraction there waiting to be found.
There's a blog post about using instance variables in step definitions at http://www.cloudspace.com/blog/2010/06/23/using-instance-variables-with-cucumber-steps/.
Commenters talk about the coupling this entails and at least one possible way around it.
In particular, davetron5000 says:
What we do is to not use instance variables at all, but instead
provide a has that shared state can go in. This hash is cleared after
each test run. Not ideal, but it's a bit cleaner than random instance
variables all over the place (and also ensures a reasonably clean
state before each test)

Is there a simpler way to write the following cucumber test?

I'm usisng cucmber to test a php app and it's working quite well actually.
I have a cucmber feature that uses the following step to check for the presence of a link in a page:
Then /^I should see a link that contains "(.+)"$/ do |link|
assert !!(response_body =~
/<a ([\w\.]*="[\w\.]*" )*href="(http:\/\/)?([\w\.\/]*)?(#{link})/m), response_body
end
Now, this works but it's butt ugly and complicated.
Originally I tried using the xpath thing:
response_body.should have_xpath("//a[#href=\"#{link}\"]")
But then if I check for a link to 'blah.com' then it won't match 'http://blah.com" - which kind of defeats the whole purpose of the test. Hence the reason I switched to regex.
So is there a simpler way to write the test which doesn't rely on complicated regular expressions?
Cheers.
EDIT:
After lots of hair-pulling... I did find a less messy way to find images on my page:
response_body.should include(image)
Where the image string is set to something like 'myimage.png' - of course, this will break if the actual text 'myimage.png' is on the page and not the image.
There must be a better way. I was considering Hpricot to see if I can parse the html and pull out the attribute I want to test, then test that with a regex but that all seems so... bloated.
Something like this should work:
response_body.should have_css("a[href*='#{link}']")
See this for details:
http://www.w3.org/TR/css3-selectors/#attribute-substrings
EDIT:
Looks like the equivalent method for webrat is have_selector, so:
response_body.should have_selector("a[href*='#{link}']")
Then /^I should see the image "(.+)"$/ do |image|
response_body.should have_selector("img[src*='#{image}']")
end
Then /^I should see a link that contains "(.+)"$/ do |link|
response_body.should have_selector("a[href*='#{link}']")
end
Thanks AlistairH - your advice worked! :)
I still don't undestand why it's searching html with a css selector syntax but maybe that was just a design choice they guy who wrote it took because it looked easier than regex...? I don't know.

Resources