How to Write RSpec Validation Tests Part 1 of 2
Now that we have our user model ready, we are going to create some tests for it in this lesson. Validations are helpful while learning about TDD/BDD practices since they're easy to understand and can be tested independently from other code.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Now that we have our user model ready, we are going to create some tests for it in this lesson. Validations are helpful while learning about TDD/BDD practices since they're easy to understand and can be tested independently from other code.

If you go to the spec folder, you can see that it has created a subfolder called 'modelsand a file inside it calleduser_spec.rb`. This is because we had installed RSpec before creating our model.

If you open this file, it'll look like this:

large

Let's change this file a little now by deleting the pending line and adding some custom code instead.

If we are going to use just Rspec, like in this case, start with a before block. As the name suggests, this block of code will get executed before each test is run.

before(:each) do 
  @user = User.create! (name: "test name", email: "email@yahoo.com", password: "asdfasdf")
end

In this block, we are creating an instance of the User model and passing values to it. If you're unsure of what needs to be passed, take a look at your schema file.
Next, we are going to write our first test inside another describe block.

describe "creation" do
  it "should have one item created after being created" do
    expect(User.all.count).to eq (1)
  end
end

large

To test, let's open the terminal and run the tests:

bundle exec rspec

This worked as the result shows there is one example and 0 failures.

large

Next, we are going to test validations with another describe block. Let's create some tests that'll fail to give an idea of what that looks like. If you open the User model, you can see there are no validations in place. This means, we can allow a user to create a record with empty values, and the application will still work. Since we don't want users to do that obviously because it makes no sense to have email and passwords empty, we are going to have a "validations" block.

describe "validations" do
  it "should not let a user be created without an email address" do
    @user.email = nil
    expect (@user).to_not be_valid
  end
end

In this code, we are setting the user's email to be nil, and then calling one of RSpec method called be_valid, to see how a failed test looks like. Here, we are using a to_not because we don't want it to be valid. On the other hand, if you want it to be valid, then like the previous case, you'd just use to.

To check, go to the terminal and run the tests:

bundle exec rspec

large

So, we have one test that passed and another that failed. The green dot signifies a passed test, while the F means a test failed. if you look closely, the test that failed is the second one where we're checking if the email is not empty. Since we set the value as nil in the previous line, this test failed and this exactly what we want!

The idea behind this test is to ensure our code is working fine, so let's go back to the code and make changes to pass the test.

The easiest way to get this test to pass is by adding validation code to our model. So, let's go to our model file and type this code:

validates_presence_of :email

large

Let's run the test again and see what happens.

large

Both these tests have passed as is evident from the two green dots.

Let's just do another one for more practice.

it "should not let a user be created without a password" do
  @user.password = nil
  expect (@user). to_not be_valid
end

large

The last test will fail again. Go to user.rb and add the validation code for password too, like this:

validates_presence_of :email

Run the tests now, and everything should work fine.

Next, put both the email and password in the same line, and run the test. It should pass this time too.

large

So, everything worked fine. If you see, we used tests to drive the code we want to write.