Assert amount of found nodes greater than N - capybara

With Capybara, one can easily assert the exact amount of nodes to be found:
page.should have_selector("fieldset.has_many_fields input[type=file]", :count => 2)
This ensures that there are exactly 2 such fields. But I want to check for "at least 2". Something like:
page.all("fieldset.has_many_fields input[type=file]").count should be_greater_than 2
This is an example, because it throws undefined method 'greater_than?' for 3:Fixnum'
Is there a matcher like this? Or another trick that allows me to check for "at least N nodes"?

Unfortunately the answer from RobertH on 17th Jan 2013 is now depreciated syntax.
For this precise scenario you would need to do:
page.all("fieldset.has_many_fields input[type=file]", :minimum => 2)

I think you just have a typo. Try:
expect(page.all("fieldset.has_many_fields input[type=file]").count).to be > 2

Related

Fuzzy `==`, or "almost_equal_to" function for strings?

I want to search for duplicates in my database, but it could be things like
"The smallest thing, and nothing more"
"The Smallest Things, And Nothing More"
"The smallest thing, and nothing more."
"The smallest thing, and nothing"
Is there an easy way to design a fuzzy == function that gives a weight of matching, instead of a binary true/false result?
Ruby ships with a library called did_you_mean it is used to make suggestions for code correction when you make a mistake like "abc".downcsae will ask you "Did you mean downcase?"
This library includes a module called DidYouMean::Levenshtein which has a method called distance. This distance is the number of transformations required for 2 strings to be equal
Example:
s = "The smallest thing, and nothing more"
x = "The Smallest Things, And Nothing More"
DidYouMean::Levenshtein.distance(s,x)
#=> 6
DidYouMean::Levenshtein.distance(s.downcase,x.downcase)
#=> 1
This may be useful in your case although you would need to determine the threshold.
Implementation is also available via the Gem::Text module which you could include in a class if needed e.g.
class MyClass
extend Gem::Text
def self.fuzzy_equal?(x:, y:, threshold:3)
levenshtein_distance(x,y) <= threshold
end
end
MyClass.fuzzy_equal?(x: s,y: x)
#=> false
MyClass.fuzzy_equal?(x: s.downcase,y: x.downcase)
#=> true
MyClass.fuzzy_equal?(x: s,y: x, threshold: 10)
#=> true

How to execute the another it block based on the value in ruby

a=0
describe "desc-1" do
it "it-1" do
puts "IT -1 "
a=1
end
if (a==1)
it "it-2" do
puts "IT-2"
end
end
end
the second it block must be executed,but now it is not executing can u please help thanks in advance
In RSpec your it blocks should be independent of each other and each test a specific piece of behavior. (Check out this similar question)
If you need to share a value across examples, assign the variable in a before(:all) block, but the order your tests are run should be random to ensure limited side effects (read this answer) so even this wouldn't really give you your answer.
If you want tests that test a larger system or series of actions look at this Rails Guide for functional testing or this great article on functional tests.
You have a scope issue. Local variable values assigned inside the it block will not be available outside of that context. In this case, if this is Rspec as it looks, your second example is not getting run because a evaluates to 0 in that context, but it will evaluate to 1 if you just allow the second block to run and test the expectation. This will work
a = 0
describe "a" do
it "is 0" do
expect(a).to eq 0
a = 1
end
it "is 1" do
expect(a).to eq 1
end
end
However now your second example is dependent on the first example running before it. A better idea would be to define the variable within the block testing the expectation, in which case it's a good idea to change it back afterward with an after block so you it resets to the default.
a = 0
describe "a" do
after { a = 0 }
it "is 0" do
expect(a).to eq 0
end
it "can be changed to 1" do
a = 1
expect(a).to eq 1
end
end

Inconsistent namespacing for maps?

I think namespacing of maps (at least in R19) is pretty weird. Consider the example:
14> M = #{a => 2, b => 3, c => 4}.
#{a => 2,b => 3,c => 4}
15> M.
#{a => 2,b => 3,c => 4}
16> map_size(M).
3
17> maps:map_size(M).
** exception error: undefined function maps:map_size/1
18> to_list(M).
** exception error: undefined shell command to_list/1
19> maps:to_list(M).
[{a,2},{b,3},{c,4}]
So, map_size is available in default namespace but not in maps:. However, to_list/1 exhibits opposite behavior. I haven't tried other functions, but even these results are surprising.
Am I missing some important undercurrent here or is this just an example of carelessness in language design?
I see some logic to this. The map_size/1 function is also available as maps:size/1, where both names contain the information you need: it takes a map, and returns the size. On the other hand, the name to_list doesn't say what you're converting from. There are several to_list functions in the default namespace already:
atom_to_list
binary_to_list
float_to_list
integer_to_list
pid_to_list
tuple_to_list
So the inconsistency here is that while "size" is available as map_size/1 and maps:size/1, the function map_to_list is missing. As Dogbert notes in the comments, this is presumably because map_size is available in guard tests, and thus deserves a special place. (I seem to remember that there are functions in other modules that are available in guard tests, but my memory might be deceiving me.)

Add verbosity to rspec's passing expectations

I'm using rspec rails to test my application, but I'm concerned that a few specs may actually be misleading. Can I get more information regarding passing specs in my console output to make sure the specs are testing behaviour I am happy with?
Here's how the output currently looks:
# spec.rb
require 'spec_helper'
context "With James Bonds' car" do
before do
#car = {make: "Aston Martin", color: "Silver", owner: "James", age: 3}
end
it "should not have an age of over 1 month" do
#car[:age].should_not == 1
end
end
Now, that expectation would pass, despite the car being over one month old:
$ rspec spec.rb
.
Finished in 0.12 seconds
1 examples, 0 failure, 0 pending
In order to make sure I've written good specs, how can I get ouput like this:
$ rspec spec.rb
.
Finished in 0.12 seconds
1 examples, 0 failure, 0 pending
Passing examples:
1) With James Bonds' car, it should not have an age of over 1 month
Pass: #car.age.should_not == 1
expected not: 1
got : 3
Rspec has different formatters for test output (and you can even write your own).
Try running your specs with the documentation format.
rspec -fd spec.rb
Which will have a more verbose output containing the text you put after your describe, context and it.
That doesn't necessarily assure you are testing the right thing (that's up to you when writing tests), but it does allow you to take stock of what tests are in your suite each time you run it.
Your logic in your spec is wrong - if you want to test if the age is less than 1, test that!
#car.age.should be < 1
The test suite for any decent sized app will span hundreds if not thousands of tests - you really don't want to be wading through the output of that for every single test run.
Your question is a bit confusing.
If the test failed, then you would get the output you were looking for.
If you want to check the actual value that is being tested, deliberately make the test fail e.g. change it to
#car.age.should == 1
Having said that, you seem to be checking the age with a method call, but you are setting car to be an Array of Hashes. In that sense, it will never be true because the method isn't there to be checked.

How to cap and round number in ruby

I would like to "cap" a number in Ruby (on Rails).
For instance, I have, as a result of a function, a float but I need an int.
I have very specific instructions, here are some examples:
If I get 1.5 I want 2 but if I get 2.0 I want 2 (and not 3)
Doing number.round(0) + 1 won't work.
I could write a function to do this but I am sure one already exists.
If, nevertheless, it does not exist, where should I create my cap function?
Try ceil:
1.5.ceil => 2
2.0.ceil => 2
How about number.ceil?
This returns the smallest Integer greater than or equal to number.
Be careful if you are using this with negative numbers, make sure it does what you expect:
1.5.ceil #=> 2
2.0.ceil #=> 2
(-1.5).ceil #=> -1
(-2.0).ceil #=> -2
.ceil is good, but remember, even smallest value in float will cause this:
a = 17.00000000000002
17.0
a.ceil
18
Use Numeric#ceil:
irb(main):001:0> 1.5.ceil
=> 2
irb(main):002:0> 2.0.ceil
=> 2
irb(main):003:0> 1.ceil
=> 1
float.ceil is what you want for positive numbers. Be sure to consider the behavior for negative numbers. That is, do you want -1.5 to "cap" to -1 or -2?

Resources