Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Testing In Rails: Unit Testing In Models

    • 1
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 450
    Comment on it

    Testing In Rails: Unit Testing In Models

    Hi friends,
    In my previous blog, Testing In Rails: Introduction and Creating Test Data, I had given you a brief introduction of rails test cases and why they are required. Also I guided you how we can create test data using factory girls or fixtures, which will be used in testing our application related methods. Now its time to see how we can write test cases.

    Unit Testing in Models:
    Rails is a proper MVC framework, where models represents the classes which are used for associating with the database. Thus most of the business logics, validations are performed in the models. It means they have the most highest priority for testing. In this blog we are using Unit test cases for testing the application. For testing the model properly, these things needs to be checked:

    a) whether a valid data is going into the database - validations
    b) all associations are working properly - associations
    c) all callbacks are working properly - callbacks
    d) all class methods are working properly
    e) all object methods are working properly

    Now to understand the functionality of test cases, lets first create a model Product with a title, description and price.

    	rails g model Product title:string description:text price:decimal
    	# => 
    	invoke  active_record	
    	create    db/migrate/20160624173932_create_products.rb
    	create    app/models/product.rb
    	invoke    test_unit
    	create      test/models/product_test.rb
    	create      test/fixtures/products.yml
    

    Now closely look the test/models/product_test.rb, which will look like:

    	require 'test_helper'
    
    	class ProductTest < ActiveSupport::TestCase
    	  # test "the truth" do
    	  #   assert true
    	  # end
    	end
    

    The code require 'test_helper' specifies that whatever thing is written inside the test_helper.rb is available in all the model test files. There are basically two ways of writing a test stubs, one sample which is already written above like specifying a test keyword with a string and creating a block of that, the other is create a method starting with test_  prefix:

    	# Using Block
    	test "validation method" do
    		# Your code Here
    	end
    
    	# Using Method
    	def test_validation_method 
    		# Your code Here
    	end
    

    After this the next section is how we can check, whether a method in a model is working fine. For that there must be some desired output for a set of input. For that kinds of validations there are assertions, which are used for the following tasks:

    a) expected output value = actual output value

    b) whether the object is nil?

    c) whether there is exception in a line of code.

    For these kinds of checking we have assertions. Assertions are actually used for evaluating the object or output for its desired expected result. So our test case can have more than one test cases depending upon the requirement. A method is said to pass the test only if none of the assertions gets failed. There are so many kinds of assertions available in ruby and rails. Full list of assertions can be found here:
    http://ruby-doc.org/stdlib-2.1.1/libdoc/test/unit/rdoc/Test/Unit/Assertions.html
    http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html
    Now lets test our first model but Before testing that lets add a validation in the Product model.

    	class Product < ActiveRecord::Base
    		validates :title, presence: true
    	end
    

    Now lets create test cases for this models validation using assertions

    	require 'test_helper'
    
    	class ProductTest < ActiveSupport::TestCase
    	  test "validations in product model" do
    	  	product = Product.new(title: '', description: 'Great Going', price: 1000)
    	  	assert_equal false, product.save, 'Product should not be created because title is not present'
    
    	  	product = Product.new(title: 'Product Title', description: 'Great Going', price: 1000)
    	  	assert_equal true, product.save, 'Product should be created'
    	  end
    	end
    

    After that finally run the test case using:

    	bin/rake test test/models/product_test.rb
    	#=>
    	Run options: --seed 271
    
    	# Running:
    
    	.
    
    	Finished in 0.275001s, 3.6363 runs/s, 7.2727 assertions/s.
    
    	1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
    

    Now looking into the output, we can see that we have run one test stub for which there were two assertions in which both passed so the failure is o and also the code doesn't contain any error so errors are also 0.
    The dot (.) below the running expressed the pass of the test stubs. It will show F in case of failure and E in case of errors. Also one more thing to be noticed of how we should write assertions, after the assert keyword we should write the expected value and after that there should be the actual value and a assertion message to differentiate the case, separated by commas. After that lets change a little bit code in the test file to check the failed case

    	require 'test_helper'
    
    	class ProductTest < ActiveSupport::TestCase
    	  test "validations in product model" do
    	  	product = Product.new(title: '', description: 'Great Going', price: 1000)
    	  	assert_equal false, product.save, 'Product should not be created because title is not present'
    
    	  	product = Product.new(title: 'Product Title', description: 'Great Going', price: 1000)
    	  	assert_equal true, product.save, 'Product should be created'
    	  end
    	end
    

    Now again run the test case:

    	bin/rake test test/models/product_test.rb
    	#=> Now it will give the output
    	Run options: --seed 40450
    
    	# Running:
    
    	F
    
    	Finished in 0.175340s, 5.7032 runs/s, 5.7032 assertions/s.
    
    	  1) Failure:
    	ProductTest#test_validations_in_product_model [/home/raghvendra/rails_apps/MyTestingApp/test/models/product_test.rb:6]:
    	Product should not be created because title is not present.
    	Expected: true
    	  Actual: false
    	1 runs, 1 assertions, 1 failures, 0 errors, 0 skips
    

    Thus we can see the assertion failed here showing the failed the assertion message. The test case should contain all possible types of input data sets and conditions to get rid of later bugs.

    Hope you liked this in next chapter I will talk about how we can write test cases for controllers.
    Testing In Rails: Functional Testing In Controllers

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: