As promised, I am starting a series of articles on RSpec.
In this article, I will try to explain in detail how to write tests for models in Ruby on Rails. If you are already familiar with rspec_on_rails, correct and supplement me if something is wrong. Remember that I study Rspec with you and I can be wrong somewhere.
Training
We assume that after reading my
previous article, you have already created a test project, configured it and created a schema for it in the database, as well as installed gem rspec. If not, quickly do:
[sudo] gem install rspec
rails ./test -d mysql
nano ./test/config/database.yml
rake db: create
Now, let's move to the directory of our project and execute the command:
./script/generate rspec
Now at the root of our project, we have a spec directory. You can create a direct test for our model, run:
./script/generate rspec_model Post
The rspec will automatically create the model itself, fixtures and migrates for it, as well as a test file with the following contents:
require File.dirname (__ FILE__) + '/../spec_helper'
describe Post do
before (: each) do
@post = Post.new
end
it "should be valid" do
@ post.should be_valid
end
end
Simple test sample
Well, you can try to get rid of all the tests for the first time, run:
rake spec: models
Oh oh oh, not passed. Rspec says:
You have 1 pending migrations:
20090302064129 CreatePosts
Run "rake db: migrate" to update your database then try again.
Well, let's do what we are asked for, but before that, let's correct the migration file a bit, to such a state:
class CreatePosts <ActiveRecord :: Migration
def self.up
create_table: posts do | t |
t.string: name,: limit => 50,: null => false
t.text: content
t.timestamps
end
end
def self.down
drop_table: posts
end
end
Now let's migrate and run the test again:
rake db: migrate
rake spec: models
and voila, our test was successfully passed (if you do not, write in the comments, I will try to help):
.
Finished in 0.040821 seconds
')
1 example, 0 failures
A dot at the beginning means that the test is passed successfully, the letter F means that the test is not passed. Let us now complicate our example a little. Let's change the code a bit:
it "should require name" do
@ post.name = nil
@ post.should_not be_valid
@ post.errors.on (: name) .should_not be_nil
end
After execution, we get:
F
one)
'Post "should require name"' FAILED
expected valid? to return false, got true
./spec/models/post_spec.rb:10:
Finished in 0.045391 seconds
1 examples, 1 failure
rake aborted!
Ok, as long as everything is correct, you need to add validation to our model:
validates_presence_of: name
validates_length_of: name,: within => 3..50
We run again, now everything is OK. The test was successful.
Using Fixtures
Let's edit the file ~ / spec / fixtures / post.yml:
one:
id: 1
name: "this is ferst post"
content: "tru la la, tra la la"
two:
id: 2
name: "this is second post"
content: "tran tan tan, tra ta ta"
Now we change our test, to this type:
require File.dirname (__ FILE__) + '/../spec_helper'
describe Post do
fixtures: posts
before (: each) do
@post = Post.new
end
it "should require name" do
@ post.name = nil
@ post.should_not be_valid
@ post.errors.on (: name) .should_not be_nil
end
it "clears post" do
posts (: one) .destroy
lambda {posts (: one) .reload} .should raise_error (ActiveRecord :: RecordNotFound)
end
end
Thus, we loaded all fixtures (posts: posts) and work with them directly, calling them by the symbols (posts (: one)) specified in posts.yml
That's all for now, this should be enough to start writing your own tests for models.
In the following articles, I will discuss the creation of tests for Controllers and Views.