Showing posts with label windows. Show all posts
Showing posts with label windows. Show all posts

Saturday, February 14, 2009

BDD WxRuby applications with Cucumber and Nobbie

For a long time now, I've been wanting to write some Cucumber features to describe a WxRuby application I have. A couple of weeks ago, I found a library called wx-nobbie on Rubyforge that seems to be almost exactly what I was looking for.  It provides a simple, high level interface for driving WxRuby applications through commands like "click", "choose" and "type".  I had a little trouble getting the tests to pass to start with, but with a few minor tweaks I got there.  I contacted the original author and got his permission to take it forward.

I created a GitHub repository for Wx-Nobbie and have made a few updates over the last week.  Currently, I've got 4 feature scenarios with 10 steps:

C:\dev\wx-nobbie>rake features
(in C:/dev/wx-nobbie)
In order to test drive a WxRuby application  # features/acceptance_test.feature
As a developer
I want Nobbie to provide acceptance test access to the application
  Scenario: Choosing a radio button  # features/acceptance_test.feature:5
    Then "radio_button" is not chosen# features/step_definitions/acceptance_test_steps.rb:21
    When I choose "radio_button"     # features/step_definitions/acceptance_test_steps.rb:1
    Then "radio_button" is chosen    # features/step_definitions/acceptance_test_steps.rb:17

  Scenario: Choosing a check box  # features/acceptance_test.feature:10
    Then "check_box" is not chosen# features/step_definitions/acceptance_test_steps.rb:21
    When I choose "check_box"     # features/step_definitions/acceptance_test_steps.rb:1
    Then "check_box" is chosen    # features/step_definitions/acceptance_test_steps.rb:17

  Scenario: Type into a text control        # features/acceptance_test.feature:15
    When I type "123" into "text_ctrl"      # features/step_definitions/acceptance_test_steps.rb:5
    Then I should see "123" in "text_ctrl"  # features/step_definitions/acceptance_test_steps.rb:9

  Scenario: Type into a combo box           # features/acceptance_test.feature:19
    When I type "456" into "combo_box"      # features/step_definitions/acceptance_test_steps.rb:5
    Then I should see "456" in "combo_box"  # features/step_definitions/acceptance_test_steps.rb:9


4 scenarios
10 steps passed

With just these 4 scenarios, RCov tells me I have 62.9% coverage.

Hurrah!

Sunday, January 25, 2009

Building a Ruby Extension With Visual C++ Express 2008

Edit March 29, 2009: While the instructions below describe how to build the Win32::GuiTest extension, I didn't get very far with using it before I found Wx::Nobbie which I much prefer and have taken up the maintenance of at Github.

I'd like to be able to use Cucumber to drive the development of Windows applications so I went looking for something like Webrat for desktop GUI's. I found Win32::GuiTest.  There is a project of the same name on RubyForge that contains the same source but that's as far as that went. 

Win32::GuiTest is a C extension that was compiled with Cygwin, so I wanted to rebuild a native version.  I found some instructions on Kevin Kleinfelter's blog that look much like below, but using VC++ 2008 I got to skip a couple of steps:

  1. Download and install Visual C++ Express Edition (this is free, I got the 2008 version)
  2. Edit $RUBY_HOME/lib/ruby/1.8/i386-mswin32/config.h and delete the “#error MSC version unmatch” line
  3. Open a Visual Studio 2008 Command Prompt
    • Start
    • All Programs
    • Microsoft Visual C++ 2008 Express Edition
    • Visual Studio Tools
  4. cd C:\temp\guitest020218\ext\cguitest
    • I'm building the guitest extension
  5. ruby extconf.rb
  6. nmake
  7. mt.exe -manifest cguitest.so.manifest -outputresource:cguitest.so;2
    • Copy and paste the command above. You need it all from the 'mt' to the ';2'
  8. nmake install
  9. cd \temp\guitest020218
  10. ruby install.rb config
  11. ruby install.rb install
  12. To test:
    • irb
    • require 'win32/guitest'
    • check response is '=> true'

Sunday, October 5, 2008

Where to put sqlite3.dll on Windows

When I first started using SQLite3 on Windows, most people suggested downloading sqlite3.dll from www.sqlite.org and storing it in ruby/bin so Windows could find it. For a while, this strategy worked fine but I really didn't like the application requiring users to put that DLL into an acceptable place. I don't know why it didn't occur to me earlier, but, given that this is only intended to be a Windows application, why not just modify the PATH environment variable within the application. So that's what I've done. In config/boot.rb:
# Make sqlite3.dll available
ENV['PATH'] += ";#{RAILS_ROOT}/vendor/bin/sqlite3"

