Clicking Links in UnitTests

Using click /change/i is a good way of testing you links/methods, since it will assure your views render the valid link and you do not have to repeat the link parameters as in get :edit, :id=>3

  1. get form_test_helper with
    script/plugin install http://form-test-helper.googlecode.com/svn/form_test_helper/
  2. patch vendor/plugins/form_test_helper/lib/form_test_helper.rb
    -  if self["onclick"] && self["onclick"] =~ /'_method'.*'value', '(\w+)'/
    -    $1.to_sym
    +  if self["onclick"] && self["onclick"] =~ /\.method = '(.*)'/
    +    $1.downcase.to_sym
  3. insert helper to test/test_helper.rb
      def click(text)
        select_link(text).click
      end
  4. click click click clickaround!
      def test_should_not_upload_from_ftp
        login_as :aaron
        assert_invalid_upload do
          `cp -f test/fixtures/videos/test.mov #{ftp_accounts(:aaron).dir}/wrong_name.flv`
    
          click /upload.*ftp/i
          assert_response :redirect
          assert flash[:alert]
        end
      end

Test Driven Javascript – Aftermath

Yesterday i realesed my first Test Driven Developed jQuery plugin!

For development i used newjs (which has some problems with IE6 atm, but they are sorted out), it comes with a simple unittesting framework and all the assertions and help one can want.

Results

1. Its hard to test, because JS is not designed for test

  • No way to handle alerts/confirms or most of the other user interaction.
  • No sleep method, since javascript has no threads, it is hard to wait for 100ms while a request is performed(luckily jsunit helps with wait)
  • Resetting the DOM is often not possible when you rely on 3rd party code, that just does not bothers with reverting its changes. Normal javascript is one way, executed once and works until the user leaves. The only solution is to split your tests into multiple units, one for every test that involves the 3rd party code. (do the TD community a favour and include a reset method in your next libary)

2. Development takes longer but is rewarded

  • Figuring out ways to test your code and ensuring everything gets resetted takes time and effort
  • Testing against multiple Browsers is where you get your time back! When hacking things to work in IE6 i fell in love with my testsuite πŸ™‚
  • Running tests in multiple browsers is automated by newjs (‘rake test’ will start 6 different browsers and run them over your unit tests)
  • You can keep changing the code without any thought about what this will do to this or that browser.

3. Build a prototype and see it work in every browser

  • Ensure that your approach works with all browsers you want to support
  • Look for workarounds early, so that you can build the right thing, the first time

my unittest source if you want to see it run, download the ‘test and demo packadge’

anything missing ? -> drop a comment πŸ˜‰

HTML_TEST because RailsTidy drives me crazy

The functionality of RailsTidy is great, but it can drive you crazy, all the senceless warnings, wich as far as i looked cannot be turned off. Aditionally it cannot validate all requests, only the last one (if you followed my previouse post).

html_test features:

  • validating ALL requests
  • validating with up to 3 different validators (ok.. 1 is enought for me)
  • killing senceless warnings
  • checking all URLs (returnes :success or :redirect?)

Grab here: ruby script/plugin install http://htmltest.googlecode.com/svn/trunk/html_test

And put this into your test_helper.rb:

#--------html_test plugin
#validate every request
ApplicationController.validate_all = true
ApplicationController.validators = [:tidy]

#ignore common warnings
Html::Test::Validator.tidy_ignore_list = [
  /<table> lacks "summary" attribute/,
  /trimming empty <fieldset>/,#erros_on missing -> empty fieldset
  /line 1.*Warning: inserting missing 'title' element/,#redirect html has no title....
  /Warning: replacing invalid character code 130/, #€ has a very bad character
]

#check urls
ApplicationController.check_urls = true
ApplicationController.check_redirects = true

If you always see an extra line like 0 tests, 0 assertions, 0 failures, 0 errors, go to vendor/plugins/html_test/lib/html_test.rb and move the first 3 reuire lines into the if block

Install RailsTidy Plugin by Script

I try to keep some script to do everything, just in case i get to lazy to do it again by hand, which is … always πŸ™‚

This will install RailsTidy from your Rails directory:
(Ubuntu 7.10) change the paths according to your system

sudo apt-get install tidy
sudo gem install tidy

wget http://www.cosinux.org/~dam/projects/rails-tidy/rails_tidy-0.2/tidy.patch
sudo patch /var/lib/gems/1.8/gems/tidy-1.1.2/lib/tidy/tidybuf.rb < tidy.patch
rm tidy.patch

#script/plugin/install fails with strange warnings and does not install anything...
cd vendor/plugins/
wget http://www.cosinux.org/~dam/projects/rails-tidy/rails_tidy-0.2.tar.bz2
tar -xf rails_tidy-0.2.tar.bz2
rm rails_tidy-0.2.tar.bz2
 
 
 

In case you see something like “tidybuf.rb:39: [BUG] Segmentation fault” downgrade to the last stable version:
apt-get install libtidy-0.99.0/20051018-1 (Ubuntu 8.0.4)

now, inside test_helper.rb you can put this:

class Test::Unit::TestCase
  def teardown
    assert_tidy if @request
  end
end

happy nagging πŸ™‚

PS:
If this is still not enought validating fun for you, you can go a step further with html_test (requires RailsTidy) a project that combines html validation with url checking(do all my links return :success or :redirect?)(Project).