Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Pivotal Labs

Standup April 18th – Keeping fixtures fresh and Regex's encoded

Pivotal Labs
Monday, April 18, 2011

Help!

Jasmine fixtures
A Pivot was bothered by the occasionally stale state of Jasmine .html fixtures. If you’re following a workflow similar to the recent Jasmine Railscast then your fixture files will undoubtable deviate from the ‘reality’ of your application. JB posted a solution that address the issue of quickly generating and loading .html fixture files, but this Pivot’s concern was having to manually kick off that process. It seems like watchr would be a good tool to monitor app/views and call one’s fixture generation process.

encoding of regular expressions in 1.9
Executing regular expressions over input of unknown encodings has caused headaches for people using Ruby 1.9. When the encoding of the regex and input differ Ruby throws an Encoding::CompatibilityError. The only solution we’ve seen is to change the encoding of either the input or expression to match the other, as seen here.

Does anyone know of a double ledger accounting gem?

crickets

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 1/19/2011: How would you google this?

Pivotal Labs
Wednesday, January 19, 2011

Ask for Help

“Anyone using Selenium 2 and Webdriver?”

One of our internal projects is using it.

“How to stop time in Jasmine?”

There were a couple suggestions:

  • use a global function, such as ‘now’
  • send in your own clock object

“Whurl standalone, or more dynos?”

Apparently Whurl is running on a single dyno at Heroku, so a single bad request can tie up Whurl until the request times out. Where are you TildeWill?

“What’s this called?”

Imagin these are records in a relational database, with the records on the left having a one to many relationship with the records on the right. How would you google this?

one to many diagram

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ken Mayer

rails 3.0.2 + jasmine 1.0.1.1 + json_pure == dll_hell.rb

Ken Mayer
Tuesday, November 23, 2010

The 3.0.2 update to rails made a change in active support that creates an interference pattern failure in the jasmine-gem. Not jasmine, itself, mind you, just the standalone server that runs the jasmine tests, and not the server, but just the report runner. Thus, your tests are all green, but the jasmine suite fails anyway. You might see this error:

