- Read Tutorial
- Watch Guide Video
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 called
user_spec.rb`. This is because we had installed RSpec before creating our model.
If you open this file, it'll look like this:
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
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.
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
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
Let's run the test again and see what happens.
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
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.
So, everything worked fine. If you see, we used tests to drive the code we want to write.