Counting strings in a file: Ruby vs Windows Command shell

This is not the usual material that I put up, but I’d like to immortalize an event that demonstrated yet again the beauty of Ruby for basic file manipulation, especially in contrast to doing the same in a Windows command shell. Here goes:

“Nat, I need a script that displays a count of the number of instances of a string in a file. The output must be a number and nothing else.”
“No worries, that won’t take 2 seconds.”
“Stop right there – I don’t want any of your ruby nonsense – it must be a batch file.”
“Hmmm… Can the batch file call a ruby script?”
“No.”
“Err… ok… I’ll see what I can do.”

So off I went trawling google, stackoverflow, random blogs, and websites which can’t have seen hits since 1995. One hour, some frustration, and several cups of tea later, this is what I came up with:

findstr /C:"search string" "c:\my\file.txt" | find /C /V "nonsense"

And that, ladies and gentlemen, works! Let me explain what’s going on… The script uses 2 commands: findstr and find. findstr is used for finding strings in files, and find is also used for finding strings in files. It of course makes perfect sense to have two commands that do the same thing – the very definition of the word “intuitive”. In the above example, findstr returns lines from the file that contain the search string. These lines are piped to find which then displays the number of lines that don’t contain a particular string, in the above case: "nonsense". That will return a number. It’s the only way you can get find, findstr or a combination of the two to return a-number-and-only-a-number of the instances of a string in a file. I would love to see this improved – leave a comment if you know a better way to do it.

To demonstrate to myself why doing the above in DOS is crazy, I wrote the same line in ruby:

File.open("c:/my/file.txt").read.scan(/search string/).count

It doesn’t take much explanation: It opens a file, reads it, scans it for a search string and then returns the number of instances it found.

Now. Can we all start using the right tool for the right job please? I know it may involve a bit of learning, but that never hurt anyone. That is all.

IronRuby vs. Gherkin – a temporary fix

IronRuby doesn’t currently work with the latest versions of cucumber. This is a known bug and is a real pain. There is a work around, and it’s kinda rubbish: don’t use any versions of cucumber > 0.6.3. After that version, Gherkin became a .c extension – and IronRuby doesn’t like .c extensions.

Keith Burnell (the .Net Dev Dude) has blogged about getting Cucumber working with IronRuby – you may want to take a look if you’re getting stuck.

Learning Ruby? Here’s the book for you…

Something I get asked over and over again: “Can you recommend a book that will improve my ruby skills?” There are quite a few ruby books out there, but here’s what has become my standard answer:

Learning Ruby - O'Reilly

Learning Ruby“, published by O’Reilly, is awesome. I was given my copy when an old friend and colleague moved back to Australia – he couldn’t fit the book into his suitcase! I gladly became the new owner and have since handed it out to a number of people, all of which give it rave reviews and have ended up buying their own copy.

So, if you don’t know much ruby and want to increase your knowledge of it then this is the book for you.

Announcing ‘bewildr’ – test your WPF UI apps with IronRuby

Get it here: http://www.bewildr.info

After writing an automation framework to test a WPF GUI using IronRuby and White, I decided to write a ruby-specific gem for automating WPF UI tests. Kinda like Watir, but for WPF instead of the web. The gem is called bewildr - I’ve been working on it for a while and it’s finally in a releasable state.

Here’s an example of bewildr being used in rspec to show you what it’s all about:

require 'rubygems'
require 'spec'
require 'bewildr'

describe "my example app" do
  it "should not allow invalid users to log in" do
    #start the app and wait for the main window
    @app, @main_window = Bewildr::Application.start_app_and_wait_for_window("c:\\app.exe", /App v1.\d+/)

    username_field = @main_window.get(:id => "username")
    password_field = @main_window.get(:id => "password")
    login_button   = @main_window.get(:type => :button, :name => "Go")

    #some initial checks...
    username_field.should be_enabled
    password_field.should be_a_password_field

    #attempt login with invalid user
    username_field.text = "invalidUser"
    password_field.text = "s3cr3t"
    login_button.click

    #check we're not logged in
    @main_window.get(:id => "login_message").text.should match("Wrong username/password")
  end
end

And, since bewildr was written ‘BDD-style’ there are loads of examples of its use in cucumber here: http://github.com/natritmeyer/bewildr/tree/master/features/

Cool:

  • It’s written in ruby
  • It’s free (as in speech – BSD license)
  • It’s free (as in beer – there are no bazillion-dollar yearly license fees)
  • It’s easy to install (here’s how: gem install bewildr)
  • It has a clean API (makes for idiomatic tests in cucumber/rspec)
  • It has a strong test focus (…of the testers, by the testers, for the testers…)
  • It’s been written BDD-style
  • It’s updated frequently
  • It allows tests to be written in an interpreted language (with all the flexibility which that gives you – unlike White)

Not Cool:

  • It’s limited to IronRuby, not MRI/YARV (it needs access to .Net automation)
  • It’s new – expect bugs (please raise them when you find them)
  • It’s built on top of MS UI Automation (expect quirkiness)
  • There is quite a bit to do before it does everything I want it to, eg: it doesn’t yet allow you to test for visibility, there’s no drag-and-drop; see here for more

Note: I have no intention to support anything but WPF. No WinForms, no Silverlight, no [insert non-WPF tech here]. Not yet anyway…

So, if you’re looking for a UI testing tool to automate your WPF app with, but QTP is too expensive and White is too [insert pejorative here]… Well, what are you waiting for?  http://www.bewildr.info

Netbeans ‘Cucumber Features’ plugin in Beta!

The best ruby IDE, Netbeans, now has a Cucumber plugin in beta! It’s the old “QuBiT” plugin that I’ve been using for a while though it looks like it’s been rebranded as the “Cucumber Features” plugin. Here it is:

As well as syntax highlighting and pretty icons, the new version has the following new (to me) features:

  • right-click “Run Feature” in the editor window and the file browser window
  • Better formatting (plugin now in line with latest cucumber changes)
  • Formatting of Examples tables (killer feature for me!)

Nice! Now, if only it would provide right-click-run-scenario…

Testing a website on different versions of IE

So, no matter how much you argue that it’s an ancient, irrelevant browser; there’s no way you can wriggle out of having to test your web app against IE6 on WinXP. But… trying to find a machine with it lying around might be difficult. Magnanimous Microsoft have made testing your web app on different IE/Windows combinations less tedious than it could be: combine Virtual PC with a collection of pre-built images and you’re on your way. Here are the details…

First, you’ll need to install Virtual PC:

  • Download the latest version of Virtual PC from here if you’re running Windows 7
  • Download Virtual PC 2007 from here if you’re running Windows XP/Vista

Next, you’ll need to download as many of the following combinations of Windows/IE as you want from here.

The Windows/IE combinations available are:

  • IE6 / XP SP3
  • IE7 / XP SP3
  • IE7 / Vista SP1
  • IE7 / Vista SP2
  • IE7 / Vista SP3
  • IE8 / XP SP3
  • IE8 / Vista SP1
  • IE8 / Vista SP2
  • IE8 / Vista SP3

Download the images you need, start them, get your testing done before the VM runs out of time (they’re time limited) and then get back to doing something less painful!

Enjoy your multi-IE-version testing. Rather you than me ;)

How to connect to an Oracle database in IronRuby

After spending a few hours trying to connect to an oracle database in ironruby using various gems, I gave up. None of the gems out there would work, each for a different reason. It was time to write my own class to do the job of managing connections and executing queries.

You’ll need a few things:

  1. A copy of the ‘Oracle.DataAccess.dll’ that you can find somewhere inside this outrageously large download:
    http://www.oracle.com/technology/software/tech/windows/odpnet/index.html
    Copy the ‘Oracle.DataAccess.dll’ into your load path (you’ll find it somewhere in the bowels of the directory structure that the above installs)
  2. An oracle database you can point at
  3. The connection string required to connect to the database. It’ll look something like:
    Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROT...

Once you’ve got those details, you can use the following class:

require 'System'
require 'System.Data'
require File.join(File.expand_path(File.dirname(__FILE__)), "Oracle.DataAccess.dll")

class IronRubyOracleClient
  #pass in oracle connection string, eg, for Test env:
  def initialize(connection_string)
    @connection = Oracle::DataAccess::Client::OracleConnection.new(connection_string)
  end

  #opens connection
  def open
    @connection.open
  end

  #returns 2D array
  def execute(query)
    @query = query
    cmd = Oracle::DataAccess::Client::OracleCommand.new(@query, @connection)
    cmd.CommandType = System::Data::CommandType.Text
    data_reader = cmd.ExecuteReader()
    column_count = data_reader.visible_field_count.to_i

    result_rows = ::System::Collections::ArrayList.new

    while(data_reader.read) do
      row = ::System::Collections::ArrayList.new
      column_count.times do |i|
        row.add(data_reader.get_oracle_value(i).to_string)
      end
      result_rows.add(row)
    end

    result_set = []

    result_rows.each do |result_row|
      ruby_row = []
      result_row.each do |cell|
        ruby_row << cell.to_s
      end
      result_set << ruby_row
    end

    result_set
  end

  #close connection
  def close
    @connection.close
  end
end

And here’s how you use it:


#create your connection string
connection_string  = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=..." #etc...
#create an instance of the client, passing in the connection string
my_client = IronRubyOracleClient.new(connection_string)
#open a connection to the database
my_client.open
#execute a query and save the result
results = my_client.execute("select * from some_table")
#dump the results (a 2D array of values)
puts results.inspect
#close the connection
my_client.close

It’s fairly slow, but it works. Which is an improvement on what’s out there…

Note that everything is returned as a string. For some reason, the unless the data is a basic string or is a number that fits into an integer, the data gets garbled somewhere between the dll and ironruby. I can’t find out where, so everything-returned-as-a-string is the current compromise. If you can get it to work with all data types, send it along!

Explaining Watir, Selenium and WebDriver

Something I seem to be explaining to people all the time… the relationships between Watir, Watir “2.0″, Selenium, Selenium “2.0″ and WebDriver.

Alister Scott has done an excellent job of explaining the impact of WebDriver on Selenium and Watir and what it mean for their respective futures. Read it here.

Summary:

  • Selenium 1 => dead
  • Selenium 2 == WebDriver
  • Watir 1.* (+ derivs) => dead
  • Watir 2.0 => Watir API using WebDriver to communicate with the browser

===Update===
Added version number to Watir to avoid the confusion seen here.