undefined method `merge' for #<JSON::Pure::Generator::State:0x102181890> (NoMethodError)

The selenium driver inside the jasmine gem is loadingjson_pureunless it can find an already loaded JSON class. json_pure was hacked by rails for other reasons, but it breaks JSON.generate. Madness ensues.

To fix this, you need to use something other than json_pure, at least in your test suite. The fix, fortunately, is pretty simple. Add the following line to your Gemfile

gem "json", "1.4.6"

This will load the json gem built with native extensions. The version number is not necessary to fix this problem, but we try to lock down versions as a standard practice.

This was maddeningly painful to pinpoint. I’m not sure if there’s a long term solution to the problem either. You need a JSON library, but so do many others. Monkey patching the class seems really handy, but is prone to break behaviors.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Sarah Mei

Standup 11/4/2010: sweeping-up-the-ticker-tape edition

Sarah Mei
Thursday, November 4, 2010

Is it possible in Jasmine to spy on a getter such as myObject[key]? We want to know when local storage is accessed.

No. Jasmine‘s spyOn only works with functions, and in JavaScript getters are not implemented as functions.

Local storage has a functionally equivalent getValue function, which you can spy on, but the spy is not triggered when you access the value via [].

Interesting:

  • On unicorn, the random number generator is seeded before the fork. So if you are depending on a set of unicorns to generate different random numbers, you need to reseed the random number generator manually after the fork.

  • If you want to make absolutely sure you aren’t generating any queries in your Rails views, try no_querying_views – which explodes if your query comes from view code.

  • Other ways to track down inefficient queries that folks have successfully used: bullet and query_reviewer

  • Skype 5 beta is out for Mac, which allows group video chat. Everyone must be on the beta for it to work.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Abhijit Hiremagalur

Standup 08/03/2010: Bundle me this Batman!

Abhijit Hiremagalur
Tuesday, August 3, 2010

Ask for Help

  • I asked if there’s a date library in Ruby as rich as Java’s JODA

Suggestions included Chronic and RI_CAL though I’m hoping for something that can represent arbitrary periods (ranges?) of time JODA and handles interval calculation and other such date/time arithmetic.

  • is(‘:visible’) doesn’t always work as expected in Jasmine

One project reported that using this to as part of a Jasmine spec to ensure that an element becomes visible doesn’t appear to be reliable.

  • Annotate and Git History failed for a team using Rubymine 2.0.2 and git 1.7.2.1 in combination with svn.

They solved the problem by downgrading to git 1.7.1.1:

I followed instructions here to create a local set of portfiles:

http://guide.macports.org/#development.local-repositories and grabbed the older portfile from here:

https://trac.macports.org/browser/trunk/dports/devel/git-core?rev=69357

After I could do a port search git-core and have 1.7.1.1 show up, I was able to sudo port deactivate git-core @1.7.2_0+doc+svn and sudo port install git-core @1.7.1.1+doc+svn

  • One person was experienced compile errors when installing memprof on Ubuntu, fortunately somebody else had gotten this working before and offered to help him through thee.
  • A team noticed that Bundler ran multiple (4) times on CI taking nearly 11mins overall and wanted to know to make Bundler run only once

It was suggested that the problem may be due to the way they’d setup their preinitializer.rb and they should move the bundle install into a Rake task.


if ENV['IS_CI_BOX']
puts "IS_CI_BOX is set, running bundle install..."

system(‘bundle install’) || raise(“‘bundle install’ command failed. Install bundler with gem install bundler.”)

end

It was pointed out that they should make sure their Gemfile.lock file is checked into version control, which it was. Additionally Bundler 1.0.0 RC1 will allow isolating gems to a local path using bundle install path --disable-shared-gems

Interesting Things

  • The Facebook Graph API doesn’t appear to implement OAuth 2.0 properly/completely so it doesn’t work with the OAuth2 gem
  • One Pivot noticed that the version of ImageMagick installed on the default EngineYard solo image is out of date and had to upgrade this manually.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Abhijit Hiremagalur

Standup 08/02/2010: weird errors and convenient Jasmine fixture generation

Abhijit Hiremagalur
Monday, August 2, 2010

Interesting Things

  • One team noticed an odd error when they mistyped a Thor constant name.

ArgumentError: Thor is not missing constant Sandbox!.

This appears to due to how #const_missing in activesupport handles nested constant names. Specifically when trying to reference one nested constant from within another nested constant that isn’t its parent:

 

Curiously the spec that exposed the previous issue also returned this odd summary:

0 examples, 1 failure, -1 passed

This is also similar to another standup blog post from almost a year ago.

  • When using JB’s technique to save fixtures
    for Jasmine in controller specs
    , considering naming all your examples that create fixtures identically. This way you can easily run just these examples to regenerate your fixtures with something like spec -e 'should generate a fixture for jasmine'
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Adam Milligan

iPhone UI Automation tests with Jasmine

Adam Milligan
Sunday, July 18, 2010

Since the language of the new iPhone UI Automation component is JavaScript I figured the easiest way to organize tests is to use a JavaScript testing framework, such as Jasmine. So, I created jasmine-iphone, which is little more than a few simple scripts to make UI Automation and Jasmine play nice.

Once you clone jasmine-iphone from GitHub (it includes Jasmine as a submodule, so be sure to git submodule init && git submodule update) you can copy the example-suite.js file, import your spec files, point Instruments at your suite.js and go.

As an example, I set up a trivial example in the Cedar project. The directory structure looks like this:

Project Directory
- Spec
    - UIAutomation
        - jasmine-iphone     <--- submodule
            - jasmine        <--- nested submodule
        - suite.js
        - thing-spec.js
        - other-thing-spec.js

The suite.js file is relatively simple (note that I moved it up one directory from where the example-suite.js file is, so the #import statements are slightly different):

#import "jasmine-iphone/jasmine-uiautomation.js"
#import "jasmine-iphone/jasmine-uiautomation-reporter.js"

// Import your JS spec files here.
#import "thing-spec.js"
#import "other-thing-spec.js"

jasmine.getEnv().addReporter(new jasmine.UIAutomation.Reporter());
jasmine.getEnv().execute();

You can write the specs themselves the same way you’d write Jasmine specs for anything else. The UIAutomation subclass of the Jasmine Reporter takes care of marking the start of each spec, as well as reporting if it passes or fails. You’ll need to use the UIAutomation classes and methods for driving your application’s state, of course.

That’s it. Try it out and see what you think.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 6/3/2010: Jasmine bundled with RubyRacer

Pivotal Labs
Thursday, June 3, 2010

Interesting Things

Jasmine bundled with RubyRacer
Jasmine is now optionally bundled with the RubyRacer gem. This lets you run Jasmine tests through Google’s V8 engine in a browser-less environment. Similarly, some Pivots paired Jasmine with Johnson and env.js to produce JazzMoney. Right now, JazzMoney is the only headless testing tool for Ruby that has DOM support, but I’m sure RubyRacer has that in mind. You can find JazzMoney here.

Help

Does anyone know how to run specs with a certain name? We’re using RSpec to generate fixtures for our Jasmine tests and want those to be updated right before we run our Jasmine task.

You can set SPEC_OPTS with the ‘e’ flag and give it a string to match test names. Something like this: rake spec SPEC_OPTS='-e "should generate a fixture"'

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
JB Steadman

javascriptTests.bind(reality)

JB Steadman
Friday, February 5, 2010

Javascript tests are good, but manually-maintained HTML fixtures are painful. It’s time consuming to keep fixture markup in sync with the actual markup produced by your app. Despite best efforts, deviations arise, leading to bugs and false positives in tests.

For the past few months on Mavenlink, we’ve been pre-generating real-life fixture markup and making it available in our javascript tests. Results have been positive.

The basic approach is simple:

1) Pre-generate real-life markup using any convenient mechanism.

2) When javascript tests run, load the pre-baked markup into the DOM for access by JS code.

For #1, we use a small set of RSpec controller specs that exist solely to generate fixtures. For #2, we retrieve fixture markup from our Jasmine server via ajax, and inject it into the DOM with jQuery. While our approach leans on the various bits of our stack, any part of it could be swapped out to adapt to different tools.

Big thanks to Jonathan Barnes for the code that got us started.

Generating the fixtures

Taking a closer look, here’s an RSpec test that generates an HTML fixture file named ‘workspace-page’:

describe WorkspacesController do
  it "generates a workspace page" do
    @workspace = create_workspace
    log_in @workspace.creator
    get :show, :id => @workspace.to_param
    response.should be_success
    save_fixture(html_for('body'), 'workspace-page')
  end
end

We create a workspace, hit the WorkspaceController‘s show method, and save the full text of the response’s <body> element to a file. This spec lives in a file with others like it, separate from the real controller specs. We have about a dozen of these specs, all in the same file.

We added save_fixture() and html_for() to ControllerExampleGroup to help with fixture generation. This gist has implementation details.

Our javascript tests sometimes require that we load different versions of the same page. We generate a different fixture for each version, giving them meaningful names like ‘busy-workspace-page’ and ‘empty-workspace-page’.

When we change markup consumed by our javascript tests, we re-run the controller specs that generate fixtures. Changes are picked up the next time we run our javascript tests. Fixture generation is hooked into continuous integration, so our javascript tests see the latest markup when running in CI.

Loading fixtures into the javascript test DOM

On the javascript side, fixture loading is handled by the code in this gist. Of note:

  • We use two methods for making fixture content available to our tests. loadFixture() inserts the fixture markup into the DOM for use by code that accesses the DOM. readFixture() returns fixture content as text; we use it to test our ajax callback methods.

  • Within the same test run, we cache fixture text in javascript to avoid multiple requests to the server for the same markup. Across test runs, we ensure our markup is fresh by appending a cache busting timestamp to our request path.

Ready to test!

Here’s how we typically use loadFixture() within our Jasmine tests:

describe('the status module', function() {
  it('switches tabs', function() {
    spec.loadFixture('workspace-page');
    var $tabContainer = $('#jasmine_content').find('.tab-container');
    expect($tabContainer).toHaveSelectedTab('team');
    $tabContainer.find('li[tab=schedule]').click();
    expect($tabContainer).toHaveSelectedTab('schedule');
  });
});

loadFixture() inserts markup into the #jasmine_content div. Then we examine the DOM, do stuff to it, and inspect it again. toHaveSelectedTab() is a custom Jasmine matcher. Jasmine matchers are super easy to write. We love them.

You may be wondering how we’ve established our event bindings. jQuery’s html() method, used within loadFixture(), executes any scripts in the markup passed to it. If you’ve bound events in your fixture markup, within a $(document).ready() or not, they will execute when you call loadFixture(). This is really nice, because it means the same mechanism used for binding events in real life is also used within tests, keeping our tests that much closer to reality.

If, on the other hand, you bind events not within fixture markup, but instead within a script loaded once per suite globally, you’ll have to invoke your event binding code explicitly before each test.

Speaking of event bindings, you’ll need to clean them up properly between tests. For example, jQuery live events are bound to document. We clear them in a global beforeEach():

beforeEach(function() {
  $('#jasmine_content').empty();
  spec.clearLiveEventBindings();
  jasmine.Clock.useMock();
});

spec.clearLiveEventBindings = function() {
  var events = jQuery.data(document, "events");
  for (prop in events) {
    delete events[prop];
  }
};

Any events bound on elements within #jasmine_content are cleared out by jQuery when we call $('#jasmine_content').empty(), which also wipes the DOM clean between our test runs.

Results

Managing html fixtures like this has been a big win. In a recent team retrospective, consensus was “I can’t imagine doing it any other way.”

Building fixtures for tests is often simple as writing a 5-line controller spec. Maintaining fixtures just means re-running the specs, or perhaps enhancing the specs with additional data. We don’t see any production bugs from fixture markup vs. real markup discrepancies, and we spend very little time dealing with the fixtures.

We sometimes forget to re-generate fixtures after we change our markup, but, by now, realizing our mistake is a reflex action.

Test speed was one of our concerns going into this. Loading the fixtures takes time, of course. In practice, the runtime hit is dwarfed by the time saved by automating fixtures.

We have 224 javascript tests, and 200 of them load an html fixture. Our suite runs in 38 seconds in Chrome on a 2.4 GHz Core 2 iMac. (Other browsers are considerably slower). Of that 38 seconds, 9 seconds are spent loading fixtures and re-binding events.

We end up running our tests on fairly large DOM. We could probably save some running time by more narrowly focusing the markup that we generate and load. However, we haven’t felt it worth the additional development overhead. Additionally, running tests on our full DOM has an advantage – it exposes event handlers that conflict with each other.

Other gotchas

Nested describes are another great feature of Jasmine. It can be difficult, though, to keep track of where you’ve called loadFixture() within your hierarchy of describes. We sometimes found that we were calling loadFixure() twice in the same spec. To prevent that, we now keep track of how many times loadFixture() is called within a single test, and fail the test if the count exceeds 1.

At one point, we noticed that our javascript suite was consuming hundreds of megabytes of memory as it executed. We traced the problem to two jQuery plugins. Each time we loaded a fixture, the plugins claimed memory that never got freed. Now we mock out the plugins where we’re not explicitly testing them.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (783)
  • rails (117)
  • testing (90)
  • ruby (86)
  • ruby on rails (71)
  • jobs (62)
  • javascript (59)
  • techtalk (44)
  • ironblogger (42)
  • rspec (39)
  • bloggerdome (34)
  • productivity (34)
  • activerecord (30)
  • rubymine (30)
  • git (29)
  • gogaruco (29)
  • nyc (27)
  • design (24)
  • mobile (23)
  • pivotal tracker (22)
  • process (21)
  • cucumber (21)
  • jasmine (19)
  • ios (18)
  • tracker ecosystem (17)
  • webos (17)
  • objective-c (17)
  • fun (16)
  • android (16)
  • palm (16)
  • ci (16)
  • "soft" ware (16)
  • bdd (15)
  • tdd (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • css (14)
  • gem (13)
  • mouse-free development (12)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • api (12)
  • keyboard (11)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
Subscribe to jasmine Feed
  1. ←
  2. 1
  3. 2
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >