From dd737af03e6f626403c87aeae516940bf80535c9 Mon Sep 17 00:00:00 2001 From: Joe Ferris Date: Wed, 9 Jun 2010 11:42:48 -0400 Subject: [PATCH] Added Rails 3 integration --- .gitignore | 6 +++ LICENSE | 19 ++++++++++ README.rdoc | 39 ++++++++++++++++++++ Rakefile | 16 ++++++++ factory_girl_rails.gemspec | 23 ++++++++++++ features/load_definitions.feature | 47 ++++++++++++++++++++++++ features/step_definitions/rails_steps.rb | 32 ++++++++++++++++ features/support/terminal.rb | 36 ++++++++++++++++++ lib/factory_girl_rails.rb | 2 + lib/factory_girl_rails/railtie.rb | 15 ++++++++ 10 files changed, 235 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.rdoc create mode 100644 Rakefile create mode 100644 factory_girl_rails.gemspec create mode 100644 features/load_definitions.feature create mode 100644 features/step_definitions/rails_steps.rb create mode 100644 features/support/terminal.rb create mode 100644 lib/factory_girl_rails.rb create mode 100644 lib/factory_girl_rails/railtie.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc313f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.swp +test.db +factory_girl-*.gem +tmp +rdoc +coverage diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7e98a70 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Joe Ferris and thoughtbot, inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..a50ba6b --- /dev/null +++ b/README.rdoc @@ -0,0 +1,39 @@ += factory_girl + +factory_girl is a fixtures replacement with a straightforward definition +syntax, support for multiple build strategies (saved instances, unsaved +instances, attribute hashes, and stubbed objects), and support for multiple +factories for the same class (user, admin_user, and so on), including factory +inheritance. + +== Rails + +factory_girl_rails provides Rails integration for factory_girl. All +Rails-specific features are only compatible with Rails 3. + +Currenty, automatic factory definition loading is the only Rails-specific feature. + +== Download + +Github: http://github.com/thoughtbot/factory_girl_rails/tree/master + +Gem: + gem install factory_girl_rails + +== Configuration + +Add factory_girl Rails to your Gemfile: + + gem 'factory_girl_rails' + +== More Information + +factory_girl: http://github.com/thoughtbot/factory_girl/tree/master + +== Author + +factory_girl_rails was written by Joe Ferris. + +Thanks to all members of thoughtbot for inspiration, ideas, and funding. + +Copyright 2010 Joe Ferris and thoughtbot[http://www.thoughtbot.com], inc. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..caf838a --- /dev/null +++ b/Rakefile @@ -0,0 +1,16 @@ +require 'rake/gempackagetask' +require 'cucumber/rake/task' + +eval("$specification = #{IO.read('factory_girl_rails.gemspec')}") +Rake::GemPackageTask.new($specification) do |package| + package.need_zip = true + package.need_tar = true +end + +Cucumber::Rake::Task.new(:cucumber) do |t| + t.fork = true + t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')] +end + +desc "Default: run the cucumber scenarios" +task :default => :cucumber diff --git a/factory_girl_rails.gemspec b/factory_girl_rails.gemspec new file mode 100644 index 0000000..baef821 --- /dev/null +++ b/factory_girl_rails.gemspec @@ -0,0 +1,23 @@ +Gem::Specification.new do |s| + s.name = %q{factory_girl_rails} + s.version = '1.0' + s.summary = %q{factory_girl_rails provides integration between + factory_girl and rails 3} + s.description = %q{factory_girl_rails provides integration between + factory_girl and rails 3 (currently just automatic factory definition + loading)} + s.files = Dir['[A-Z]*', 'lib/**/*.rb', 'spec/**/*.rb', 'features/**/*'] + s.require_path = 'lib' + s.test_files = Dir['spec/**/*_spec.rb', 'features/**/*'] + s.authors = ["Joe Ferris"] + s.email = %q{jferris@thoughtbot.com} + s.homepage = "http://thoughtbot.com/projects/factory_girl_rails" + s.add_runtime_dependency('rails', '>= 3.0.0.beta4') + s.add_runtime_dependency('factory_girl', '~> 1.3') + s.add_development_dependency('rake') + s.add_development_dependency('rspec') + s.add_development_dependency('cucumber') + s.platform = Gem::Platform::RUBY + s.rubygems_version = %q{1.2.0} +end + diff --git a/features/load_definitions.feature b/features/load_definitions.feature new file mode 100644 index 0000000..44e9b70 --- /dev/null +++ b/features/load_definitions.feature @@ -0,0 +1,47 @@ +Feature: automatically load step definitions + + Scenario: generate a rails 3 application and use factory definitions + When I generate a new rails application + And I save the following as "Gemfile" + """ + source "http://rubygems.org" + gem 'rails', '3.0.0.beta4' + gem 'sqlite3-ruby', :require => 'sqlite3' + gem 'factory_girl_rails', :path => '../../' + """ + When I run "bundle lock" + And I save the following as "db/migrate/1_create_users.rb" + """ + class CreateUsers < ActiveRecord::Migration + def self.up + create_table :users do |t| + t.string :name + end + end + end + """ + When I run "rake db:migrate" + And I save the following as "app/models/user.rb" + """ + class User < ActiveRecord::Base + end + """ + When I save the following as "test/factories.rb" + """ + Factory.define :user do |user| + user.name 'Frank' + end + """ + When I save the following as "test/unit/user_test.rb" + """ + require 'test_helper' + + class UserTest < ActiveSupport::TestCase + test "use factory" do + user = Factory(:user) + assert_equal 'Frank', user.name + end + end + """ + When I run "rake test" + Then I should see "1 tests, 1 assertions, 0 failures, 0 errors" diff --git a/features/step_definitions/rails_steps.rb b/features/step_definitions/rails_steps.rb new file mode 100644 index 0000000..0ce1f92 --- /dev/null +++ b/features/step_definitions/rails_steps.rb @@ -0,0 +1,32 @@ +PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze +TEMP_ROOT = File.join(PROJECT_ROOT, 'tmp').freeze +APP_NAME = 'testapp'.freeze +RAILS_ROOT = File.join(TEMP_ROOT, APP_NAME).freeze + +Before do + FileUtils.rm_rf(TEMP_ROOT) + FileUtils.mkdir_p(TEMP_ROOT) + @terminal = Terminal.new +end + +When /^I generate a new rails application$/ do + @terminal.cd(TEMP_ROOT) + @terminal.run("rails new #{APP_NAME}") +end + +When /^I save the following as "([^\"]*)"$/ do |path, string| + FileUtils.mkdir_p(File.join(RAILS_ROOT, File.dirname(path))) + File.open(File.join(RAILS_ROOT, path), 'w') { |file| file.write(string) } +end + +When /^I run "([^\"]*)"$/ do |command| + @terminal.cd(RAILS_ROOT) + @terminal.run(command) +end + +Then /^I should see "([^\"]*)"$/ do |expected_text| + unless @terminal.output.include?(expected_text) + raise("Got terminal output:\n#{@terminal.output}\n\nExpected output:\n#{expected_text}") + end +end + diff --git a/features/support/terminal.rb b/features/support/terminal.rb new file mode 100644 index 0000000..c4b5bd0 --- /dev/null +++ b/features/support/terminal.rb @@ -0,0 +1,36 @@ +require 'fileutils' + +class Terminal + attr_reader :output, :status + + def initialize + @cwd = FileUtils.pwd + @output = "" + @status = 0 + @logger = Logger.new(File.join(TEMP_ROOT, 'terminal.log')) + end + + def cd(directory) + @cwd = directory + end + + def run(command) + output << "#{command}\n" + FileUtils.cd(@cwd) do + logger.debug(command) + result = `#{command} 2>&1` + logger.debug(result) + output << result + end + @status = $? + end + + def echo(string) + logger.debug(string) + end + + private + + attr_reader :logger +end + diff --git a/lib/factory_girl_rails.rb b/lib/factory_girl_rails.rb new file mode 100644 index 0000000..aac86d2 --- /dev/null +++ b/lib/factory_girl_rails.rb @@ -0,0 +1,2 @@ +require 'factory_girl_rails/railtie' + diff --git a/lib/factory_girl_rails/railtie.rb b/lib/factory_girl_rails/railtie.rb new file mode 100644 index 0000000..ab0cf31 --- /dev/null +++ b/lib/factory_girl_rails/railtie.rb @@ -0,0 +1,15 @@ +require 'factory_girl' +require 'rails' + +class Factory + class Railtie < Rails::Railtie + config.after_initialize do + Factory.definition_file_paths = [ + File.join(Rails.root, 'test', 'factories'), + File.join(Rails.root, 'spec', 'factories') + ] + Factory.find_definitions + end + end +end +