Ruby way of writing this spec in "Rspec" - ruby

I was wondering if there is any Ruby way of writing the following views spec(without using Capybara/Cucumber/Webrat helpers. Should be just in rspec or rspec-rails):
expect(rendered).to include("<input class='toggle_m' name='result_configuration[information]' type='checkbox' value='1'>")
expect(rendered).to include("<textarea class=details' disabled='disabled' name=result_configuration[info][]'></textarea>")
Thing is, I need to see if the the checkbox is checked(means the value is "1", value is set to "0" when it is unchecked) then textarea should be disabled. Any idea?
Or How would you write this expectation in a more readable way? Suggestions are most welcome.
Thanks.

You could try a regex, but I think your method is good enough.
expect(rendered).should =~ /<input[^>]*name='result_configuration[information]'[^>]*value='1'[^>]*>/
expect(rendered).should =~ /<textarea[^>]*disabled='disabled'[^>]*name=result_configuration[info][][^>]*>
Limitations of this method are that if there are any checked checkboxes and any disabled textareas it will pass, to do anything more I would definitely require capybara or something to actually parse the html (regexes are not parsers)
EDIT: Added the name= part into both regexes as a response to the comment. Only advantage of this method is that it won't break if you change the class of the elements. Unfortunately I don't know any better solution other than external gems.

