How to know if you have a secure session in Watir

Sometimes you’re on a secure page, sometimes you’re not. How to know? There’s a very simple method you can write to find out, based on the browser’s current url. Here’s the method:


def is_session_secure?
  @browser.url =~ /^https/ ? true : false
end

It’s worth noting that the method highlights how much you can get done with very little code using ruby and watir. Here’s what it does: first, get the url out of the browser. Then, see if the url matches a simple regex. Since this operation is done in a ternary operation, a simple true/false will result. And, since ruby returns what the final line in a method resolves to, the true/false result of the match will be returned. Another nail in the coffin of big and bloated UI automation tools!

Here’s an example of the code in use…


require "rubygems"
require "firewatir"
require "test/unit"

include FireWatir

class GoogleSecurePageTests < Test::Unit::TestCase
  def setup
    @browser = Firefox.start("http://www.google.com")
  end

  def test_google_https
    assert(!is_session_secure?)
    @browser.link(:text, "Sign in").click
    assert(is_session_secure?)
  end

  def is_session_secure?
    @browser.url =~ /^https/ ? true : false
  end
end

How to know your ruby Test::Unit test result

If a test passes, you usually don’t want to know any more – nothing to see here, move along. But, if a test fails or errors, you become far more interested. But… how to know if a test failed or not? If you could tell, you could do useful things like taking screenshots, writing stack traces to a file, etc. So it’d be useful to know the result.

Using ruby’s Test::Unit, it’s easy. Since test cases inherit from Test::Unit::TestCase, and since Test::Unit::TestCase contains an instance variable called @test_passed – a boolean, you can access the result  of your test with no problem. So the following is possible:


class MyTests < Test::Unit::TestCase
  def setup
    #do nothing
  end
  def teardown
    if @test_passed then
      puts "Yay! The test passed!"
    else
      puts "Oh no! The test went bad!"
    end
  end
  def test_that_passes
    assert(true)
  end
  def test_that_fails
    assert(false)
  end
end

See the code in the teardown? It’s doing stuff based on the test result. I’m sure you can come up with a better use for this than printing silly strings…

How to print start time in Ruby Test::Unit test run

I want to be able to print a timestamp of the test execution start time. Test::Unit doesn’t seem to be able to do this out-of-the-box, so here’s a monkeypatch I’ve written to put that functionality into-the-box!


class Test::Unit::AutoRunner
  alias original_run run
  def run
    puts "---===[ Starting at #{Time.now} ]===---\n\n"
    original_run
  end
end

When you run, you’ll see:

---===[ Starting at Thu Aug 13 23:13:24 +0100 2009 ]===---
Loaded suite /Users/nat/dev/add_start_time_to_test_unit
Started
...
Finished in 0.000731 seconds.
3 tests, 3 assertions, 0 failures, 0 errors

Very useful if you are highly iterative in the way you write tests… Are those results on screen from something I ran 2 minutes ago or 30 minutes ago? Well, now you have an easy way to find out!

How to print test names when executing Ruby Test::Unit tests

When I run my test_all.rb from the command line, I get ‘.’ when a test passes, but I don’t know which test it was that passed. I only get the names of tests that fail or error. Quite sensible – for regression testing, this is all you need. But where audit trails are required, I need to be able to provide a list of all tests that were executed in a particular test run. Here’s how to do it (using tests in a NetBeans project as an example)…

Instead of running:

ruby -I test -I lib test/test_all.rb

…run:

ruby -I test -I lib test/test_all.rb -v

The ‘verbose’ argument does exactly what I need! Here’s the kind of output you get:

test_that_passes(RelevantTestCaseClass): .
test_that_fails(RelevantTestCaseClass): F
test_that_errors(RelevantTestCaseClass): E

You’ll still get all the errors listed at the end of the run as usual.

How to run individual Ruby Test::Unit tests

I have a whole load of Test::Unit::TestCase class files. Each one contains a whole load of test_* methods. If I want to run one or two individual test_ methods from a selection of  TestCase classes, how do I do it? Simple. Test::Unit has a feature that allows me to create TestSuites from TestCases just by specifying the name of the test when I create an instance of the relevant TestCase class.

I create a file to contain my custom TestSuite (‘sanity_tests.rb‘), and add a require for each TestCase that I contains a test_ method that I want to run as part of this custom TestSuite. I then create a new TestSuite giving it a name. Then, for each test_ method I want to add to my custom TestSuite, I create an instance of its containing TestCase class, passing in a string representation of the test_ method I want to execute. The initialization returns a TestSuite object which is appended to the custom TestSuite that I just created.

