Comments
yourfanat wrote: I am using another tool for Oracle developers - dbForge Studio for Oracle. This IDE has lots of usefull features, among them: oracle designer, code competion and formatter, query builder, debugger, profiler, erxport/import, reports and many others. The latest version supports Oracle 12C. More information here.
Cloud Expo on Google News
SYS-CON.TV
Cloud Expo & Virtualization 2009 East
PLATINUM SPONSORS:
IBM
Smarter Business Solutions Through Dynamic Infrastructure
IBM
Smarter Insights: How the CIO Becomes a Hero Again
Microsoft
Windows Azure
GOLD SPONSORS:
Appsense
Why VDI?
CA
Maximizing the Business Value of Virtualization in Enterprise and Cloud Computing Environments
ExactTarget
Messaging in the Cloud - Email, SMS and Voice
Freedom OSS
Stairway to the Cloud
Sun
Sun's Incubation Platform: Helping Startups Serve the Enterprise
POWER PANELS:
Cloud Computing & Enterprise IT: Cost & Operational Benefits
How and Why is a Flexible IT Infrastructure the Key To the Future?
Click For 2008 West
Event Webcasts
Faster Test Suite Boot Times with Ruby on Rails
Learn how to reduce startup times for your Ruby on Rails test suite. We talk about dependencies, stubs and factories.

Let's jump into an example. We're assuming you're using the following, simplified, Gemfile for your dependencies:

gem "rails"
gem "bcrypt"
gem "foreman"
gem "thin"
gem "newrelic_rpm"
gem "airbrake"

First we stop loading gems which aren't used in the code.

gem "rails"
gem "bcrypt"
gem "foreman", require: false
gem "thin", require: false
gem "newrelic_rpm"
gem "airbrake"

Then we make sure dependencies are only specified for the environments where they're used in.

gem "rails"
gem "bcrypt"

group :development do
  gem "foreman", require: false
end

group :production do
  gem "thin", require: false
  gem "newrelic_rpm"
  gem "airbrake"
end

At this point you might start getting undefined constant errors about Airbrake. You can decide to either move Airbrake back into all environments or stub its implementation.

We generally do this by defining the module or class ourselves from a support file in the test directory, like so:

module Airbrake
    extend self
    def notify(exception, opts = {})
    end
  end

Partial example of a stub implementation for Airbrake.

On the one hand you probably never want to send data from your test suite to Airbrake. On the other hand some people are more comfortable running their entire production stack in at least one or two tests.

Reduce time spent setting up tests
Basically you need to do less. There are a few strategies to accomplish this.

One strategy is moving setup code as local to your test as possible so it only runs for the tests where it's needed. For example, don't run setup methods specific for functional tests in unit test.

Keep in mind that your test_helper.rb or spec_helper.rb is loaded during every boot. Try to limit slow operations in this file.

Tests that require long setup tasks sometimes need to be run in a variety of contexts: library tests, model tests, and functional tests. Sometimes you can cheat a little bit and test through the entire stack in one massive integration test.

Another strategy is to perform long setup tasks only once and find a way to cache the result to speed up next runs.

In one of our applications we process YAML files with questionnaire definitions and create records for them in the database. In hindsight we should have never done this, but that's a discussion for another day.

In unit and functional tests we use fixtures to test specific situations. For regression tests we need the production definitions. We speed up loading these by dumping the database tables with INTO OUTFILE and load them with LOAD DATA INFILE. We also hook into Rails fixture loading code so it only happens once for the entire suite.

Finally, never, ever, ever, ever, call external services from your tests. Not only is this slow, but it might accidentally erase production data. In most tests we override Net::HTTP#startto make sure it's never called by accident.

Factories or fixtures
There is a lot to say about database setup, so it deserves its own little chapter.

Let's get the elephant out of the room first. Factories are slow! They're slow by design.

Factories can be used to create database records anywhere in your test suite. This makes them pretty flexible and allows you to keep your test data local to your tests. The drawback is that it makes them almost impossible to speed up in any significant way.

We can understand why factories are slow by looking at why ActiveRecord fixtures are fast.

Fixtures are bulk loaded once. A transaction is created in the database when a test starts. After the test the database is rolled back to its initial state. This means the fixtures don't have to be reloaded for each test.

Most factory implementations start a test with an empty database and run through all the factories needed for a test each time it's run. After the test the database is reset to its blank state by removing all records. On top of that records are created through ActiveRecord model instances, which creates a lot of objects in the Ruby VM, which need to be garbage collected.

We try to use fixtures as much as possible. We write little scenarios with them to make tests easier to understand. Paul might be a pro account holder who has paid his bills the last two years, but unfortunately missed a payment this month because his credit card expired.

Using small scenarios like this reduce the chance of someone messing up tests by using the wrong fixture or changing fixtures to not fit their intended scenario. You can even document these scenarios shortly in the fixture files or test helper.

Use a fast test framework

Your test framework needs to be loaded and initialized during every boot.

RSpec is notoriously slow. If you're willing to part with it, you might want to consider minitest/spec. You can use minitest/spec with Rails out of the box since version 4.0. Another alternative is Peck on Rails.

In doubt, measure!

Optimizations don't really make sense when you can't measure the speedups. Most test frameworks print their runtimes, but this doesn't include boot time. The time tool is your friend.

$ time ruby test/unit/post_test.rb
Loaded suite test/unit/post_test
Started
..
Finished in 0.001313 seconds.

2 tests, 6 assertions, 0 failures, 0 errors
ruby test/unit/post_test.rb  0.15s user 0.08s system 96% cpu 0.238 total

In this example test/unit reports 0.001313 seconds, but the real runtime is 0.238.

To measure particular parts of your code you can either use a profiler or the Benchmark class.

Isolate the slow code and keep the benchmark in place to measure if your fix actually helps.

About Manuel Weiss
I am the cofounder of Codeship – a hosted Continuous Integration and Deployment platform for web applications. On the Codeship blog we love to write about Software Testing, Continuos Integration and Deployment. Also check out our weekly screencast series 'Testing Tuesday'!

Latest Cloud Developer Stories
With more than 30 Kubernetes solutions in the marketplace, it's tempting to think Kubernetes and the vendor ecosystem has solved the problem of operationalizing containers at scale or of automatically managing the elasticity of the underlying infrastructure that these solutions n...
The deluge of IoT sensor data collected from connected devices and the powerful AI required to make that data actionable are giving rise to a hybrid ecosystem in which cloud, on-prem and edge processes become interweaved. Attendees will learn how emerging composable infrastructur...
When building large, cloud-based applications that operate at a high scale, it's important to maintain a high availability and resilience to failures. In order to do that, you must be tolerant of failures, even in light of failures in other areas of your application. "Fly two mis...
Machine learning has taken residence at our cities' cores and now we can finally have "smart cities." Cities are a collection of buildings made to provide the structure and safety necessary for people to function, create and survive. Buildings are a pool of ever-changing performa...
As Cybric's Chief Technology Officer, Mike D. Kail is responsible for the strategic vision and technical direction of the platform. Prior to founding Cybric, Mike was Yahoo's CIO and SVP of Infrastructure, where he led the IT and Data Center functions for the company. He has more...
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021



SYS-CON Featured Whitepapers
ADS BY GOOGLE