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'

Wednesday, January 14, 2009

My first Rails bug – accepted!

At the time that I posted about My first Rails bug the tests that existed for Action Pack contained failures and the only test in integration_upload_test.rb was:

assert_equal(:multipart_form, SessionUploadTest.last_request_type)

I felt that my change could be submitted with no tests because:

  • The change was trivial (6 characters)
  • The change was for a well known Windows file issue
  • The tests that existed didn’t pass
  • There were no example tests for me to build on

Three months after I submitted the ticket, Pratik dismissed it by changing its state to incomplete with the comment “Missing a test case.”  Are these guys CRAZY?  No, no they are not.  Just because there were broken windows in the neighborhood did not give me the right to break any more.

So, I sucked it up, cloned the latest rails repository again and to my surprise … all the Action Pack tests passed! … and there was a nice simple example in multipart_params_parsing_test.rb:

  test "uploads and reads file" do
    with_test_routing do
      post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
      assert_equal "File: Hello", response.body
    end
  end

This is too easy!  I added a test for my issue:

  test "uploads and reads a binary file in windows" do
    with_test_routing do
      fixture_file = FIXTURE_PATH + "/mona_lisa.jpg"
      post '/read', :uploaded_data => fixture_file_upload(fixture_file, "image/jpg")
      assert_equal 'File: '.length + File.size(fixture_file), response.content_length
    end
  end

Watched it fail.  Added the magic 6 characters (“, ‘rb’”).  Watched it pass.  Wrapped it up and shipped it off.  The following morning I pick up an email letting me know that Pratik has reopened the ticket and assigned it to Joshua Peek for review.  The change was committed before the day was out!

Many thanks to Pratik and Josh for attending to this so promptly.

Monday, January 12, 2009

Restful-Authentication with Cucumber features (Step 2)

Knowing that all the stories that ship with restful-authentication pass, I’m ready to convert to Cucumber features.  The process is actually fairly simple and is described quite clearly on this Cucumber wiki page.  I did have to tweak a couple of the step matchers and create ra_env.rb:

Before do
  Fixtures.reset_cache
  fixtures_folder = File.join(RAILS_ROOT, 'spec', 'fixtures')
  Fixtures.create_fixtures(fixtures_folder, "users")
end
 
# Make visible for testing
ApplicationController.send(:public, :logged_in?, :current_user, :authorized?)

I’d have liked to put this in the support directory but Cucumber loaded it before env.rb, so I put in with the step_definitions.

Once that was done, all that was left was to update authenticated_generator.rb to copy the template features instead of stories.

The result is available from my fork on github.

Enjoy!

Saturday, January 10, 2009

Restful-Authentication with Cucumber features (Step 1)

My latest exercise is to update the restful-authentication Rails plugin to generate Cucumber features instead of RSpec stories. There is already a Lighthouse ticket open for this, so I guess I'm not the first one to think of it. The first steps make sure that restful-authentication is set up correctly:
  1. Create an empty Rails application
  2. Put in version control (git init, git add ., git commit -a -m "init")
  3. Add plugins as shown on the Cucumber Rails wiki page
  4. Add my fork of restful-authentication in the same manner
  5. Complete the restful-authentication installation per the directions
  6. Create the database tables (rake db:migrate)
  7. Run the RSpec stories (stories\rest_auth_stories.rb)
Stories won't even run, let alone pass! I'm not going to show all the errors along the way, but the steps to get to passing stories were:
  1. Added AthenticatedSystem into ApplicationController with the following 2 lines:
      include AuthenticatedSystem
      helper :all # include all helpers, all the time
  2. Uncommented the routes.rb map.root line(map.root :controller => "welcome")
  3. Removed line 1 of user_steps.rb (require File.dirname(__FILE__) + '/../helper')
  4. Created a minimal WelcomeController with an index method
  5. Created a minimal layout
16 scenarios: 16 succeeded, 0 failed, 0 pending
Hurrah!