So this will require (a) opening a database in Ruby, (b) running a test in Ruby, and (c) sending an email in Ruby. None of these is probably very difficult, but not being a Ruby expert I went searching for examples on the web. I wasn’t thrilled by the examples I found for these tasks, so I thought I’d write up what I did.
Databases: This is code that will open an Access database and grab all of the rows in the Exam table:
DBI.connect("DBI:ODBC:driver=Microsoft Access Driver
ENV['TESTINSTALLDIR'] + "db1.mdb ") do dbh
dbh.select_all('select * from Exam')
Tests: I started by writing my own little test procedures, until I stepped back and looked at what I’d done – I’d developed a rudimentary RUnit, along the lines of NUnit or CPPUnit. At that point I was sure that it had been done before, and it had – and not only that, but it turned out to be part of the Ruby standard library. Although what I’m doing here isn’t really what I would call unit testing, it’s close enough that I decided to use that instead.
DatabaseTest < Test::Unit::TestCase
assert(rows["Media Type"] == "Image Server")
Email: There are some good email sending examples around. I started with this one and ended here:
email_text = <<END_EMAIL
To: "Ben Fulton"
automated test failure
An automated assertion failed for the project
if (@counter > 0)
Net::SMTP.start("myprovider.net") do smtp
@from_addr, @to_addr )
puts "No failures!"
Now, my goal was for the results of the test to be put into the email. That took a long time to figure out. Step 1 of the solution was to realize what the automated test runner was doing under the covers, and take advantage of it. So I replaced the run(DatabaseTest) line with this:
tr = Test::Unit::UI::Console::TestRunner.new( DownloaderTest)Now I have the results back in a TestResult, which I can examine for failures, so emails only go out if some tests actually failed:
passed = tr.start()
if (passed.failure_count() > 0 passed.error_count() > 0)
fc.Add( “Failures found” )
Step 2 of the solution is to get the information from the test in a format that I can put in an email. It turns out that TestRunner.new can take a parameter defining where output should go, which defaults to STDOUT. I could have redirected it to a file, but that seemed like unnecessary work, so after a lot of searching I came up with what I was looking for, StringIO, which takes output and writes it to a string:
sio = StringIO.new
tr = Test::Unit::UI::Console::TestRunner.new(
DownloaderTest, Test::Unit::UI::VERBOSE, sio )
I also changed the default NORMAL verbosity parameter to VERBOSE. Then I replace the FailCounter “Failures found” line like this:
fc.Add( “Failures found: “ + sio.string )
And that was it. I’m not going to glue all this code together here, since this post is already too long, but hopefully if you’re interested it should be straightforward. Good luck!