Unlike normal Rails Application Templates or more modern Rails application generators like Rails Composer, the HolyGrailHarness is a basic Rails application that can be considered a prototype and customized via a simple setup script. It is also somewhat opinionated in that it promotes simple and powerful testing choices and focuses on using Ruby 1.9 and up, MiniTest::Spec, Capybara, Poltergeist/PhantomJS, and Konacha. More details on each component and what HolyGrailHarness provides are below.
The HolyGrailHarness is perfect for any of the following:
- Bootstrapping your next Rails application.
- Learning and promoting MiniTest::Spec
- Download the project.
- Now from the root of “holy_grail_harness” directory.
Make sure to replace
my_app_name above with the name of your new Rails application. The setup script has a few options, but the end result will be a new Rails application all ready to go. So why not a normal Rails application template? Although, Rails application templates provide a really nice feature set. It was much easier to bootstrap a new Rails application using this prototype method. The end result is a cleaner Gemfile and application setup that can be vetted and tested from within HolyGrailHarness itself.
The script will rename your directory and prompt you to
cd to that directory. Once you do that, run
rake test:all to see that everything is working.
This application prototype will focus on the latest Rails version. At this time, the bundle is locked down to v3.2.9. As Rails updates and is compatible with each component, so will this prototype application be updated. The bundle includes:
- QuietAssets gem for silent pipeline logging.
- Thin webserver. Primarily to be automatically used by Konacha but also good for development if you are not using something like Pow.
MiniTest::Spec All The Way Across The Sky!
Don’t wait for Rails 4 to use MiniTest::Spec! This application is using the minitest-spec-rails gem which forces
ActiveSupport::TestCase to subclass
MiniTest::Spec. This means that you can start using the MiniTest’s Spec or Unit structure and assertions directly within the familiar Rails unit, functional, or integration directories. For full details, check out the minitest-spec-rails documentation or some of the test shims within HolyGrailHarness. For example, a
test/unit/user_test.rb might look like this.
1 2 3 4 5 6 7 8 9 10 11 12 13
Capybara Integration Tests With Poltergeist Using PhantomJS
You don’t need Cucumber to write good integration tests. Instead use the basic Capybara DSL directly within a Rails integration tests with the most bad ass driver available, Poltergeist, which is built on top of PhantomJS. Never again worry about installing Qt so you can compile capybara-webkit, just go download a pre-compiled PhantomJS binary for your specific platform and enjoy 20% faster integration test runs vs capybara-webkit.
Integration tests are still within the
ActionDispatch::IntegrationTest class and as promised, MiniTest::Spec is available here too. Each test file needs to require the test_helper_integration which provides the following base features.
- Sets page size to that of a 13” MacBook Air.
- Resets Capybara sessions after each test.
- Provides a
#page!for short, screen shot method.
- Ensures a single ActiveRecord DB connection for transactional test runs.
HolyGrailHarness comes with a integration test example in the test/integration/application_test.rb file. An integration test might look something like this.
1 2 3 4 5 6 7 8 9 10 11 12 13
<iframe> for each test spec to run within as well as full Rails asset pipeline integration. The HolyGrailHarness does all the work to get your Konacha
- An initializer that sets up Poltergeist as the Capybara driver.
- A directory structure for model, view, and controller specs.
spec_helper.js.coffeefor your specs to require. Provides global setup, configurations and vendor requires.
HolyGrailHarness also has a
fixtures.js.coffee file that demonstrates how to setup JSON data fixtures for use from anything to stubbing requests to instantiating new model objects. We also have a
- Sinon.JS - For spies, stubs, faking time, etc.
- jQuery Mockjax - Best way to mock jQuery’s AJAX functions.
- Chai jQuery - Chai assertions for jQuery.
- jsDump - Used by the
Because your CI system should run all your tests, the HolyGrailHarness has added a Rake task to the test namespace that runs the default rails test task (units, functional, integrations) then your Konacha tests.
TDD in style and run your tests when you hit save! Both guard-minitest and guard-konacha are bundled and ready to go. A basic
Guardfile is already setup too. Unlike most, this one is split into two groups
:js. This lets you focus on either everything or a specific language for your tests.
1 2 3
The Guardfile assumes you are running OS X and wish to use the Ruby GNTP (Growl Notification Transport Protocol). If this is not the case, consult the Guard documentation on different system notification alternatives.
Factories And Fixtures
ActiveRecord YAML fixtures suck, but so do slow tests that rely on an empty database with excessive setups based on factories. The answer? Take advantage of the best each has to offer. Use factories to populate fixtures into the test database while leveraging database transactions during your test runs. The end result is a known factory story with the ability to create more test data as needed using the same factories. Allowing factories to properly hook into model logic means no more decomposing business logic into YAML text files. How?
The HolyGrailHarness bundles the named_seeds gem along with the factory_girl gem. The NamedSeeds library checks for the existence of a
db/test/seeds.rb file and if present, loads that file. Just like Rails’ own
db/seeds.rb anything in this file goes. The only difference is that this seed file is populated right before you tests are run so they persist between transactions. You also get the benefit of using this same seed data in development as part of the normal Rails
db:setup process. Read the full documentationn on their site on how to use it. Below is a brief example.
Create factories in the
test/factories directory. Note, factories are best when they make
valid garbage™, so the HolyGrailHarness also requires the forgery gem to help with that.
1 2 3 4 5 6 7 8 9 10 11 12
When making seed data, be explicit with your attributes that may be forged in the factory, database seeds should be consistent and have meaningful attributes. In this example we are creating an admin user. Note too how we are using
NamedSeeds.identify which mimics AcctiveRecord’s fixture identity. This gives us a handle to the fixture within our tests. We also create the
@admin instance variable because we might want to use that user later on in the fixture story.
1 2 3 4 5 6 7 8
Lastly, in your
test/test_helper.rb file, declare that you have a named seed to the users model. This will allow your tests to act just like those with ActiveRecord fixtures and use the
users(:admin) helper to get to that seeded fixture.
1 2 3 4 5 6 7
application.js file requires all vendor frameworks, then the
By default the
index.js.coffee will require all Spine components. This includes manager (stacks), ajax, route, and relation. Remove anything that you do not need. This file also defines the root view controller along with a
MyAppName.App.Index.init() class level initialization function. This is called in the main
application.html.erb layout file for you too. Likewise, the application init is done in the Mocha before filters mentioned above in both the
fixtures.js.coffee files. If you examine these files closely, you will see how they make use of Mocha’s
1 2 3 4 5
notifications.js.coffee that exposes a class level
trigger() to any event string/namespace you want. To make more simple, we recommend creating class level functions that expose the event name as the function name and pass the args to the
handle() function. We have done this for the
MyAppName.Notifications.appReady() to demonstrate. Calling this function will trigger the
app.ready event and passing a function to this function will bind that function to the same event name.
Sass & Compass
Sass is the only way to write CSS for today’s modern web applications. Compass is the CSS framework that no Sass user should go without. Together they provide a foundation for writing beautiful CSS using pre-built time saving functions. The HolyGrailHarness includes both the sass-rails and compass-rails gems.
To get you started on the right path, we have also created a basic structure within the
app/assets/stylesheets asset pipeline directory to help you organize your Sass files. Here is the directory structure below.
1 2 3 4 5 6 7 8 9 10 11 12 13
The application.css file.
Never write CSS in
application.css. Say what? I know right, but trust me. Just consider this file a top level bundle dependency that only requires other top level bundle assets. Here is the contents of that file. Notice how it requires a bundle called twitter and an index. One is for twitter bootstrap, see section below, and the other is the index to your own Sass framework.
1 2 3 4
The shared directory.
Think of this as your own Compass framework. The
base.scss is your single file to
@import to get everything loaded and ready to go. Nothing in any of the shared files should generate CSS! Importing
shared/base should act just like importing
compass. Use these files for setting your own variables and creating misc helper functions & mixins. There is a variables file for… variables! Another for animations, fonts and mixins too.
Pay special attention to the
_placeholders.scss file. If you do not know about Sass 3.2’s placeholder selectors (silent classes) and how they make presentational classes efficiently extended by semantic ones, then I highly suggest you read Dale Sande’s presentation titled Sass 3.2 Silent Classes on Speaker Deck.
Below is the contents of the
base.scss file, take note of the order. See too how we import the entire Compass framework. This means that all of your Sass code in any of the shared files can take full advantage of both Bootstrap and Compass’ variables and mixins. Epic win!
1 2 3 4 5 6 7 8 9 10 11
The application directory.
Organize this as you see fit. We have started you off by creating a
_layout.scss file for your general layout/structure styles. There is also a
components directory which all sub files are imported via a glob. The idea is that components are not dependent upon another. Files that might go in here are things like datepicker, navigation, and general files named after components or widgets. Below is what the
application/index.scss looks like.
1 2 3
If you are more advanced with your CSS and like the idea of style guides, take a looks a the Toadstool style guide framework.
Twitter Bootstrap is awesome, but LESS is not. That is why the HolyGrailHarness uses the bootstrap-sass gem that converts all the Bootstrap LESS files to Sass. Making them ready to import via the Rails asset pipeline.
As shown above in the Sass section, we require the
application/twitter.scss bundle asset from the top level
application.css bundle file. This twitter bundle file, contents below, take advantage of your shared variables before importing bootstrap from the gem. In this way you can define variables that tweak bootstrap. A good example would be button colors, column widths, etc. Later on in the file you can extend bootstrap styles to your liking. For instance, add more padding to buttons.
1 2 3 4 5
The glyph icons included in Twitter Bootstrap are horrible for hi-resolution “retina” displays typically found on mobile devices. Thankfully the Font Awesome project provides a drop in replacement that instead uses icon fonts vs raster images.
The HolyGrailHarness vendors these font files and the needed
font-awesome.scss file and requires them as part of the Twitter Bootstrap bundle shown above. More advanced users may prefer to only include the icon fonts needed in their application or a few custom icons. If that is the case, check out Font Custom, webfonts from the comfort of the command line.