Once I’ve done this for every test_ method that I’m interested in, I execute my custom TestSuite and wait for the results! Here’s a code example. The comments should make it clear…


#relevant test::unit requires
require 'test/unit'
require 'test/unit/ui/console/testrunner'

#TestCase classes that contain the methods I want to execute
require 'One/test_one'
require 'Two/test_two'

#create a new empty TestSuite, giving it a name
my_tests = Test::Unit::TestSuite.new("My Special Tests")

#add the test method called 'test_one' defined
#in the TestOne TestCase class to the my_tests
#test suite defined above
my_tests << TestOne.new('test_one')

#add the test method called 'test_me' defined
#in the TestTwo TestCase class to the my_tests
#test suite defined above
my_tests << TestTwo.new('test_me')

#run the suite
Test::Unit::UI::Console::TestRunner.run(my_tests)

And the output is as expected:

Loaded suite My Special Tests
Started
..
Finished in 1.000935 seconds.
2 tests, 2 assertions, 0 failures, 0 errors

Running NetBeans ruby tests from the command line

As far as doing UI testing with watir/firewatir goes, NetBeans is a fantastic IDE. It’s lightweight, but powerful enough to do pretty much anything I need. The integration with Test::Unit is particularly good: I select a test file, I call “Run > Test File”, I wait, I see pretty green and red indicators for the tests. But what if I want to run the tests from the command line? The NetBeans project structure means that it isn’t a matter of simply running ruby all_my_tests.rb. I took a look at what NetBeans actually did when it runs the test files (using the magic of ps -ax), and I’ve managed to compress the whole thing into:

cd project_dir
ruby -I lib -I test test/all_my_tests.rb

That’s the mac/unix/linux syntax. The windows syntax is the same:

cd project_dir
ruby -I lib -I test test\all_my_tests.rb

How to count all Ruby Test::Unit tests

I’m using Ruby’s Test::Unit with Watir and Firewatir for a project I’m working on. Tests are divided up into test classes, each test class being in one file. I then have files that aggregate the test case classes using the magical AutoRunner functionality (ie: ‘require’ all the test case classes, and they’ll be automatically run). These ‘test suites’ are very useful when I want to run a whole load of tests, but sometimes I just want to know how many tests I have in total – I need to provide this statistic daily and don’t want to have to do the count manually.

After browsing through the Test::Unit code (I was hoping it would send me to sleep – it was 3am), I figured out how the test case aggregation function worked. Turns out I could use the same concept to do my count, if I could stop the tests from running when they get ‘require’d!

Here’s the contents of a class you can use that will search the directory it lives in for all files whose names match ‘all_test*.rb’; requires the relevant files, performs a count on each one, and displays the results including a total:


#stop the tests from being run
require "test/unit"
Test::Unit.run=(true)

#read in only my 'all_test*.rb' files, and
Dir.glob(File.join(File.dirname(__FILE__),'all_test*.rb')) do |f|
  require f
end

#populate an array with all classes that inherit from TestCase
testcases = []
ObjectSpace.each_object(Class) do |obj|
  testcases << obj if(obj < Test::Unit::TestCase)
end

#sort by name
testcases.sort! { |a,b| a.name <=> b.name }

#print results!
total_tests = 0
testcases.each do |testcase|
  puts "#{testcase.name}: #{testcase.suite.size}"
  total_tests += testcase.suite.size
end
puts "Total: #{total_tests}"

Add assert_false to Ruby’s Test::Unit

For the past few months, I’ve been using NUnit. A few days ago I started using ruby’s Test::Unit – the only thing I miss from nunit is Assert.IsFalse(). So here’s something that will do the job… add the following code somewhere early on in the sequence:


module Test::Unit::Assertions
  def assert_false(object, message="")
    assert_equal(false, object, message)
  end
end

Here’s some code you can stick in a file that will prove the above method works:


require "test/unit"

module Test::Unit::Assertions
  def assert_false(object, message="")
    assert_equal(false, object, message)
  end
end

puts Test::Unit::TestCase.method_defined?(:assert_false)

class MyTests < Test::Unit::TestCase
  def test_this_one_fails
    assert_false(false)
    assert_false(true)
  end
  def test_this_one_passes
    assert_false(false)
  end
  def test_this_one_passes_too
    assert(true)
  end
end

=========UPDATE=========

After emailing Nathaniel Talbott (the author of Test::Unit), it turns out that he’s no longer the maintainer. That job has passed on to Ryan Davis, and he’s writing a replacement for Test::Unit. So I guess assert_false will never make it in. If you want assert_false, use the monkeypatch above!