Does anyone have any experiences with one of the object mother libraries like object daddy? (Answers at standup were “no, we always wrote our own object mothers in a domain-specific way”). The appeal of a library is that it might help keep track of what needs to be done to make an object pass rails validation.
Clock.zone now has exists. (Background, pivotal has a Clock class which has a now method which can be implemented either by a call to Time.now for production, or a mock clock which lets tests specify the “time”). This is so that the rails 2.1 features like Time.zone.now have an analog in Clock.
Standup 08/26/2008
Looking for options to maintain a website of technical documentation with the following:
- A somewhat technical person, but not a programmer, must be able to
maintain the site (think a technical manager or a tech writer). - I need to display code samples, so this should be easy/convenient
- Somewhat skinnable (custom logo, custom fonts & colors)
The ideal examples would be the google chart api or google maps api
A possible solution is a wiki (mediawiki?). Something
google-code-like gets extra points for the issue tracker. Google
groups gets points for the mailing list. Google sites seems like is
might be a decent basic option (it’s easy to point a CNAME at it too).Experience reports/recommendations appreciated.
- A somewhat technical person, but not a programmer, must be able to
Rails hackfest is on through the end of August. Get points for getting patches accepted, and win prizes.
Standup 7/28/2008
Interesting
- firebug lite 1.2 is out
Ask for Help
We upgraded to rails 2.1 and polonium and our rspecs
are not running on CI, but run fine if you simply use rake on the
command line.
Check to see if you are using the rake extensions in pivotal core bundle.
Using setTimeout() to wait for DOM to update in JsUnit does not work.
Using setTimeout in tests is not going to do what you want, unless you mock setTimeout. Basically, setTimeout kicks off another thread which is not likely to effect the current test.
Standup 7/25/2008
Interesting Things
- There was an edge version of Rails (this project has a frozen Rails at some point in the past) that had a bug where a namespaced route would send a POST that should go to
MyController#createwas instead going to a POST toMyController#index. The fix is to freeze to current Edge, or usealias_method.
Ask for Help
“Any way to turn off a validation in a re-opened class?”
No way to do this. Best to refactor by pulling the validation out of the class and then mixing it in, or not, at a different level.
Standup 7/23/2008
Interesting Things
- Y!Slow + Firebug + submit a form will cause the result to be pulled from cache instead of hitting your server. The workaround is to disable Y!Slow.
- Some of our customers are requesting targeting Firefox 3, which has some rendering differences from FF2. So we’re adding FF3 to the system image with a new icon and the correct trick to let it run side-by-side with FF2.
- How to Run FF2 & FF3 side-by-side on Mac OS X
- FF3 customer icon that is sufficiently different than Firefox’s normal icon so you can tell the difference
- On a related note, rumor is that Facebook is dropping support for IE6. So is 37Signals.
- Interesting issues with the Globalize plugin & Rails 2.1:
- The currency formatting code does not work at all anymore – it always uses a ‘$’
- Their work for localizing templates, which involves injecting a fully-qualified path, breaks
#assert_template. The workaround is to comment out the path injection code, but this only works if you don’t have localized templates.
- EngineYard’s eycap gem version 0.3.6 now has better support for deploying from SVN tags
- Deploying from tag, since the URL was different used to do a
rm -rf, which takes a long time on EY’s GFS disks for large file sizes. This was causing a customer’s deploy taking ~20 minutes - The fix was to change eycap to use svn switch; the deploy now takes ~1 minute
- Deploying from tag, since the URL was different used to do a
Ask for Help
“Anyone seen/solved an issue with random font size increase using Firebug 1.1 or later?”
The issue is that at some point a page will render with much larger fonts and the CSS exploration won’t tell you why. The work around is to launch a browser with Firebug disabled and run it side by side with the same page in a window with Firebug enabled (restarting the 2nd window whenever the problem occurs.)
Seeing this with Firefox 2 and 3 and any Firebug later than 1.05 (which doesn’t run on FF3). This might be an issue with IFRAMEs, but we’re not sure. No data found on this via Google searches or the Firebug group. We will post there.
Standup 07/21/2008
Interesting Things
Model#update_allis your friend if you’re not yet on Rails 2.1Like
Model#update_attributefor each attribute,#update_allwill save direct to the database, bypassing validation, updating only the columns you specify. In Rails 2.1, with partial model updates, you may not need this. But if you’ve not yet upgraded your application, then give#update_alla try.
Update: fixed per comment. Model#update_attribute does not validate. Thanks for the catch!
Standup 3/19/08
Interesting
The defer method in EventMachine allows you to spawn processes in Ruby, like this (from comment in eventmachine.rb):
operation = proc { # perform a long-running operation here, such as a # database query. # as usual, the last expression evaluated in the block will #be the return value. } callback = proc {|result| # do something with result here, such as send it back # to a network client. } EventMachine.defer( operation, callback )New art on the wall, check it out.
Help
- Can anyone recommend a good hosted wiki for casual use? Some of the suggestions so far include pbwiki, MediaWiki (perhaps a bit heavy weight for personal use), and Google Pages.
Standup 03/18/08
Interesting
- Ian Mcfarland talks to Geoffrey Grosenbach about Pivotal’s agile culture in the May 17 episode of the Rails Podcast. Check it our here.
- This Wednesday’s brown bag will be a round table discussion about “Tracker and the client: The real vs. the ideal”. Lunch provided, as always.
- When something in Rails isn’t working as expected, it may just be a bug that’s been reported or fixed recently. Is a good idea to check the the Trac tickets at dev.rubyonrails.org.
Help
- Rails rcov seems to get stuck in an infinite loop on Leopard.
- Anyone know a good general practitioner within walking distance of the office?
- Confirm dialogs are tripping up Selenium (8.1) on one of our projects. Something related to focus, perhaps?
- What does NĂ Hea mean?
Happy Path Testing With Selenium RC Fu
Selenium RC Fu is a fantastic system for testing Ruby On Rails
applications. It is the blending of xUnit testing with Selenium.
Selenium is a cool system that operates your browser as if a human were sitting
there moving the mouse pressing buttons and keys.
Selenium RC Fu is also a remarkable example of the power of open
source. It’s selenium remotely controlled by rails and
ruby. You can learn more about it by viewing the slides for
Full-stack webapp testing with Selenium and Rails
presented by my colleagues Alex Chaffee and Brian Takita at the
SDForum Silicon Valley Ruby Conference.
Now that you are excited about Selenium RC Fu, by law I
must inform you that this wonderful testing tool comes with some
costs. First, this is the daisy cutter of testing — problems will be detected,
but it won’t be too specific about those problems. A failed selenium
test will likely only tell you some expected text
was not present on the page — you have to do some digging
to discover the real problem.
It’s also slow. To be fair, a lot of software is running to do this testing.
So use selenium testing sparingly. A good strategy is to restrict
selenium testing to “happy path” testing. These happy path tests
become a compliment to other more focused and faster unit and integration
tests.
Getting Started With Selenium RC Fu
Selenium RC Fu is hosted at rubyforge.org in the “pivotal.rb”
project. It’s not well documented and a little hard to find. The
primary documentation is the
README File.
Step 1 is to add it to your project:
script/plugin install svn://rubyforge.org/var/svn/pivotalrb/seleniumrc_fu/trunk
Building Your Tests
Create your tests in app/tests/selenium. The basic structure mirrors
the other test types:
require File.dirname(__FILE__) + "/selenium_helper"
class HappyPathsTest < MyProject::SeleniumTestCase
def test_nav_bar
...
end
def test_about
...
end
# more tests
end
Note that HappyPathsTest extends something called
MyProject::SeleniumTestCase. Selenium RC Fu provides a sample
selenium helper file that suggests this convention for name spacing
your tests.
For the happy paths tests I simply wanted to go to a page and know
that the page loads. A pattern I learned from my colleague
Shifra is:
- Pick something you know is on the target page, but not on the
current page. Let’s call it ‘evidence’. Assert that evidence is not
present on the current page. - go to the target page
- assert that evidence is present on the target page.
This process ensures that you are moving about as you expect. Here’s
an example from my project:
def test_tasks
...
assert_element_not_present "xpath=//h1[text()='The Daily Planet']"
click_and_wait "link=The Daily Planet"
assert_element_present "xpath=//h1[text()='The Daily Planet']"
...
end
I repeated this simple pattern for every path.
Selenium Functions/Assertions/Commands
Here are the functions and assertions I used in my tests:
click_and_wait locatorgo_backwait_for_page_to_loadtype locator, textassert_text_present textassert_text_not_present textassert_equal value1, value2
Many of the functions require a ‘locator’ argument. This needs to
identify a single element on the page. Often the name or id of an
element is sufficient, but you may need to use an XPath. Check
the docs
for more information on element locators.
These functions were sufficient for me. Look for more in
vendor/plugins/seleniumrc_fu/lib/seleniumrc_fu/selenium_dsl.rb.
Selenium RC Fu comes with some rake commands too (from rake -T selenium):
rake selenium:restart_servant # Stop and start the selenium servant (the server that launches browsers) on localhost
rake selenium:run_server # Run the selenium servant in the foreground
rake selenium:server # Run the selenium remote-control server
rake selenium:start_servant # Start the selenium servant (the server that launches browsers) on localhost
rake selenium:stop_servant # Stop the selenium servant (the server that launches browsers) on localhost
rake selenium:test # Run a selenium test file (default test/selenium/selenium_suite)
rake selenium:test_with_server_started # Run the selenium tests in Firefox
Running Your Tests
You can run your selenium tests individually or as part of a
suite. Selenium RC Fu comes with a suite script in the
vendor/plugins/seleniumnrc_fu/sample directory. Drop that in your
test/selenium directory.
The selenium server must be running before running individual
tests. You can start the server with the rake command rake. Once the server is running you run your tests from
selenium:server
the command line or via the suite.
You can also run the suite with the command rake selenium:test. This
command is smart enough to start the server if it’s not already
running. However, when the server is started by this mechanism it’s a
little more work to stop it. You can stop the server with a simple ^c
if it was started via the rake selenium:server command.
Make It So
That’s really all you need to build your tests, but here are few more
things that may help.
Site Diagram
A site diagram is handy for building your happy paths tests. There
will be a lot of paths through the site and marking the paths on the
diagram as you visit them is an easy way to track your progress.
On the diagram you need to indicate both pages and the paths to those
pages.
The later is really important. It’s the paths that you will be
testing with your happy path selenium testing. Often there are
buttons, links, or other controls such as check boxes that may touch
the server and reload the current page, or just update the current
page via ajax. Be sure to add these to your
navigation diagram.
Here’s the diagram I used for my site.

Selenium IDE
You can code your tests by hand using Selenium RC Fu functions but
it’s easier if you use
Selenium IDE. This is a
Firefox plugin that records your activity. That activity is available
in various selenium dialects and can be pasted into your
tests. Unfortunately, it does not have output for Selenium RC
Fu. Nonetheless I still found it useful. I simply clicked through my
application while Selenium IDE was recording, pasted the
resulting selenium commands into my tests, then converted those
commands to equivalent Selenium RC Fu commands. For example:
Output from Selenium IDE:
@selenium.click "link=My Account"
@selenium.wait_for_page_to_load "30000"
assert @selenium.is_text_present("Update Account")
Becomes:
click_and_wait "link=My Account"
assert_text_present "Update Account"
Test Data
Your selenium tests will be exercising your application just like
standard unit or integration tests. These tests require data and there
are a variety of techniques to make data available to your
tests. Building your happy path tests is easier if you have fixture data and that fixture data is loaded in your development environment via rake. If you use fixture scenarious, it
db:fixtures:load
is handy to have a scenario for selenium testing, which you would load
with something like rake db:scenario:load SCENARIO=selenium.
With your fixtures loaded in your development environment you can see
exactly what is present during testing and the selenium IDE will
record exactly what is played back by selenium.
XPath Checker
Usually Selenium IDE can assign a locator that simply works but there
are times when it can’t.
Using XPath Checker you can
right click on an element and it will display an XPath to that
element. You can also experiment with varitions and XPath Checker will
list all of the elements on the page that can be identified by that XPath.
That’s it. Let me know how it goes.
Teaching Your Tests To Report Unused Parameters
Recently I was about to check in some changes and did a last minute
click through of the application. All of a sudden I’m staring at a stack
trace. My tests were green and I had functional tests for the failing
controller/action.
Tests are like pants — they cover your backside while you focus on other
things like adding features to your application. Suddenly I felt a
breeze on my cheeks. Something was amiss.
I soon discovered the action and its associated tests had diverged
over time. Some of the parameters were renamed in the action but not
in the functional test. Since some of the work of the action was
conditional on the presence of certain parameters, that work was no
longer being tested.
This exposed weaknesses in the tests and code, such as expected
side effects in the tests that are never checked. If they had been
checked the tests would have failed and the parameter name mismatch
would have been discovered.
Most functional tests provide specific parameters that should at least
be examined during the processing of the action. Reporting unread
parameters would strengthen those tests. It was conceivable to me that
some of the other functional tests had similar unused parameters. I
wanted all of my functional tests to report all unused parameters.
The first step was to instrument the params hash. I wanted to track
access to the params hash and report parameters that were not read
during the processing of the action. I don’t know what all is done to
params during the lifecycle of a test. I’m only interested in access
from the time the action starts till it returns so I need to be able
to turn the tracking on and off at specific times.
It turns out that Rails uses a subclass of Hash called
HashWithIndifferentAccess.
I added my changes to
HashWithIndifferentAccess in test/test_helper.rb:
class HashWithIndifferentAccess
def [](key)
@accessed_keys ||= {}
@accessed_keys[key] = true
super
end
def start_logging
@accessed_keys = {}
end
def end_logging
@accessed_keys['action'] = true
@accessed_keys['controller'] = true
never_accessed = []
self.each_key do |key|
never_accessed << key unless @accessed_keys.include?(key)
end
raise "Some keys never accessed: #{never_accessed.join(', ')}" unless never_accessed.empty?
end
end
With these changes an exception will be raised if any first level keys
are not read between start_logging
and end_logging.
In each of my functional tests I added code similar to this (from account_controller_test.rb):
class AccountController
around_filter :check_params
private
def check_params
params.start_logging
yield
params.end_logging
end
end
The around filter starts and ends the logging in the context of the
action.
With these changes in place my tests no longer passed and my
backside was warm and protected again.