Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing invalid emails with Rspec

This comes from the Learn Rails by example book:

 describe "when email format is invalid" do
    it "should be invalid" do
      addresses = %w[user@foo,com user_at_foo.org example.user@foo.
                     foo@bar_baz.com foo@bar+baz.com]
      addresses.each do |invalid_address|
        @user.email = invalid_address
        @user.should_not be_valid
      end      
    end

I'm a beginner in Rspec. Previously, there was a code like this:

  describe "when email is not present" do
    before { @user.email = " " }
    it { should_not be_valid }
  end

So I was wondering why the author didn't write the code above like this:

 describe "when email format is invalid" do
    before do
      addresses = %w[user@foo,com user_at_foo.org example.user@foo.
                     foo@bar_baz.com foo@bar+baz.com]
      @user.email = invalid_address 
      addresses.each do |invalid_address|
        @user.email = invalid_address
      end 
    end

    it { should_not be_valid }          
 end

OK, maybe this code is wrong. But basically, I'm asking why the author didn't use before before it or put the address variable before it? (as he did in the previous example)

EDIT:

He also does something similar in an further example:

 describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.email = @user.email.upcase
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
like image 485
alexchenco Avatar asked Oct 27 '12 02:10

alexchenco


1 Answers

The answer lies in what the before block is actually doing. In these tests, it is being run fully before the it is being run.

So, the first block of code is run (and could be written) as:

@user.email = 'user@foo,com'
@user.should_not be_valid
@user.email = 'user_at_foo.org'
@user.should_not be_valid
@user.email = 'example.user@foo.'
@user.should_not be_valid
@user.email = 'foo@bar_baz.com'
@user.should_not be_valid
@user.email = 'foo@bar+baz.com'
@user.should_not be_valid

And the second block of code is run (and could be written) as:

@user.email = ' '
@user.should_not be_valid

But the third block would loop through the entire array before getting to the it, resulting in only:

@user.email = 'foo@bar+baz.com'
@user.should_not be_valid

In the final example, he is performing a series of operations against the same object, which are evaluated before the it, which only needs to run once to make sense.

Hope this helps, good luck!

like image 154
Brad Werth Avatar answered Oct 01 '22 19:10

Brad Werth