Hi people from StackOverflow,
I'm taking over someone's work, and my predecessor created a testset using Cucumber&Capybara&Selenium.
I'm familiar with the lot, but I've got a question concerning his way of finding text on a page.
His implementation:
expect(page).to have_content(text)
My implementation:
page.has_content?(text)
What I've noticed is that the first implementation often fails because the automation is 'too quick' for the website to load its page. The latter seems a more robust implementation, perhaps because of its simplicity?
Can someone tell me if there's a right or a wrong, or whether these two are fundamentally different. Because I've been trying to search the web but have not really found a solid conclusion..
Thanks in advance!
have_content raises an exception when it's expectation fails and should be used much more often in most test suites than has_content?. has_content? is basically just a wrapper around have_content that catches the exception and returns true or false, and is for use with conditionals
if page.has_content?(...)
# click something
else
# click something else
end
Your predecessor is using Capybara correctly since if you are testing to make sure a page has specific content you should be using have_content. has_content? will never fail the test (just silently return false and continue on). If your have_content assertions are failing because the site is too slow you probably need to increase Capybara.default_max_wait_time (or figure out why page load times are so long)
Ummm... I think that there is one more thing.
expect(page).to_have_content(text) is Rspec method while page.has_content?(text) is Minitest method. It is just depend what type of testing you use in your project. I guess.
Related
I am just thinking about command typeAndWait in Selenium, because I cant figure out any real purpose of it.
In what situation you type in some input and then the page immedeately starts reloading? I can imagine AJAX, but in this case the page doesn't reload - which is the reason, you have to use waitForXY commands instead of xyAndWait when testing AJAX...
But it was a long day today, maybe I am just dull now and the answer is quite obvious...
The google search while you type is the only situation I can think of where that would happen, except your right that the page wouldn't actually load, but there are some weird cases out there that I'm sure I haven't thought of.
I have some tests in Capybara.
Specifically I have two 'describe' methods.
These two test sometimes run fine, but sometimes they fail and I don't understand why as I don't change them.
This makes my testing environment completely unreliable.
Does somebody suggest what can be the reason?
I mean, I think that sometimes some queries like expect.to have_css() run before that the page is completely loaded. Is that possible?
Luca
What's your timeout set to? You can override it with.
using_wait_time(30) do
expect(page).to have_css('selector')
end
How do I resolve ambiguity in Capybara? For some reason I need links with the same values in a page but I can't create a test since I get the error
Failure/Error: click_link("#tag1")
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching link "#tag1"
The reason why I can't avoid this is because of the design. I'm trying to recreate the twitter page with tweets/tags on the right and the tags on the left of the page. Therefore it will be inevitable that identical links page shows up on the same page.
My solution is
first(:link, link).click
instead of
click_link(link)
Such behavior of Capybara is intentional and I believe it shouldn't be fixed as suggested in most of other answers.
Versions of Capybara before 2.0 returned the first element instead of raising exception but later maintainers of Capybara decided that it's a bad idea and it's better to raise it. It was decided that in many situations returning first element leads to returning not the element that the developer wanted to be returned.
The most upvoted answer here recommend to use first or all instead of find but:
all and first don't wait till element with such locator will appear on the page though find does wait
all(...).first and first won't protect you from situation that in future another element with such locator may appear on the page and as the result you may find incorrect element
So it's adviced to choose another, less ambiguous locator: for example select element by id, class or other css/xpath locator so that only one element will match it.
As a note here are some locators that I usually consider useful when resolving ambiguity:
find('ul > li:first-child')
It's more useful than first('ul > li') as it will wait till first li will appear on the page.
click_link('Create Account', match: :first)
It's better than first(:link, 'Create Account').click as it will wait till at least one Create Account link will appear on the page. However I believe it's better to choose unique locator that doesn't appear on the page twice.
fill_in('Password', with: 'secret', exact: true)
exact: true tells Capybara to find only exact matches, i.e. not find "Password Confirmation"
The above solution works great but for those curious you can also use the following syntax.
click_link(link_name, match: :first)
You can find more information here:
http://taimoorchangaizpucitian.wordpress.com/2013/09/06/capybara-click-link-different-cases-and-solutions/
NEW ANSWER:
You can try something like
all('a').select {|elt| elt.text == "#tag1" }.first.click
There may be a way to do this which makes better use of the available Capybara syntax -- something along the lines of all("a[text='#tag1']").first.click but I can't think of the correct syntax off hand and I can't find the appropriate documentation. That said it's a bit of a strange situation to begin with, having two <a> tags with the same id, class, and text. Is there any chance they are children of different divs, since you could then do your find within the appropriate segment of the DOM. (It would help to see a bit of your HTML source).
OLD ANSWER: (where I thought '#tag1' meant the element had an id of "tag1")
Which of the links do you want to click on? If it's the first (or it doesn't matter), you can do
find('#tag1').click
Otherwise you can do
all('#tag1')[1].click
to click the second one.
You can ensure that you find the first one using match:
find('.selector', match: :first).click
But importantly, you probably do not want to do this, as it will lead to brittle tests that are ignoring the duplicate-output code smell, which in turn leads to false positives that keep working when they should have failed, because you removed one matching element but the test happily found the other one.
The better bet is to use within:
within('#sidebar') do
find('.selector).click
end
This ensures that you're finding the element you expect to find, while still leveraging the auto-wait and auto-retry capabilities of Capybara (which you lose if you use find('.selector').click), and it makes it much clearer what the intent is.
To add to the existing body of knowledge here:
For JS tests, Capybara has to keep two threads (one for RSpec, one for Rails) and a second process (the browser) in sync. It does this by waiting (up to the configured maximum wait time) in most matchers and node-finding methods.
Capybara also has methods that don't wait, primarily Node#all. Using them is like telling your specs that you'd like them to fail intermittently.
The accepted answer suggests page.first('selector'). This is undesirable, at least for JS specs, because Node#first uses Node#all.
That said, Node#first will wait if you configure Capybara like so:
# rails_helper.rb
Capybara.wait_on_first_by_default = true
This option was added in Capybara 2.5.0 and is false by default.
As Andrei mentioned, you should instead use
find('selector', match: :first)
or change your selector. Either will work well regardless of config or driver.
To further complicate things, in old versions of Capybara (or with a config option enabled), #find will happily ignore ambiguity and just return the first matching selector. This isn't great either, as it makes your specs less explicit, which I imagine is why no longer the default behavior. I'll leave out the specifics because they've been discussed above already.
More resources:
https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara
https://makandracards.com/makandra/20829-threads-and-processes-in-a-capybara-selenium-session
Due to this post, you can fix it via "match" option:
Capybara.configure do |config|
config.match = :prefer_exact
end
As considering all the above options, you can try this too
find("a", text: text, match: :prefer_exact).click
If you are using cucumber, you can follow this too
You can pass the text as a parameter from the scenario steps which can be generic step to reuse again
Something like When a user clicks on "text" link
And in step definition When(/^(?:user) clicks on "([^"]*)" (?:link)$/) do |text|
This way, you can reuse the same step by minimizing the lines of code and would be easy to write new cucumber scenarios
To avoid ambiguous error in cucumber.
Solution 1
first("#tag1").click
Solution 2
Cucumber features/filename.feature --guess
So I have a Rails 3.0 Engine (gem).
It provides a controller at app/controllers/advanced_controller.rb, and a corresonding helper at app/helpers/advanced_helper.rb. (And some views of course).
So far so good, the controller/helper/views are just automatically available in the application using the gem, great.
But I want to let the local application selective over-ride helper methods from AdvancedHelper in the engine (and ideally be able to call 'super'). That's a pretty reasonable thing to want to allow, right, a perfectly reasonable (and I'd think common) design?
Problem is, I can't seem to find any way to make it work. If the application defines it's own app/helpers/advanced_helper.rb (AdvancedHelper), then the one from the engine never gets loaded at all -- so that would work if you wanted to replace ALL the helper methods in there (without calling super), but not if you just want to over-ride one.
So that kind of makes sense actually, so I pick a different name. Let's call my local one ./app/helpers/local_advanced_helper.rb (LocalAdvancedHelper). This helper DOES get loaded, if I put a method in there that wasn't in the original engine's AdvancedHelper, it is available to views.
But if I put a method in there with the same name as one in the engine's AdvancedHelper... my local one NEVER gets called. It's like the AdvancedHelper (from engine) is earlier in the call chain than the LocalAdvancedHelper (from app). Indeed, if I turn on the debugger, and look at helpers.ancestors, that's exactly what's going on, they're in the reverse order I'd want in the ancestor chain. So AdvancedHelper (from engine) could theoretically call 'super' to call up to LocalAdvancedHelper (from app) -- but that of course wouldn't make a lot of sense to do, you'd never want to do that.
But what I would want to do... I can't do.
Anyone have any ideas, is there any way to provide this design, which seems perfectly reasonable to me, where an app can selectively over-ride a helper method from an Engine?
Anyone have any explanation of why it's working the way it is? I tried looking at actual Rails source code, but got lost pretty quick, the code around this stuff is awfully abstract split amongst a bunch of places.
This is pretty esoteric question, I'm pessimistic anyone will have any ideas, I hope you surprise me!
== Update
Okay, in order to understand what part of Rails code is being called where, I put a "def self.included ; debugger ; end" on each of my helpers, then in the debugger I can raise an exception to see a stack trace.
That still isnt' really helping me get to the bottom of it, the Rails code jumps all over the place and is pretty confusing.
But it's clear that a helper with the 'standard' name (ie WidgetHelper for WidgetController) is called by different rails code, to include in the 'master' view helper module for a given controller, than other helpers are. I'm wondering if I give the helper a different name, then manually include it in my controller with ("helper OtherNamedAdvancedHelper"), if that will change the load order.
We can use Module#class_eval to override.
In main app,
MountedEngineHelper.class_eval do
def advanced_helper
...
end
end
In this way other methods defined in engine helper are still available.
Thanks for your elaboration. I think this really is a problem. And it is still present in Rails 3.2.3, so I filed an issue.
The least-smelling workaround I came up with is to do a "half alias method chain":
module MountedEngineHelper
def advanced_helper
...
end
end
module MyHelper
def advanced_helper_with_extra_behavior
advanced_helper
extra_behavior
end
end
The obvious drawback is that you have to change your templates so that your helper is called. At least, you make the existence of extra behavior explicit there.
These release notes from Rails4 seem enticingly related to this problem, and potentially note it's been fixed:
http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#helpers-loading-order
Brian Kernighan was asked this question in a recent interview. I'll quote his reply:
Brian: I'm torn on this. Error-handling code tends to be bulky and very uninteresting and uninstructive, so it often gets in the way of learning and understanding the basic language constructs. At the same time, it's important to remind programmers that errors do happen and that their code has to be able to cope with errors.
My personal preference is to pretty much ignore error handling in the earlier parts of a tutorial, other than to mention that errors can happen, and similarly to ignore errors in most examples in reference manuals unless the point of some section is errors. But this can reinforce the unconscious belief that it's safe to ignore errors, which is always a bad idea.
I often leave off error handling in code examples here and on my own blog, and I've noticed that this is the general trend on Stack Overflow. Are we reinforcing bad habits? Should we spend more time polishing examples with error handling, or does it just get in the way of illustrating the point?
I think it might be an improvement if when posting example code we at least put comments in that say you should put error handling code in at certain spots. This might at least help somebody using that code to remember that they need to have error handling. This will keep the extra code for error handling out but will still reinforce the idea that there needs to be error handling code.
Any provided example code will be copy-pasted into production code at least once, so be at your best when writing it.
Beyond the question of cluttering the code when you're demonstrating a coding point, I think the question becomes, how do you choose to handle the error in your example code?
That is to say, what do you do ? What's fatal for one application is non-fatal for another. e.g. if I can't retrieve some info from a webserver (be it a 404 error or a non-responsive server) that may be fatal if you can't do anything without that data. But if that data is supplementary to what you're doing, then perhaps you can live without it.
So the above may point to simply logging the error. That's better than ignoring the error completely. But I think often the difficulty is in knowing how/when (and when not) to recover from an error. Perhaps that's a whole new tutorial in itself.
Examples should be illustrative. They should always show the point being made clearly with as little distraction as possible. Here's a meta-example:
Say we want to read a number from a file, add 3, and print it to the console. We'll need to demonstrate a few things.
infile = file("example.txt")
content = infile.read()
infile.close()
num = int(content)
print (3 + num)
wordy, but correct, except there are a few things that could go wrong. First, what if the file didn't exist? What if it does exist but doesn't contain a number?
So we show how the errors would be handled.
try:
infile = file("example.txt")
content = infile.read()
infile.close()
num = int(content)
print (3 + num)
except ValueError:
print "Oops, the file didn't have a number."
except IOError:
print "Oops, couldn't open the file for some reason."
After a few iterations of showing how to handle the errors raised by, in this case, file handling and parsing. Of course we'd like to show a more pythonic way of expressing the try clause. Now we drop the error handling, cause that's not what we're demonstrating.
First lets eliminate the unneeded extra variables.
infile = file("example.txt")
print (3 + int(infile.read()))
infile.close()
Since we're not writing to it, nor is it an expensive resource on a long-running process, it's actually safe to leave it open. It will closewhen the program terminates.
print ( 3 + int(file("example.txt").read()))
However, some might argue that's a bad habit and there's a nicer way to handle that issue. We can use a context to make it a little clearer. of course we would explain that a file will close automatically at the end of a with block.
with file("example.txt") as infile:
print (3 + int(infile.read()))
And then, now that we've expressed everything we wanted to, we show a complete example at the very end of the section. Also, we'll add some documentation.
# Open a file "example.txt", read a number out of it, add 3 to it and print
# it to the console.
try:
with file("example.txt") as infile:
print (3 + int(infile.read()))
except ValueError: # in case int() can't understand what's in the file
print "Oops, the file didn't have a number."
except IOError: # in case the file didn't exist.
print "Oops, couldn't open the file for some reason."
This is actually the way I usually see guides expressed, and it works very well. I usually get frustrated when any part is missing.
I think the solution is somewhere in the middle. If you are defining a function to find element 'x' in list 'y', you do something like this:
function a(x,y)
{
assert(isvalid(x))
assert(isvalid(y))
logic()
}
There's no need to be explicit about what makes an input valid, just that the reader should know that the logic assumes valid inputs.
Not often I disagree with BWK, but I think beginner examples especially should show error handling code, as this is something that beginners have great difficulty with. More experienced programmers can take the error handling as read.
One idea I had would be to include a line like the following in your example code somewhere:
DONT_FORGET_TO_ADD_ERROR_CHECKING(); // You have been warned!
All this does is prevent the code compiling "off the bat" for anyone who just blindly copies and pastes it (since obviously DONT_FORGET_TO_ADD_ERROR_CHECKING() is not defined anywhere). But it's also a hassle, and might be deemed rude.
I would say that it depends on the context. In a blog entry or text book, I would focus on the code to perform or demonstrate the desired functionality. I would probably give the obligatory nod to error handling, perhaps, even put in a check but stub the code with an ellipsis. In teaching, you can introduce a lot of confusion by including too much code that doesn't focus directly on the subject at hand. In SO, in particular, shorter (but complete) answers seem to be preferred so handling errors with "a wave of the hand" may be more appropriate in this context as well.
That said, if I made a code sample available for download, I would generally make it as complete as possible and include reasonable error handling. The idea here is that for learning the person can always go back to the tutorial/blog and use that to help understand the code as actually implemented.
In my personal experience, this is one of the issues that I have with how TDD is typically presented -- usually you only see the tests developed to check that the code succeeds in the main path of execution. I would like to see more TDD tutorials include developing tests for alternate (error) paths. This aspect of testing, I think, is the hardest to get a handle on since it requires you to think, not of what should happen, but of all the things that could go wrong.
Error handling is a paradigm by itself; it normally shouldn't be included in examples since it seriously corrupts the point that the author tries to come across with.
If the author wants to pass knowledge about error handling in a specific domain or language then I would prefer as a reader to have a different chapter that outlines all the dominant paradigms of error handling and how this affects the rest of the chapters.
I don't think error handling should be in the example if it obscures the logic. But some error handling is just the idiom of doing some things, and in theese case include it.
Also if pointing out that error handling needs to be added. For the love of deity also point out what errors needs to be handled.
This is the most frustrating part of reading some examples. If you don't know what you are doing (which we have to assume of the reader of the example...) you don't know what errors to look for either. Which turns the "add error handling" suggestion into "this example is useless".
One approach I've seen, notably in Advanced Programming in the UNIX Environment and UNIX Network Programming is to wrap calls with error checking code and then use the wrappers in the example code. For instance:
ssiz_t Recv(...)
{
ssize_t result;
result = recv(...);
/* error checking in full */
}
then, in calling code:
Recv(...);
That way you get to show error handling while allowing the flow of calling code to be clear and concise.
No, unless the purpose of the example is to demonstrate an aspect of exception handling. This is a pet peeve of mine -- many examples try to demonstrate best practices and end up obscuring and complicating the example. I see this all the time in code examples that start by defining a bunch of interfaces and inheritance chains that aren't necessary for the example. A prime example of over complicating was a hands-on lab I did at TechEd last year. The lab was on Linq, but the sample code I was directed to write created a multi-tier application for no purpose.
Examples should start with the simplest possible code that demonstrates the point, then progress into real-world usage and best practices.
As an aside, when I've asked for code samples from job candidates almost all of them are careful to demonstrate their knowledge of exception handling:
public void DoSomethingCool()
{
try
{
// do something cool
}
catch (Exception ex)
{
throw ex;
}
}
I've received hundreds of lines of code with every method like this. I've started to award bonus points for those that use throw; instead of throw ex;
Sample code need not include error handling but it should otherwise demonstrate proper secure coding techniques. Many web code snippets violate the OWASP Top ten.