rails captcha and testing using mock objects

To prevent bots from Signing up on our application, we added a captcha to our User model. We used the validates_captcha plugin available at http://svn.2750flesk.com/validates_captcha/trunk

The plugin, selects text from a String array for the captcha challenges, so, Sur, my co-programmer, hacked the plugin a little to add random text and improved images.

After adding the plugin we realized that all our tests which validate the User model had started failing. Programmatcially a test case or a bot are not much different, they are both scripts.

Mocks to the rescue.

Here is what I wrote in a file named add_captcha_to_active_record.rb under test/mocks/test directory.


require File.expand_path(File.dirname(__FILE__) + 
"/../../../vendor/plugins/validate_captcha/lib/add_captcha_to_active_record")

module AngryMidgetPluginsInc #:nodoc:

	module Validations #:nodoc:

		# module Captcha
		module Captcha #:nodoc:

			# module InstanceMethods
			module InstanceMethods #:nodoc:

			private

				def validate_captcha(options = {}) #:nodoc:
				  
				end

			end

		end#module Captcha

	end#module Validations

end#module AngryMidgetPluginsInc

What I have done by adding this file is, I have asked the test scripts to use the validates_captcha method in /test/mocks/test/add_captcha_to_active_record.rb instead of the validates_captcha method in plugins/validate_captcha/lib/add_captcha_to_active_record.rb

Well actually Rails does all the magic, I just need to give the same file name as the one I want to mock and then define the method that I want to override.

The original validates_captcha method checks that the text entered on the signup screen is the same as that stored on the server. If these do not match it adds a validation error to the base class, the User class in our case.
In the mock validates_captcha method we just do nothing. So a validation error will never be added to the base class.

And now our tests are running and passing again.

I also noted the presence of a directory /test/mocks/development/ … well that means I can even mock classes in the development environment.
One of our application, connects to Paypal to make a payment and then returns back. During development we had commented out this code so that we are not sent to paypal everytime. Now I know how I can avoid commenting or changing the code by using mock objects.
I will be working on that soon and blog about my experiences here.

Comments

  1. Agh, trying again.. My math isn’t that good it seems 😉

    That’s some nice mocking there. I’ll certainly start using mocks more in my own tests as well.

    FYI, I’ve moved the plugin to a new repository which will contain all my plugins (only two at the moment) here: http://svn.2750flesk.com/plugins/trunk/validates_captcha/

    The old repo will still work, but it won’t see any updates.. Also note that I’ve changed some names (that would break your mock) in the new version if you choose to use that..

  2. Hi,

    >so, Sur, my co-programmer, hacked the plugin a little to add random text >and improved images.

    Are you willing to share the enhacements you made with regards to the quality of the image?

    Thanks,
    Serge

  3. Hi, just wanted to let you (and others reading this) that I’ve updated the plugin so that it will now only give validation errors when not in test mode. This behaviour can be turned off in config/captcha.yml. There’s a few other updates too, such as a new type of challenge, the question challenge, which is the same as is used right here on this site.

Leave a Reply

Your email address will not be published. Required fields are marked *

+ 46 = fifty six