for" I have a User model with this validation validates :name, :lastname, :format => {:with => /^[a-zA-Z]+$/, ...">

Testing "checks ... format => for"

I have a User model with this validation

validates :name, :lastname, :format => {:with => /^[a-zA-Z]+$/, :message => 'Only letters and spaces allowed.'}

      

I'm not sure how to properly test it.

I have implemented a function that returns a random 10 character string from the a-zA-z character array.

def get_random_name
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split('').shuffle[0..10].join

      

end end

and then I get a new name for each run of my specs.

I dont want to check that it is using some regexp because then I would be testing the implementation, not the behavior, and I also dont want to check only one hard drive.

My questions are: should I do this? Is it really necessary? Is it better or useless? Do you know the best way to check such checks?

EDIT: Another question, how about generating incorrect random names? is there a way to generate random names that include at least one char out of range? I can't hardcode an array of all invalid values ​​to randomize it as it would be big big

+3


source to share


3 answers


Random data testing is a common Fuzzing testing method . I would look at using FuzzBert generators to generate true random binary data for testing.

Here's an example of some great random data that you wouldn't want to receive for your checks.

irb> require 'fuzzbert'
       => true
irb> test_string = FuzzBert::Generators.random_fixlen(10)[]
       => "S\x1EU1\x11HVY\x0E\xD0"
irb> puts test_string
     S▲U1◄HVY♫ 
       => nil

      

Accidentally good

Since it converts random binary bits to strings, you will get some really funky results to test. This is a good thing! It not only checks the use of known characters like?, But also all kinds of combinations of valid and invalid characters.

Random is sometimes valid



It is possible that you will receive reliable data from time to time, although very unlikely. In addition, the likelihood of getting reliable data decreases longer than the random string you create.

The first attempt at solving this problem might be to just add an invalid character to each output, but I wouldn't suggest it. For example, if you always add "!", Then your test equivalent will do it to make sure there is no "!" in it, not in true testing of the full regexp capabilities.

I would suggest testing your random strings against this same regex, if it passes it, it will generate another string to test.

Finally, you can simply ignore the rare chance that the random data is valid. If every time that particular rspec fails, look at which line it fails on, if it was a valid string, then just rebooted.

Check all possibilities

You can never test all invalid strings (if you have a short maximum length), but with Fuzz Testing you can test strings that contain a large number of valid and invalid characters.

+1


source


To check for valid and invalid formats (I think regex is great for defining a format to check), how to determine what you think is valid and invalid names are found in some helper helper methods that you might refine over time if necessary. For example:

specs / support / utilities.rb

def valid_names
  %w[Homer bart LISA]
end

def invalid_names
  %w[BuRn$ 5M1+h3Rs♡]
end

      

Then you can write tests for :name

(and :lastname

) using RSpec, shoulda-matchers and Factory Girl which looks something like this:



specs / models / user_spec.rb

describe User do

  let(:user) { FactoryGirl.create(:user) }

  # ...

  describe "validations" do
    context "for name, lastname" do
      context "when format is invalid" do
        invalid_names.each do |invalid_name|
          it { should_not allow_value(invalid_name).for(:name) }
          it { should_not allow_value(invalid_name).for(:lastname) }
        end
      end

      context "when format is valid" do
        valid_names.each do |valid_name|
          it { should allow_value(valid_name).for(:name) }
          it { should allow_value(valid_name).for(:lastname) }
        end
      end
      # ...
    end
    # ...
  end
  # ...
end

      

If you ever intend to internationalize your application in the future, just remember that not all world names follow this format.

+4


source


Checkout an open source project. https://github.com/thoughtbot/shoulda-matchers

Edit: Sorry, just noticed that Paul Fioravanti

Shoulda mentioned. However, you don't need to use FactoryGirl to instantiate the model. Use is create

not required for validation checks.

You can create unit tests directly on the model:


describe User, 'Validations' do
  it { should allow_value("Name").for(:name) }
  it { should_not allow_value("Inv4lid_").for(:name) }
end

      

+2


source







All Articles