15 Rails In Depth 14.4 Integration Testing of Applications
mkdir test/fixtures/performance/
edit test/fixtures/performance/products.yml
<% 1.upto(1000) do |i| %>
product_<%= i %>:
id: <%= i %>
title: Product Number <%= i %>
description: My description
image_url: product.gif
price: 1234
<% end %>
edit test/performance/order_speed_test.rb
require 'test_helper'
require 'store_controller'
class OrderSpeedTest < ActionController::TestCase
tests StoreController
DAVES_DETAILS = {
:name => "Dave Thomas",
:address => "123 The Street",
:email => "dave@example.com",
:pay_type => "check"
}
self.fixture_path = File.join(File.dirname(__FILE__), "../fixtures/performance")
fixtures :products
def test_100_orders
Order.delete_all
LineItem.delete_all
@controller.logger.silence do
elapsed_time = Benchmark.realtime do
100.downto(1) do |prd_id|
cart = Cart.new
cart.add_product(Product.find(prd_id))
post :save_order,
{ :order => DAVES_DETAILS },
{ :cart => cart }
assert_redirected_to :action => :index
end
end
assert_equal 100, Order.count
assert elapsed_time < 3.00
end
end
end
ruby -I test test/performance/order_speed_test.rb
Loaded suite test/performance/order_speed_test
Started
E
Error:
test_100_orders(OrderSpeedTest):
FixturesFileNotFound: Could not find test/performance/../fixtures/performance/orders.yml or test/performance/../fixtures/performance/orders.csv
Finished in 0.075971554 seconds.
1 tests, 0 assertions, 0 failures, 1 errors, 0 pendings, 0 omissions, 0 notifications
0% passed
13.16 tests/s, 0.00 assertions/s
edit app/models/user.rb
require 'digest/sha1'
class User < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :name
attr_accessor :password_confirmation
validates_confirmation_of :password
validate :password_non_blank
def self.authenticate(name, password)
user = self.find_by_name(name)
if user
expected_password = encrypted_password(password, user.salt)
if user.hashed_password != expected_password
user = nil
end
end
user
end
# 'password' is a virtual attribute
def password
@password
end
def password=(pwd)
@password = pwd
return if pwd.blank?
create_new_salt
self.hashed_password = User.encrypted_password(self.password, self.salt)
end
after_destroy :ensure_an_admin_remains
def ensure_an_admin_remains
if User.count.zero?
raise "Can't delete last user"
end
end
private
def password_non_blank
errors.add(:password, "Missing password") if hashed_password.blank?
end
def create_new_salt
self.salt = self.object_id.to_s + rand.to_s
end
def self.encrypted_password(password, salt)
100000.times { Math.sin(1)}
string_to_hash = password + "wibble" + salt
Digest::SHA1.hexdigest(string_to_hash)
end
end
rails benchmarker "User.encrypted_password(\"secret\", \"salt\")"
user system total real
#1 0.160000 0.020000 0.180000 ( 0.199111)
rails profiler "User.encrypted_password(\"secret\", \"salt\")"
Using the standard Ruby profiler.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
43.02 2.25 2.25 1 2250.00 5150.00 Integer#times
38.24 4.25 2.00 100000 0.02 0.03 Math.sin
17.21 5.15 0.90 100000 0.01 0.01 Fixnum#to_f
0.76 5.19 0.04 24 1.67 1.67 Kernel.respond_to?
0.19 5.20 0.01 2 5.00 45.00 ActiveSupport::Dependencies.new_constants_in
0.19 5.21 0.01 11 0.91 0.91 ActiveSupport::Callbacks::Callback#start
0.19 5.22 0.01 6 1.67 1.67 Hash#extractable_options?
0.19 5.23 0.01 897 0.01 0.01 Symbol#to_s
0.00 5.23 0.00 1 0.00 0.00 String#intern
0.00 5.23 0.00 11 0.00 0.00 Array#first
0.00 5.23 0.00 6 0.00 0.00 String#empty?
0.00 5.23 0.00 13 0.00 0.00 Module#const_defined?
0.00 5.23 0.00 12 0.00 0.00 Module#const_get
0.00 5.23 0.00 49 0.00 3.27 Array#each
0.00 5.23 0.00 6 0.00 0.00 ActiveSupport::Inflector.constantize
0.00 5.23 0.00 9 0.00 0.00 ActiveSupport::Dependencies.logger
0.00 5.23 0.00 5 0.00 0.00 ActiveSupport::Dependencies.log_call
0.00 5.23 0.00 6 0.00 0.00 String#sub
0.00 5.23 0.00 7 0.00 0.00 ActiveSupport::Dependencies.local_const_defined?
0.00 5.23 0.00 11 0.00 0.00 Enumerable.inject
0.00 5.23 0.00 5 0.00 0.00 ActiveSupport::Dependencies.qualified_const_defined?
0.00 5.23 0.00 2 0.00 0.00 BasicObject#equal?
0.00 5.23 0.00 29 0.00 0.00 Module#===
0.00 5.23 0.00 3 0.00 0.00 String#=~
0.00 5.23 0.00 3 0.00 0.00 Kernel.!~
0.00 5.23 0.00 3 0.00 0.00 String#blank?
0.00 5.23 0.00 3 0.00 0.00 ActiveSupport::Dependencies.to_constant_name
0.00 5.23 0.00 5 0.00 0.00 Module#name
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.qualified_name_for
0.00 5.23 0.00 1 0.00 0.00 String#initialize_copy
0.00 5.23 0.00 17 0.00 0.00 Kernel.initialize_dup
0.00 5.23 0.00 13 0.00 0.00 Kernel.dup
0.00 5.23 0.00 3 0.00 0.00 String#gsub!
0.00 5.23 0.00 1 0.00 0.00 String#tr!
0.00 5.23 0.00 1 0.00 0.00 String#downcase!
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Inflector.underscore
0.00 5.23 0.00 1 0.00 0.00 String#underscore
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::Dependencies.autoload_paths
0.00 5.23 0.00 3 0.00 0.00 File#join
0.00 5.23 0.00 3 0.00 0.00 File#file?
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.search_for_file
0.00 5.23 0.00 3 0.00 0.00 ActiveSupport::Dependencies.loaded
0.00 5.23 0.00 7 0.00 0.00 File#expand_path
0.00 5.23 0.00 2 0.00 0.00 Hash#include?
0.00 5.23 0.00 2 0.00 0.00 Set#include?
0.00 5.23 0.00 32 0.00 0.00 Hash#[]=
0.00 5.23 0.00 2 0.00 0.00 Set#add
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::Dependencies.mechanism
0.00 5.23 0.00 503 0.00 0.00 Symbol#==
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::Dependencies.load?
0.00 5.23 0.00 4 0.00 0.00 ActiveSupport::Dependencies.log
0.00 5.23 0.00 21 0.00 0.00 NilClass#nil?
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.warnings_on_first_load
0.00 5.23 0.00 4 0.00 0.00 Regexp#escape
0.00 5.23 0.00 4 0.00 0.00 Regexp#=~
0.00 5.23 0.00 3 0.00 0.00 String#[]
0.00 5.23 0.00 2 0.00 0.00 String#gsub
0.00 5.23 0.00 1 0.00 0.00 String#upcase
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Inflector.camelize
0.00 5.23 0.00 1 0.00 0.00 String#camelize
0.00 5.23 0.00 2 0.00 0.00 Array#uniq!
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.loadable_constants_for_path
0.00 5.23 0.00 22 0.00 0.00 Kernel.is_a?
0.00 5.23 0.00 1 0.00 0.00 Array#collect
0.00 5.23 0.00 4 0.00 0.00 ActiveSupport::Dependencies.constant_watch_stack
0.00 5.23 0.00 4 0.00 0.00 Module#constants
0.00 5.23 0.00 4 0.00 0.00 Module#local_constants
0.00 5.23 0.00 16 0.00 1.25 Array#map
0.00 5.23 0.00 4 0.00 2.50 Module#local_constant_names
0.00 5.23 0.00 8 0.00 0.00 Hash#[]
0.00 5.23 0.00 2 0.00 5.00 ActiveSupport::Dependencies::WatchStack#watch_namespaces
0.00 5.23 0.00 2 0.00 0.00 IO#set_encoding
0.00 5.23 0.00 132 0.00 0.00 Hash#default
0.00 5.23 0.00 1 0.00 0.00 Kernel.require
0.00 5.23 0.00 26 0.00 0.00 Array#last
0.00 5.23 0.00 3 0.00 0.00 Array#-
0.00 5.23 0.00 6 0.00 0.00 Array#concat
0.00 5.23 0.00 15 0.00 0.00 Array#pop
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::Dependencies::WatchStack#pop_modules
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::Dependencies::WatchStack#new_constants
0.00 5.23 0.00 3 0.00 0.00 Array#*
0.00 5.23 0.00 11 0.00 0.00 String#split
0.00 5.23 0.00 1 0.00 0.00 Array#blank?
0.00 5.23 0.00 1 0.00 10.00 ActiveSupport::Dependencies::Loadable.load_dependency
0.00 5.23 0.00 1 0.00 10.00 ActiveSupport::Dependencies::Loadable.require
0.00 5.23 0.00 11 0.00 0.00 Hash#initialize_copy
0.00 5.23 0.00 2 0.00 0.00 Hash#each
0.00 5.23 0.00 1 0.00 0.00 Kernel.singleton_class
0.00 5.23 0.00 1 0.00 0.00 Exception#initialize
0.00 5.23 0.00 1 0.00 0.00 NameError#initialize
0.00 5.23 0.00 1 0.00 0.00 Exception#exception
0.00 5.23 0.00 1 0.00 0.00 Exception#backtrace
0.00 5.23 0.00 1 0.00 0.00 Exception#set_backtrace
0.00 5.23 0.00 1 0.00 0.00 Module#remove_method
0.00 5.23 0.00 1 0.00 0.00 Module#remove_possible_method
0.00 5.23 0.00 3 0.00 0.00 BasicObject#singleton_method_added
0.00 5.23 0.00 4 0.00 0.00 Module#define_method
0.00 5.23 0.00 14 0.00 0.00 Module#class_eval
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::Base#_validators=
0.00 5.23 0.00 7 0.00 0.00 Kernel.hash
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::DescendantsTracker.direct_descendants
0.00 5.23 0.00 3 0.00 0.00 Regexp#===
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::DynamicFinderMatch#match
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::DynamicScopeMatch#match
0.00 5.23 0.00 20 0.00 0.00 Kernel.respond_to_missing?
0.00 5.23 0.00 1 0.00 0.00 String#scan
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::Base#respond_to?
0.00 5.23 0.00 2 0.00 0.00 Class#inheritable_attributes
0.00 5.23 0.00 6 0.00 0.00 Object#duplicable?
0.00 5.23 0.00 5 0.00 0.00 Array#initialize_copy
0.00 5.23 0.00 5 0.00 0.00 Hash#update
0.00 5.23 0.00 1 0.00 0.00 TrueClass#duplicable?
0.00 5.23 0.00 1 0.00 0.00 Kernel.instance_variable_set
0.00 5.23 0.00 1 0.00 0.00 Class#inherited_with_inheritable_attributes
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::DescendantsTracker.inherited
0.00 5.23 0.00 1 0.00 0.00 ActiveModel::Validations::ClassMethods.inherited
0.00 5.23 0.00 1 0.00 0.00 ActiveModel::Observing::ClassMethods.notify_observers
0.00 5.23 0.00 1 0.00 0.00 ActiveModel::Observing::ClassMethods.inherited
0.00 5.23 0.00 2 0.00 0.00 WillPaginate::PerPage.per_page
0.00 5.23 0.00 1 0.00 0.00 Integer#to_i
0.00 5.23 0.00 1 0.00 0.00 WillPaginate::PerPage.per_page=
0.00 5.23 0.00 1 0.00 0.00 WillPaginate::PerPage::Inheritance.inherited
0.00 5.23 0.00 11 0.00 0.91 Array#extract_options!
0.00 5.23 0.00 4 0.00 0.00 Array#flatten
0.00 5.23 0.00 4 0.00 0.00 Hash#merge
0.00 5.23 0.00 3 0.00 0.00 ActiveModel::Validations::HelperMethods._merge_attributes
0.00 5.23 0.00 6 0.00 0.00 Kernel.instance_of?
0.00 5.23 0.00 2 0.00 0.00 Array#unshift
0.00 5.23 0.00 8 0.00 0.00 Hash#delete
0.00 5.23 0.00 10 0.00 0.00 Kernel.nil?
0.00 5.23 0.00 5 0.00 0.00 Array#to_ary
0.00 5.23 0.00 28 0.00 1.43 Array#wrap
0.00 5.23 0.00 3 0.00 0.00 Kernel.freeze
0.00 5.23 0.00 3 0.00 0.00 ActiveModel::Validator#initialize
0.00 5.23 0.00 3 0.00 0.00 ActiveModel::EachValidator#check_validity!
0.00 5.23 0.00 3 0.00 13.33 ActiveModel::EachValidator#initialize
0.00 5.23 0.00 8 0.00 5.00 Class#new
0.00 5.23 0.00 26 0.00 0.00 Symbol#to_sym
0.00 5.23 0.00 3 0.00 0.00 Proc#yield
0.00 5.23 0.00 4 0.00 0.00 Hash#key?
0.00 5.23 0.00 28 0.00 0.00 Array#include?
0.00 5.23 0.00 5 0.00 0.00 ActiveSupport::DescendantsTracker.descendants
0.00 5.23 0.00 12 0.00 0.00 Kernel.object_id
0.00 5.23 0.00 2 0.00 0.00 Class#superclass
0.00 5.23 0.00 9 0.00 0.00 ActiveRecord::Base#_validate_callbacks
0.00 5.23 0.00 5 0.00 0.00 ActiveSupport::Callbacks::Callback#normalize_options!
0.00 5.23 0.00 12 0.00 0.00 ActiveSupport::Callbacks::Callback#next_id
0.00 5.23 0.00 12 0.00 0.00 Fixnum#to_s
0.00 5.23 0.00 23 0.00 0.00 Object#blank_slate_method_added
0.00 5.23 0.00 23 0.00 0.00 Object#method_added
0.00 5.23 0.00 23 0.00 0.00 ActiveRecord::Callbacks::ClassMethods.method_added
0.00 5.23 0.00 3 0.00 0.00 ActiveSupport::Callbacks::Callback#_normalize_legacy_filter
0.00 5.23 0.00 3 0.00 0.00 ActiveSupport::Callbacks::Callback#name
0.00 5.23 0.00 21 0.00 0.00 Array#join
0.00 5.23 0.00 7 0.00 0.00 ActiveSupport::Callbacks::Callback#_compile_filter
0.00 5.23 0.00 10 0.00 0.00 ActiveSupport::Callbacks::Callback#_compile_options
0.00 5.23 0.00 5 0.00 0.00 NilClass#to_s
0.00 5.23 0.00 5 0.00 0.00 ActiveSupport::Callbacks::Callback#_compile_per_key_options
0.00 5.23 0.00 5 0.00 0.00 ActiveSupport::Callbacks::Callback#initialize
0.00 5.23 0.00 5 0.00 0.00 Array#delete_if
0.00 5.23 0.00 4 0.00 0.00 Array#push
0.00 5.23 0.00 17 0.00 0.00 Array#compact
0.00 5.23 0.00 8 0.00 0.00 String#to_s
0.00 5.23 0.00 11 0.00 0.00 ActiveSupport::Callbacks::Callback#end
0.00 5.23 0.00 5 0.00 0.00 Array#reverse_each
0.00 5.23 0.00 5 0.00 2.00 ActiveSupport::Callbacks::CallbackChain#compile
0.00 5.23 0.00 6 0.00 0.00 Module#method_defined?
0.00 5.23 0.00 6 0.00 0.00 Module#private
0.00 5.23 0.00 5 0.00 0.00 Kernel.with_warnings
0.00 5.23 0.00 5 0.00 0.00 Kernel.silence_warnings
0.00 5.23 0.00 5 0.00 2.00 ActiveSupport::Callbacks::ClassMethods.__define_runner
0.00 5.23 0.00 5 0.00 2.00 ActiveSupport::Callbacks::ClassMethods.__update_callbacks
0.00 5.23 0.00 5 0.00 2.00 ActiveSupport::Callbacks::ClassMethods.set_callback
0.00 5.23 0.00 4 0.00 5.00 ActiveModel::Validations::ClassMethods.validate
0.00 5.23 0.00 3 0.00 20.00 ActiveModel::Validations::ClassMethods.validates_with
0.00 5.23 0.00 1 0.00 10.00 ActiveModel::Validations::HelperMethods.validates_presence_of
0.00 5.23 0.00 1 0.00 0.00 Hash#reverse_merge
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::Validations::UniquenessValidator#initialize
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::Validations::UniquenessValidator#setup
0.00 5.23 0.00 6 0.00 0.00 String#==
0.00 5.23 0.00 6 0.00 0.00 ActiveSupport::Callbacks::Callback#matches?
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::Validations::ClassMethods.validates_uniqueness_of
0.00 5.23 0.00 2 0.00 0.00 Module#attr_accessor
0.00 5.23 0.00 34 0.00 0.00 Array#empty?
0.00 5.23 0.00 1 0.00 0.00 ActiveModel::Validations::ConfirmationValidator#setup
0.00 5.23 0.00 1 0.00 50.00 ActiveModel::Validations::HelperMethods.validates_confirmation_of
0.00 5.23 0.00 1 0.00 0.00 Array#shift
0.00 5.23 0.00 3 0.00 0.00 ActiveRecord::Base#_destroy_callbacks
0.00 5.23 0.00 1 0.00 0.00 Array#reverse
0.00 5.23 0.00 1 0.00 0.00 ActiveRecord::Base#after_destroy
0.00 5.23 0.00 1 0.00 70.00 Kernel.load
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.autoload_once_paths
0.00 5.23 0.00 1 0.00 0.00 Enumerable.any?
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.load_once_path?
0.00 5.23 0.00 2 0.00 0.00 ActiveSupport::Dependencies.autoloaded_constants
0.00 5.23 0.00 1 0.00 80.00 ActiveSupport::Dependencies.load_file
0.00 5.23 0.00 1 0.00 0.00 ActiveSupport::Dependencies.history
0.00 5.23 0.00 1 0.00 80.00 ActiveSupport::Dependencies.require_or_load
0.00 5.23 0.00 1 0.00 80.00 ActiveSupport::Dependencies.load_missing_constant
0.00 5.23 0.00 4 0.00 0.00 Object#presence
0.00 5.23 0.00 4 0.00 0.00 Object#present?
0.00 5.23 0.00 1 0.00 0.00 NilClass#blank?
0.00 5.23 0.00 1 0.00 0.00 BasicObject#initialize
0.00 5.23 0.00 2 0.00 0.00 Digest::Base#reset
0.00 5.23 0.00 1 0.00 0.00 Digest::Base#update
0.00 5.23 0.00 1 0.00 0.00 Digest::Base#finish
0.00 5.23 0.00 1 0.00 0.00 Digest::Instance.digest
0.00 5.23 0.00 1 0.00 0.00 Digest::Class#digest
0.00 5.23 0.00 1 0.00 0.00 Digest::Class#hexdigest
0.00 5.23 0.00 1 0.00 5150.00 User#encrypted_password
0.00 5.23 0.00 1 0.00 5230.00 Object#profile_me
0.00 5.23 0.00 1 0.00 5230.00 #toplevel
edit app/models/user.rb