Saturday, September 20, 2008

My first Rails bug

UPDATE January 14, 2009 -> The patch for this bug was accepted!

I'm pretty new to Rails and my first project included uploading videos. Shouldn't be too difficult I thought, after a little Google searching, I came up with the perfect example by Jim Neath: Converting Videos with Rails: Converting the Video Wanting to practice new skills with RSpec and Cucumber I wrote my first feature spec:

Feature: Upload videos
  In order to provide videos to users after hours
  As a videographer
  I want to upload videos

  Scenario: A valid filename is provided
    Given I go to the new video page
    And I browse to the file "Movie_0001.avi"

    When I submit the upload

    Then I should see "success"
    And the file should be uploaded
and the supporting steps file, upload_steps.rb:
require 'ftools'
require 'mime/types'

When /I browse to the file \"(.+)\"/ do |path|
  @original_filepath = File.join('features/fixtures/', path)
  mime_types = MIME::Types.of(@original_filepath)

  attach_file 'video[source]', @original_filepath, mime_types[0].content_type
end

When 'I submit the upload' do
  click_button 'Create'
end

def uploaded_filepath
  uploaded_basename = File.basename(@original_filepath)
  File.join(RAILS_ROOT, "public/videos/1", uploaded_basename)
end

Then /the file should be uploaded/ do
  assert File.compare(@original_filepath, uploaded_filepath)
end
what I got was:
...
    And the file should be uploaded
       is not true. (Test::Unit::AssertionFailedError)
      c:/ruby/lib/ruby/1.8/test/unit/assertions.rb:48:in `assert_block'
      c:/ruby/lib/ruby/1.8/test/unit/assertions.rb:500:in `_wrap_assertion'
      c:/ruby/lib/ruby/1.8/test/unit/assertions.rb:46:in `assert_block'
      c:/ruby/lib/ruby/1.8/test/unit/assertions.rb:63:in `assert'
      c:/ruby/lib/ruby/1.8/test/unit/assertions.rb:495:in `_wrap_assertion'
      c:/ruby/lib/ruby/1.8/test/unit/assertions.rb:61:in `assert'
      ./features/upload/steps/upload_steps.rb:22:in `And /the file should be uploaded/'
      features/upload/upload.feature:14:in `And the file should be uploaded'
...
On closer inspection, the test was failing because the uploaded file was truncated in some bizarre way. However, if I ran the application and manually upload a file from the browser, everything worked fine. After much hunting I ended up in rails/actionpack/lib/action_controller/integration.rb where in multipart_body, the mode is not specified in the call to File.open, so it defaults to "r". This is all well and good on anything but Windows, which I happen to be using! Windows requires that the mode be specified as "rb" to ensure the file is read as binary. I submitted a patch but I'm not holding my breath for it to be pulled in anytime soon.

Ruby PCAN DLL Wrapper

Inspired by System Testing In Ruby (Systir), I have published a small Ruby PCAN USB DLL Wrapper. Now with a small device available for less than $300 and some free software, I can write automated system test scripts of the form:
send tftp_rrq("autoexec.bat").with(blksize(2036)) verify_target_sends oack(blksize(2036) send ack(0) verify_target_sends autoexec_bat send ack(1)
If you have rubygems installed, PCAN DLL Wrapper is easily obtained:
set http_proxy=http://my_proxy_host.com:80 gem install pcanusb
and then use:
require 'pcan_usb' PCAN_USB.init(PCAN_USB::BAUD_1M) PCAN_USB.write(0x0E100501, "Hello World!") PCAN_USB.close

Tuesday, June 10, 2008

ActiveRecord requires RAILS_ROOT for relative Sqlite path

I'm writing a little time tracking tool for Windows in Ruby. The data is stored in a database so I figured I'd use ActiveRecord and maybe learn something about Rails along the way. Everything I found about ActiveRecord tells me that it "can be used independently outside of Rails". One minor detail that I just figured out:
If you want to use a relative path for a sqlite3 database in your database.yml, you have to define RAILS_ROOT.
For example, if config/database.yml =>
production:
  adapter: sqlite3
  database: db/production.sqlite
ActiveRecord initialization (mine's in config/boot.rb) looks like:
RAILS_ROOT = "#{File.dirname(File.expand_path(__FILE__))}/.."
RAILS_ENV  = ENV['RAILS_ENV'] || 'production'

$LOAD_PATH.unshift "#{RAILS_ROOT}/vendor/sqlite3"
config = YAML::load(IO.read("#{RAILS_ROOT}/config/database.yml"))
ActiveRecord::Base.configurations = config
ActiveRecord::Base.establish_connection(config[RAILS_ENV])