Writing such tests for the sake of testing and coverage will only make it difficult for someone inheriting the codebase. I have written such tests only to remove them later as changes to UI are more frequent and having such tests slows down developer. if i had to still write them in OO way i would design it on the lines of pageobjects (that's a gem) - wrapper class over dom and few generic helper functions. Also adding a new gem in test group using Gemfile/bundler would not affect production servers.

Related

How to Test/Debug Jekyll Plugins?

For a blog, I put together an inline tag that pulls header information from a specified webpage. It works, but I need to add caching, so that I'm not making redundant network calls.
I'd like a tighter debugging cycle than restarting the server and waiting for a rebuild, but running the plugin as Ruby code reports uninitialized constant Liquid (NameError). That makes sense, since it isn't required, and wouldn't run, since the plugin is just a class definition.
So, I tried creating some scaffolding to run the code, or what I thought would be scaffolding, anyway.
require 'liquid'
require_relative '../_plugins/header.rb'
ht = HeaderInlineTag.new
ht.initialize 'header', 'some path'
puts ht.render()
This produces...
_test/header.rb:4:in `<main>': private method `new' called for HeaderInlineTag:Class (NoMethodError)
Considering the possibility that initialize() might be run to create objects, I combined the first two lines of code, but that didn't work, either. Same error, different function name. The plugin doesn't mark anything as private, and declaring the methods public doesn't change anything.
What more is needed to test the plugin without carrying around the entire blog?
The solution was beyond my Ruby knowledge, but mostly straightforward, once I connected the pieces of information floating around.
First, this existing answer is about a specific issue dealing with Rails, but incidentally shows how to deal with private new methods: Call them through send, as in HeaderInlineTag.send :new.
Then, this indirect call to .new() now (of course) calls .initialize(), meaning that it needs the three parameters that are required by any plugin. Two parameters are for the testing itself, so they're easy. The third is a parse context. Documentation on writing Jekyll plugins is never clear on what the parse context actually is, since it gets sent automatically as part of the build process. However, some research and testing turns up Liquid::ParseContext as the culprit.
Finally, .render() also takes the ParseContext value.
Therefore, the the test scaffold should look something like this.
require 'liquid'
require_relative '../_plugins/header.rb'
context = Liquid::ParseContext.new
ht = HeaderInlineTag.send :new, 'header', 'some path...', context
puts ht.render context
I can call this from my blog's root folder with ruby _test/header.rb, and it prints the plugin's output. I can now update this script to pull the parameters from the command line or a CSV file, depending on the tests required.

Is there any benefit of defining radio buttons in a Page Object model (eg. SitePrism) rather than using Capybara directly?

I was using a cucumber/ruby/capybara/siteprism framework and implementing the test pages at present. I've reached a point where there are a lot of radio buttons (over 20) per page in several pages, and I was thinking if there's really any benefit in trying to map all those as static elements in my page object model?
Ie, thinking about it, it seems much more convenient to just use the text of the radio button in the step definition and call the capybara 'choose' method directly, something like the following, so that I don't need to do anything else for those 20+ radio buttons, it should all just work by changing the parameter we're passing in the feature:
cucumber feature:
When I select that "I am over 18"
capybara step:
When /^I select that "(.*)"$/ |option|
choose(option)
Whereas with a page object model like siteprism, I guess the implementation would need to define and maintain all those elements independently in a format similar to:
element :over_18_button, :radio_button, "I am over 18"
element :over_12_button, :radio_button, "I am over 12"
etc x50times
And for using it, one should create the page, call the element, which doesn't seem as straight forward to me?
siteprism step:
When /^I select that "(.*)"$/ |option|
case option
when 'I am over 18'
over_18_button.click
when 'I am over 12'
over_12_button.click
I guess one could create 'elements' or a 'section' with an array to all the buttons, but then, we'll have to put extra logic to parse them and click on the relevant one anyway somewhere in the code, whilst it would be all done neatly and without the need for any extra code or maintenance with the 'choose' method from capybara.
Am I right to assume that in this example using Capybara is a better option?
or if it'd be better to define 'ALL' web elements in the page object model, what would the benefit of that be? and could the page object code be done in a different way to take advantage of any possible benefit?
That complicated case statement is unnecessary.
When /^I select that I am over "(\d\d)"$/ |age|
#page_object.select_age(age)
I'm not familiar with site_prism. My watir_drops gem would let you define everything with the same pattern like this:
element(:age_button) { |age| browser.radio_button(text: "I am over #{age}")
with this method in the page object:
def select_age(age)
age_button(age).set
end
We could also get into a whole long discussion on using declarative instead of imperative steps. Also, best practice Page Object usage avoids directly calling defined elements. Call methods that accomplish the business logic and those methods do all the implementation including element definitions and actions on them.
Old question but adding important missing info
The way in which site_prism works allows you to define your selector using anything that can be queried in Capybara. So if you want to define your radio using the text, you can do that. Or any other locating strategy you want to use.
Obviously traditionally I would advise using css locators (
element :my_radio, text: 'foo'), because they're easiest to debug and re-use. Furthermore the OP advised he had 50+ of these. If they were identical, they could be abstracted out into a Helper Module or he could even meta-program them in using a loop and index (If they followed a simple index_naming_pattern)

How much rework do i have to do when moving from simple automation to Page Object Model framework using Cucumber and Selenium/Capybara?

My Goal is to create a Page Object Model Automation framework using Cucumber with capybara/selenium for mu client project. Currently my knowledge related to Page Object Model gem is very limited and at the same time i want to show some delivery by creating automation scripts using cucumber and capybara. So i am in the process of creating some feature files and subsequent step definitions.
So my question is, If i move to simple automation to POM framework, how much rework i have to do in terms of scripts and also if this approach is correct. Please guide me as i am pretty new to ruby automation.
Well this can be a very opinionated question, but I'll try to keep it simple:
If you already have well structured and modularised code (cucumber features and step defs), it won't take significant changes to move to POM. Its essentially a different structuring technique to keep your code organised and keep your changes minimal/confined.
Gems like siteprism can help you with creating well structured page objects, if you are open to learn an additional DSL (for siteprism) on top of cucumber / capybara. Or you can roll out your own without any additional libraries, though it would demand a thorough understanding of POM architecture and best practices.
Hope that helps.
I believe you will have a little work to migrate and meet increasingly the tool, the Framework POM only shows speed gain when you have some pages that already are mapped, it might take some time to be shown in reports, but I believe it has much to gain, organization, clarity and speed are some of the advantages of migration.
In my work I help other QAs learning and use POM in one day, a lot of guys use xpath to find objects, I just show how they can reuse that xpaths in a page object.
The second step I show to use method, not only elements, then they can reuse a lot of code and stop repeat steps, find where they break and use a simple method in siteprism page, example:
element :field_login , :xpath, "login"
element :field_password, :xpath, "password"
element :login_button, :xpath, "login_button"
def authenticate (username, password)
field_login.set username
field.password.set password
LoginPage.new if login_button.click
end
My next step is show to leave to use xpath and use css elements.
And after some sprints, they understand the beneficts of the framework, and it is default for all automation, include the DEVs can understand and help in tests now.
Warning this answer is somewhat controversial.
I'd say don't bother using the Page Object Model, its fundamentally flawed. The web is about resources and representations (REST) not about pages. BDD is about behaviour, not pages.
The danger with POM (particularly when you are not experienced) is that you write lots of scenarios to test what is on each page. When really what you should be doing is writing scenarios that confirm that some behaviour exists.

Is there a lightweight, all purpose validation library/DSL for Ruby?

I'm doing a lot of bulk data-validation on various kinds of data sources and I find myself writing such boilerplate code:
if summed_payments != row['Total']
raise "The sum of the payments, #{summed_payments} != #{row['Total']}"
end
I was wondering if there was a way to apply a DSL, like Minitest, but to use it for purposes that didn't involve application testing? For example, finding and logging errors during a bulk data import and validation script...it's a quick-and-dirty script that I don't want to have to write a test suite for, but that I want to do some various kinds of validation upon.
I think standalone ActiveModel should be good for this.
Watch this railscast for more information: http://railscasts.com/episodes/219-active-model
If you like you can check out http://rubygems.org/gems/validates_simple which is a gem for doing simple validation of hashes trying to mimic the interface of the active model validation methods.
I know this is a little old, but our Veto gem is likely what you're looking for: https://github.com/kodio/veto
Standalone validation of plain old ruby object, without dependencies.

Dynamically Generating ORM Classes

I'm working on a Sinatra-based project that uses the Datamapper ORM. I'd like to be able to define criteria for the DM validations in an external YAML file so that less-experienced users of the system can easily tweak the setup. I have this working pretty well as a proof-of-concept, but I suspect there could be a much easier or a least less processor-intensive way to approach this.
Right now, the script loads the YAML file and generates the DM classes with a series of eval statements (I know this already places me on thin ice). The problem is that this process has to happen with every request. My bright idea is to check the YAML for changes, regenerate the classes and export to static source if changes are detected, and include the static files if no changes are detected.
This is proving more difficult than I anticipated because exporting code blocks to strings for serialization isn't as trivial as I expected.
Is this ridiculous? Am I approaching this in an entirely wrong-headed way?
I'm new to Ruby and the world of ORMs, so please forgive my ignorance.
Thanks!
DM validations in an external YAML file so that less-experienced users of the system can easily tweak the setup
A DSL for a DSL. Not having seen your YAML I still wonder how much easier than the DM Validations it really can get?
require 'dm-validations'
class User
include DataMapper::Resource
property :name, String
# Manual validation
validates_length_of :name, :max => 42
# Auto-validation
property :bio, Text, :length => 100..500
end
Instead of going for YAML I would provide the less-experienced users with a couple of relevant validation examples and possibly also a short guideline based on the dm-validations documentation.
It does seem a little crazy to go and put everything in YAML, as that's only a shade easier than writing the validations in Ruby. What you could do is make a DSL in Ruby that makes defining validations much easier, then expose that to your users instead of the whole class.

Resources