ActiveTest: Rails-style testing

Posted by Mathew Abonyi Tue, 15 Aug 2006 04:49:00 GMT

In pursuit of my previous post, I’ve followed up with an alpha mock-up of my ideas on how Rails testing can be made less tedious. Here’s the first version readme:

Cautionary Word

USE AT YOUR OWN PERIL.
ACTIVETEST IS NOT FINISHED.
IT HAS BUGS.
IT IS MISSING A LOT OF FEATURES.

Balls to Caution. How do I install?

  $ ./script/plugin source http://mabs29.googlecode.com/svn/trunk/plugins
  $ ./script/plugin install active_test

Foreword

You will see a lot of similarities between ActiveTest and its paronymic relative, ActiveRecord. I think it best to explain here. Other implementations which are attempting, with various success, to extend the functionality of Test::Unit and make it more Rails friendly have their own unique ways of setting up and developing. The price of their uniqueness is that they move away from the traditional thinking of a Rails developer. They introduce more complications of design and elements to be aware of, meaning more time to understand how something can be done. I do not want to think about the nuances of a test suite and model. The closer they are to each other in design and usage, the easier it is to test them rapidly.

So, without being overly creative, but instead using the conventions of Rails development in the development of Rails itself, I think, basically, ripping off ActiveRecord’s design (which is a perfectly good one for this purpose) is not such a bad idea. It eases the pain of learning how to use ActiveTest and it brings the mentality of Rails closer to tests. This is the whole point of ActiveTest: Rails-like testing.

Description

ActiveTest is an attempt – yet another – at making Test::Unit fit into the mould of Rails, a la ActiveRecord and ActionController. It uses a Base class from which are extended a number of Subjects, each subject including a specific set of Asserts. Each Asserts module can extend the instance methods of a test suite, such as ‘assert_is_a_hippo’, as well as the class methods. It is the class method idea which allows you to create ActiveRecord/ActionController style macros.

Read on for more specifics.

Subjects

Subjects are the types of tests you will run, like Controller, Model, Helper, View, Stress and Integration. Virgin Subjects can be created by extending the ActiveTest::Subject class itself, exactly how one creates new models inheriting from ActiveRecord::Base. You can, if you wish to have a completely blank slate, inherit directly from ActiveTest::Base too.

The best way to think of subjects is that they are pre-made ActiveRecord models. Everyone has a controller, view, helper, or record, so we can make certain assumptions which ActiveRecord cannot. We are not differing from the ActiveRecord metaphors. We are just filling in some blanks for convenience. If you don’t like the convenience, just extend ActiveTest::Base. You’ll get all the fancy stuff of Test::Unit::TestCase, no less and certainly no more.

You can create custom subjects like so:

  class ActiveTest::FlyingRhino < ActiveTest::Subject
  end

Alpha Note: At present, there is no advantage to doing this.

Assertions

ActiveTest allows you to create ‘assertion packages’. Think ‘Acts As …’. If you want a new assertion suite for a particular Subject, all you need to do is create a plugin with this init.rb:

  ActiveTest::PickASubject.class_eval do
    include ActiveTest::Asserts::YourAssertions
  end

And in your plugin/lib:

  module ActiveTest
    module Asserts
      module YourAssertion

        def self.included(base)
          base.extend(ClassMethods)
        end

        module ClassMethods
        end

        def instance_method
        end
      end
    end
  end

That all looks very familiar, doesn’t it?

Examples

Currently, there’s just a Controller subject. An active test would (will) look like this:

  class SessionControllerTest < ActiveTest::Controller

    setup_controller :login_as => :quentin

    test_require_login_for :new, :create, :edit, :update

    test_require_permission_for :destroy, :method => :delete

    test_index_should_index_items

    test_show_should_show_item :id => 1

    test_edit_should_edit_item :id => 1

    test_update_should_update_item :id => 1

    test_destroy_should_destroy_item :id => 1

    test_new_should_new_item

    test_create_should_create_item

    def test_special_case_for_this_controller
    end

    protected
    # overwrite the default create_item, which expects parameters from dynamic class methods
    def create_item(action = nil, parameters = {})
      super(:create, :session => { :login => 'anotherguy' })
    end
  end

The class methods create a bunch of tests for you which do precisely what it says: requires login. By default, the Controller subject has the Authentication and Authorisation modules, which assume you are using some variant of Acts As Authenticated.

Posted in  | 5 comments | no trackbacks

Simple Access Control: bug fix & README update

Posted by Mathew Abonyi Mon, 14 Aug 2006 15:59:33 GMT

It was brought to my attention there was a little bug in the way unauthenticated users were handled if login_required wasn’t called first. This bug is fixed. I also took the opportunity to spruce up the documentation and make it self-sufficient from acl_system2. If anything is missing, let me know.

In the following revisions, I’ll be adding full-blown tests using my Plugin Test Kit. I expect them to be done within a week or two; Simple Scope will be released with tests first.

Posted in  | no comments | no trackbacks

Older posts: 1 2 3 4