Reputation:
I just started to learn testing with minitest
but it sounds very confusing to me. What does this statement means?
test 'should not save simulations without name' do
post = Post.new
assert !post.save, 'Saved the simulations without a name'
end
class Post < ActiveRecord::Base
validates_presence_of :name , :type
belongs_to :user
before_create :check_validation
validates :type, :inclusion => { :in => 1..10, :message => 'The row must be between 1 and 10' }
private
def check_validation(data, type)
....
end
What would be the minitest
method for following conditions:
name
, type
parameter exist when creating a new object of Post
class. How can I do it post_test
class?test
method are checking the presence of name
in post
?check_Validation
through PostTest
class?posts
is not belong to users?I have already created post.yml
file and user.yml
file. How to proceed again. I tried to read ruby
official documentation but it is not very helpful.
Thanks in adnvance
my yml file
one:
name: 'test'
type: 3
user_id: 1
I tried :
test 'Post must have all parameters' do
assert assigns(:one).valid?
end
Upvotes: 5
Views: 800
Reputation: 1289
check if name, type parameter exist when creating a new object of Post class. How can I do it post_test class?
Is this test method are checking the presence of name in post?
Sort of. The assertion checks that saving the new Post instance fails, but there are several reasons for that result - e.g. missing :name
and :type
attributes, the before_create
filter that could hijack the save operation.
If you want to test each of these validations individually, you'll want to start with a known valid Post record and manipulate it to trigger each validation to fail. Usually, I'll have at least one minimally valid record set up in my fixture file - in this case, I'll call it :mvp
. Ex:
test 'MVP is valid' do
assert posts(:mvp).valid?, 'Minimum valid Post is invalid'
end
test 'should not save simulations without name' do
post = posts(:mvp)
post.name = nil
assert post.invalid?, 'Post is valid without a name'
end
...
For the most part, I find that testing simple validations (presence, simple numericality, etc.) clutters my tests and smells a little like testing the framework instead of my own application code, so I'll often skip them.
How can I test check_Validation through PostTest class?
check_validation
is marked as a private method, and in general, you don't want to directly test private methods. You can, however, verify that the conditions you set on newly created models match your expectations:
test 'newly created Post has settings XYZ' do
post = Post.new(...)
assert post.save, 'Post could not be saved'
# assertions to test #check_validations side effects here...
end
You don't include the body of your check_validation
method, so I don't know what you've got in mind here. With a name like that though, I'm inclined to believe you're trying to do some kind of validation that would be better left to a custom validation method defined using the validate
method. See the docs to see whether it applies in your case.
How to check throw error if posts is not belong to users?
I'd make this a validated condition on your Post class as:
class Post
belongs_to :user
validates :user, presence: true
end
Hope that helps somewhat. I've tried to answer your questions in a way that will let you get on with your work, but if you're interested in learning to be productive with Rails and Minitest, you're going to want to do a deeper study of the framework and how it's used with Rails.
Upvotes: 1
Reputation: 8984
This is a poorly written test, so I can see why you are confused. I assume that there is a companion test that attempts to show that the Post
can be saved when it has a name.
test 'should save simulations with name' do
post = Post.new name: 'simulator McSimulation'
assert post.save, 'Must save the simulations with a name'
end
test 'should not save simulations without name' do
post = Post.new
assert !post.save, 'Saved the simulations without a name'
end
What does this statement means?
That is a test method. In Minitest there are three main concepts: test class, test method, and assertion method.
A test class is a class that inherits from Minitest::Test
. It can inherit from it directly:
class PostTest < Minitest::Test
end
Or it can inherit from it indirectly
class ActiveSupport::TestCase < Minitest::Test
end
class PostTest < ActiveSupport::TestCase
end
All the testing behavior we use is available because we are creating test classes.
A test method is a method that begins with test_
, like this:
class PostTest < ActiveSupport::TestCase
def test_valid
# do the testing here
end
end
Rails adds some syntax sugar so that test methods can be created by passing a string and block to the test
method instead:
class PostTest < ActiveSupport::TestCase
test "is valid" do
# do the testing here
end
end
Your statement is using the rails-specific syntax. All test methods in a test class are run by Minitest.
The test class and test methods are how you structure the test, the assertion method is how you actually do the testing. The most basic way to indicate the code behaves as expected is to pass a truthy value to assert
, and an optional description to give guidance if the value is ever falsey. This is what your statement is doing. Post#save
returns a value, which you are negating, and then passing to assert
.
Minitest defines many more assertion methods.
I said this was a poorly written test. What do I mean by that? Well, first off, the assertion could fail for any number of reasons, so this test isn't as specific as it needs to be. Here are some changes I would make:
1) The refute
method is the invert of assert
, so I would use refute value
instead of assert !value
.
test 'should not save simulations without name' do
post = Post.new
refute post.save, 'Saved the simulations without a name'
end
2) Calling save
actually sends the data to the database, which is slow and should be avoided when possible. Use valid?
instead of save
.
test 'must not be valid without name' do
post = Post.new
refute post.valid?, 'Must be invalid without a name'
end
3) Make sure the reason the model isn't valid is because of the reason for the test, specifically that it needs a name. There are several reasons this model is invalid, and would not be saved. We need to be more specific here. The best way to specify this IMO is to check that the model's errors
object includes a reason for the missing name.
test 'must not be valid without name' do
post = Post.new
refute post.valid?, 'Must be invalid without a name'
assert post.errors[:name].any?, 'Must be invalid for missing name'
end
Of course we can make that even more specific by specifying a value returned by post.errors[:name]
. Let's use the assert_includes
assertion method that asserts that the collection contains a specific value:
test 'must not be valid without name' do
post = Post.new
refute post.valid?, 'Must be invalid without a name'
assert_includes post.errors[:name], "can't be blank",
'Must be invalid for missing name'
end
Hope that helps.
Upvotes: 3