hyphy 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -1,12 +1,10 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "sequel"
4
- gem "sqlite3"
5
3
  gem "activesupport", "~> 3.2"
4
+ gem "activerecord", "~> 3.2"
6
5
 
7
6
  group :development do
8
7
  gem "bundler"
9
- gem "database_cleaner"
10
8
  gem "jeweler"
11
9
  gem "pry-nav"
12
10
  gem "rdoc"
data/Gemfile.lock CHANGED
@@ -1,16 +1,24 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ activemodel (3.2.14)
5
+ activesupport (= 3.2.14)
6
+ builder (~> 3.0.0)
7
+ activerecord (3.2.14)
8
+ activemodel (= 3.2.14)
9
+ activesupport (= 3.2.14)
10
+ arel (~> 3.0.2)
11
+ tzinfo (~> 0.3.29)
4
12
  activesupport (3.2.14)
5
13
  i18n (~> 0.6, >= 0.6.4)
6
14
  multi_json (~> 1.0)
7
15
  addressable (2.3.5)
8
- builder (3.2.2)
16
+ arel (3.0.2)
17
+ builder (3.0.4)
9
18
  coderay (1.0.9)
10
- database_cleaner (1.0.1)
11
19
  diff-lcs (1.2.4)
12
- faraday (0.8.7)
13
- multipart-post (~> 1.1)
20
+ faraday (0.8.8)
21
+ multipart-post (~> 1.2.0)
14
22
  git (1.2.5)
15
23
  github_api (0.10.1)
16
24
  addressable
@@ -65,25 +73,22 @@ GEM
65
73
  rspec-expectations (2.14.0)
66
74
  diff-lcs (>= 1.1.3, < 2.0)
67
75
  rspec-mocks (2.14.1)
68
- sequel (4.0.0)
69
76
  simplecov (0.7.1)
70
77
  multi_json (~> 1.0)
71
78
  simplecov-html (~> 0.7.1)
72
79
  simplecov-html (0.7.1)
73
- slop (3.4.5)
74
- sqlite3 (1.3.7)
80
+ slop (3.4.6)
81
+ tzinfo (0.3.37)
75
82
 
76
83
  PLATFORMS
77
84
  ruby
78
85
 
79
86
  DEPENDENCIES
87
+ activerecord (~> 3.2)
80
88
  activesupport (~> 3.2)
81
89
  bundler
82
- database_cleaner
83
90
  jeweler
84
91
  pry-nav
85
92
  rdoc
86
93
  rspec
87
- sequel
88
94
  simplecov
89
- sqlite3
data/README.md CHANGED
@@ -1,6 +1,88 @@
1
1
  # Hyphy
2
2
 
3
- Hyphy is a framework for identifying SQL bottlenecks in tests.
3
+ Hyphy is a toolkit for identifying SQL bottlenecks in Ruby applications. Given
4
+ an adapter for an ORM and a Ruby block, Hyphy collects all executed queries in
5
+ a dataset. Afterward, it can filter the dataset and even benchmark the queries.
6
+ At [NationBuilder](http://nationbuilder.com/), we use this gem to conduct
7
+ performance regression tests.
8
+
9
+ ## Supported ORMs
10
+
11
+ Hyphy only comes with out of the box support for ActiveRecord. Adding a new ORM
12
+ should be easy, however.
13
+
14
+ ## Creating datasets
15
+
16
+ You can create a new dataset by initializing a `Sampler` object.
17
+ ```ruby
18
+ require 'hyphy'
19
+ sampler = Hyphy::Sampler.new(:orm => :active_record)
20
+ ```
21
+
22
+ ## Sampling queries
23
+
24
+ Once we've created our `Sampler` object, it is very easy to start collecting data.
25
+ Simply enclose the application code that you need profiled in a block and pass it
26
+ to the `profile` method. Example:
27
+
28
+ ```ruby
29
+ sampler.profile do
30
+ # Application code goes here
31
+ end
32
+ ```
33
+
34
+ ## Filtering queries
35
+
36
+ Hyphy comes with a few filters that fit common use cases. Here is how they can
37
+ be used:
38
+
39
+ ```ruby
40
+ # Only keep SQL 'select' queries
41
+ sampler.apply_filter(Hyphy::Filters::SQLFilter, :type => :select)
42
+
43
+ # Only keep queries that had a running time r such that .01 < r < .05
44
+ sampler.apply_filter(Hyphy::Filters::DurationFilter,
45
+ :duration_min => 0.01,
46
+ :duration_max => 0.05)
47
+
48
+ # Keep the top 10 results
49
+ sampler.apply_filter(Hyphy::Filters::LimitFilter,
50
+ :limit => 10)
51
+
52
+ # Benchmark each query with 10 runs (this saves the benchmark information)
53
+ sampler.apply_filter(Hyphy::Filters::BenchmarkFilter, :runs => 10)
54
+
55
+ # Using the benchmark information, keep queries that fit the
56
+ # duration requirements.
57
+ sampler.apply_filter(Hyphy::Filters::DurationFilter,
58
+ :benchmark => true,
59
+ :duration_min => 0.01,
60
+ :duration_max => 0.05))
61
+ ```
62
+
63
+ ## Accessing data
64
+
65
+ To form reports using the data that remains after filtering, we
66
+ use the `SQLStatement` objects in `sampler.dataset`.
67
+
68
+ ```ruby
69
+ sql_statement = sampler.dataset.first
70
+
71
+ sql_statement.statement
72
+ "Select * from users"
73
+
74
+ sql_statement.duration
75
+ 0.03
76
+
77
+ sql_statement.application_trace
78
+ ["/src/application/app/models/model.rb:24:in `make_query'"]
79
+
80
+ sql_statement.benchmark_runs
81
+ 10
82
+
83
+ sql_statement.benchmark_time
84
+ 0.0324
85
+ ```
4
86
 
5
87
  ## Contributing to Hyphy
6
88
 
data/Rakefile CHANGED
@@ -16,8 +16,10 @@ Jeweler::Tasks.new do |gem|
16
16
  gem.name = "hyphy"
17
17
  gem.homepage = "http://github.com/3dna/hyphy"
18
18
  gem.license = "MIT"
19
- gem.summary = %Q{Identify SQL bottlenecks in tests}
20
- gem.description = %Q{Identify SQL bottlenecks in tests}
19
+ gem.summary = %Q{A SQL bottleneck toolkit}
20
+ gem.description = %Q{Hyphy is a toolkit for identifying SQL bottlenecks in Ruby applications. Given
21
+ an adapter for an ORM and a Ruby block, Hyphy collects all executed queries in
22
+ a dataset. Afterward, it can filter the dataset and even benchmark the queries.}
21
23
  gem.email = "david@nationbuilder.com"
22
24
  gem.authors = ["David Huie"]
23
25
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
data/hyphy.gemspec CHANGED
@@ -5,19 +5,18 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "hyphy"
8
- s.version = "0.0.0"
8
+ s.version = "0.0.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David Huie"]
12
- s.date = "2013-07-24"
13
- s.description = "Identify SQL bottlenecks in tests"
12
+ s.date = "2013-07-30"
13
+ s.description = "Hyphy is a toolkit for identifying SQL bottlenecks in Ruby applications. Given\nan adapter for an ORM and a Ruby block, Hyphy collects all executed queries in\na dataset. Afterward, it can filter the dataset and even benchmark the queries."
14
14
  s.email = "david@nationbuilder.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
17
  "README.md"
18
18
  ]
19
19
  s.files = [
20
- ".document",
21
20
  ".rspec",
22
21
  ".ruby-gemset",
23
22
  ".ruby-version",
@@ -29,51 +28,47 @@ Gem::Specification.new do |s|
29
28
  "VERSION",
30
29
  "hyphy.gemspec",
31
30
  "lib/hyphy.rb",
32
- "lib/hyphy/database.rb",
33
- "lib/hyphy/dataset.rb",
34
- "lib/hyphy/dataset_collection.rb",
35
31
  "lib/hyphy/filters/abstract_filter.rb",
32
+ "lib/hyphy/filters/benchmark_filter.rb",
36
33
  "lib/hyphy/filters/duration_filter.rb",
37
- "lib/hyphy/models/sql_statement.rb",
34
+ "lib/hyphy/filters/limit_filter.rb",
35
+ "lib/hyphy/filters/sql_filter.rb",
38
36
  "lib/hyphy/orm_adapters/abstract_orm_adapter.rb",
39
37
  "lib/hyphy/orm_adapters/activerecord_adapter.rb",
40
38
  "lib/hyphy/sampler.rb",
41
- "spec/dataset_collection_spec.rb",
42
- "spec/dataset_spec.rb",
39
+ "lib/hyphy/sql_statement.rb",
43
40
  "spec/filters/abstract_filter_spec.rb",
41
+ "spec/filters/benchmark_filter_spec.rb",
44
42
  "spec/filters/duration_filter_spec.rb",
43
+ "spec/filters/limit_filter_spec.rb",
44
+ "spec/filters/sql_filter_spec.rb",
45
45
  "spec/models/sql_statement_spec.rb",
46
46
  "spec/orm_adapters/activerecord_orm_adapter_spec.rb",
47
47
  "spec/sampler_spec.rb",
48
- "spec/spec_helper.rb",
49
- "specification.txt"
48
+ "spec/spec_helper.rb"
50
49
  ]
51
50
  s.homepage = "http://github.com/3dna/hyphy"
52
51
  s.licenses = ["MIT"]
53
52
  s.require_paths = ["lib"]
54
53
  s.rubygems_version = "1.8.25"
55
- s.summary = "Identify SQL bottlenecks in tests"
54
+ s.summary = "A SQL bottleneck toolkit"
56
55
 
57
56
  if s.respond_to? :specification_version then
58
57
  s.specification_version = 3
59
58
 
60
59
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
- s.add_runtime_dependency(%q<sequel>, [">= 0"])
62
- s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
63
60
  s.add_runtime_dependency(%q<activesupport>, ["~> 3.2"])
61
+ s.add_runtime_dependency(%q<activerecord>, ["~> 3.2"])
64
62
  s.add_development_dependency(%q<bundler>, [">= 0"])
65
- s.add_development_dependency(%q<database_cleaner>, [">= 0"])
66
63
  s.add_development_dependency(%q<jeweler>, [">= 0"])
67
64
  s.add_development_dependency(%q<pry-nav>, [">= 0"])
68
65
  s.add_development_dependency(%q<rdoc>, [">= 0"])
69
66
  s.add_development_dependency(%q<rspec>, [">= 0"])
70
67
  s.add_development_dependency(%q<simplecov>, [">= 0"])
71
68
  else
72
- s.add_dependency(%q<sequel>, [">= 0"])
73
- s.add_dependency(%q<sqlite3>, [">= 0"])
74
69
  s.add_dependency(%q<activesupport>, ["~> 3.2"])
70
+ s.add_dependency(%q<activerecord>, ["~> 3.2"])
75
71
  s.add_dependency(%q<bundler>, [">= 0"])
76
- s.add_dependency(%q<database_cleaner>, [">= 0"])
77
72
  s.add_dependency(%q<jeweler>, [">= 0"])
78
73
  s.add_dependency(%q<pry-nav>, [">= 0"])
79
74
  s.add_dependency(%q<rdoc>, [">= 0"])
@@ -81,11 +76,9 @@ Gem::Specification.new do |s|
81
76
  s.add_dependency(%q<simplecov>, [">= 0"])
82
77
  end
83
78
  else
84
- s.add_dependency(%q<sequel>, [">= 0"])
85
- s.add_dependency(%q<sqlite3>, [">= 0"])
86
79
  s.add_dependency(%q<activesupport>, ["~> 3.2"])
80
+ s.add_dependency(%q<activerecord>, ["~> 3.2"])
87
81
  s.add_dependency(%q<bundler>, [">= 0"])
88
- s.add_dependency(%q<database_cleaner>, [">= 0"])
89
82
  s.add_dependency(%q<jeweler>, [">= 0"])
90
83
  s.add_dependency(%q<pry-nav>, [">= 0"])
91
84
  s.add_dependency(%q<rdoc>, [">= 0"])
@@ -1,13 +1,13 @@
1
- class Hyphy::AbstractFilter
1
+ class Hyphy::Filters::AbstractFilter
2
2
 
3
- attr_reader :dataset
3
+ attr_reader :data
4
4
 
5
- def initialize(dataset, opts={})
6
- @dataset = dataset
5
+ def initialize(data, opts={})
6
+ @data = data
7
7
  end
8
8
 
9
9
  def filter
10
- @dataset
10
+ @data
11
11
  end
12
12
 
13
13
  end
@@ -0,0 +1,30 @@
1
+ class Hyphy::Filters::BenchmarkFilter < Hyphy::Filters::AbstractFilter
2
+
3
+ def initialize(data, opts)
4
+ @runs = opts[:runs] || 1
5
+
6
+ super
7
+ end
8
+
9
+ def filter
10
+ @data.each do |sql_statement|
11
+ timing = self.class.benchmark(sql_statement, @runs)
12
+
13
+ sql_statement.benchmark_runs = @runs
14
+ sql_statement.benchmark_time = timing
15
+ end
16
+ end
17
+
18
+ def self.benchmark(sql_statement, runs)
19
+ times = []
20
+
21
+ (1..runs).each do
22
+ times << sql_statement.orm_adapter.time_statement(sql_statement)
23
+ end
24
+
25
+ # Calculate the average
26
+ average = times.reduce(:+) / times.count
27
+ average.to_f
28
+ end
29
+
30
+ end
@@ -1,20 +1,29 @@
1
- class Hyphy::DurationFilter < Hyphy::AbstractFilter
1
+ class Hyphy::Filters::DurationFilter < Hyphy::Filters::AbstractFilter
2
2
 
3
3
  attr_reader :duration_min, :duration_max
4
4
 
5
- def initialize(dataset, opts)
5
+ def initialize(data, opts)
6
6
  @duration_min = opts[:duration_min] || 0.0
7
7
  @duration_max = opts[:duration_max] || Float::INFINITY
8
+ @benchmark = opts[:benchmark] || false
9
+
10
+ if @benchmark
11
+ @duration = lambda { |sql_statement| sql_statement.benchmark_time }
12
+ else
13
+ @duration = lambda { |sql_statement| sql_statement.duration }
14
+ end
8
15
 
9
16
  super
10
17
  end
11
18
 
12
19
  def filter
13
- @dataset.select! do |sql_statement|
14
- (@duration_min <= sql_statement.duration) and (sql_statement.duration <= @duration_max)
20
+ @data.select! do |sql_statement|
21
+ next unless @duration.call(sql_statement)
22
+
23
+ (@duration_min <= @duration.call(sql_statement)) and (@duration.call(sql_statement) <= @duration_max)
15
24
  end
16
25
 
17
- @dataset.sort_by! { |sql_statement| -sql_statement.duration }
26
+ @data.sort_by! { |sql_statement| -sql_statement.duration }
18
27
  end
19
28
 
20
29
  end
@@ -0,0 +1,13 @@
1
+ class Hyphy::Filters::LimitFilter < Hyphy::Filters::AbstractFilter
2
+
3
+ def initialize(data, opts)
4
+ @limit = opts[:limit] || 10
5
+
6
+ super
7
+ end
8
+
9
+ def filter
10
+ @data = @data[(0...@limit)]
11
+ end
12
+
13
+ end
@@ -0,0 +1,21 @@
1
+ class Hyphy::Filters::SQLFilter < Hyphy::Filters::AbstractFilter
2
+
3
+ class IncorrectSQLTypeException < Exception; end
4
+
5
+ def initialize(data, opts={})
6
+ @type = opts[:type] || :select
7
+
8
+ unless [:select, :insert].include?(@type)
9
+ raise IncorrectSQLTypeException, "incorrect type: #{@type}"
10
+ end
11
+
12
+ super
13
+ end
14
+
15
+ def filter
16
+ @data.select! do |sql_statement|
17
+ sql_statement.send("#{@type}?".to_sym)
18
+ end
19
+ end
20
+
21
+ end
@@ -1,7 +1,9 @@
1
- require 'json'
2
-
3
1
  class Hyphy::AbstractORMAdapter
4
2
 
5
3
  def self.subscribe_to_sql_notifications(callback); end
6
4
 
5
+ def self.unsubscribe_to_sql_notifications(subscriber); end
6
+
7
+ def self.time_statement(statement); end
8
+
7
9
  end
@@ -1,15 +1,33 @@
1
+ require 'active_record'
1
2
  require 'active_support/notifications'
3
+ require 'benchmark'
2
4
 
3
5
  class Hyphy::ActiveRecordAdapter < Hyphy::AbstractORMAdapter
4
6
 
5
7
  def self.subscribe_to_sql_notifications(callback)
6
8
  ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
7
- sql_statement = args[4][:sql]
9
+ sql = args[4][:sql]
10
+ binds = args[4][:binds]
8
11
  start_time = args[1]
9
12
  end_time = args[2]
10
13
 
11
- callback.call(sql_statement, start_time, end_time)
14
+ sql_statement = callback.call(sql, start_time, end_time)
15
+ sql_statement.binds = binds
12
16
  end
13
17
  end
14
18
 
19
+ def self.unsubscribe_to_sql_notifications(subscriber)
20
+ ActiveSupport::Notifications.unsubscribe(subscriber)
21
+ end
22
+
23
+ def self.time_statement(sql_statement)
24
+ ActiveRecord::Base.connection.clear_query_cache
25
+
26
+ binds = sql_statement.binds
27
+ Benchmark.realtime { ActiveRecord::Base.connection.send(:exec_query,
28
+ sql_statement.statement,
29
+ 'SQL',
30
+ binds) }
31
+ end
32
+
15
33
  end
data/lib/hyphy/sampler.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  class Hyphy::Sampler
2
2
 
3
+ attr_accessor :dataset
3
4
  attr_reader :orm_adapter, :metadata_callbacks
4
5
 
5
6
  class UnsupportedORMException < Exception; end
@@ -13,25 +14,30 @@ class Hyphy::Sampler
13
14
  raise UnsupportedORMException, 'ORM #{orm} is not supported'
14
15
  end
15
16
 
17
+ @dataset = []
16
18
  @metadata_callbacks = {}
17
19
  end
18
20
 
19
- def log_sql(statement, start_time, end_time)
20
- Hyphy::SQLStatement.create(:statement => statement,
21
- :start_time => start_time,
22
- :end_time => end_time,
23
- :trace_json => JSON(caller))
21
+ def log_sql(statement, start_time, end_time, orm_adapter)
22
+ sql_statement = Hyphy::SQLStatement.new(:statement => statement,
23
+ :start_time => start_time,
24
+ :end_time => end_time,
25
+ :orm_adapter => orm_adapter,
26
+ :trace => caller)
27
+ @dataset << sql_statement
28
+ sql_statement
24
29
  end
25
30
 
26
31
  def process_metadata(sql_statement)
27
32
  @metadata_callbacks.each do |key, value_block|
28
- sql_statement.add_metadata(key, value_block.call)
33
+ sql_statement.metadata[key] = value_block.call
29
34
  end
30
35
  end
31
36
 
32
37
  def sample(statement, start_time, end_time)
33
- sql_statement = log_sql(statement, start_time, end_time)
38
+ sql_statement = log_sql(statement, start_time, end_time, @orm_adapter)
34
39
  process_metadata(sql_statement)
40
+ sql_statement
35
41
  end
36
42
 
37
43
  def add_metadata(name, &block)
@@ -39,7 +45,22 @@ class Hyphy::Sampler
39
45
  end
40
46
 
41
47
  def begin
42
- @orm_adapter.subscribe_to_sql_notifications(method(:sample))
48
+ @subscriber = @orm_adapter.subscribe_to_sql_notifications(method(:sample))
49
+ end
50
+
51
+ def stop
52
+ @orm_adapter.unsubscribe_to_sql_notifications(@subscriber)
53
+ end
54
+
55
+ def profile
56
+ self.begin
57
+ yield
58
+ self.stop
59
+ end
60
+
61
+ def apply_filter(filter_class, opts={})
62
+ filter = filter_class.new(@dataset, opts)
63
+ filter.filter
43
64
  end
44
65
 
45
66
  end
@@ -0,0 +1,52 @@
1
+ class Hyphy::SQLStatement
2
+
3
+ DIGIT_MARKER = '<digit>'
4
+
5
+ attr_accessor(:statement,
6
+ :trace,
7
+ :metadata,
8
+ :binds,
9
+ :orm_adapter,
10
+ :start_time,
11
+ :end_time,
12
+ :benchmark_runs,
13
+ :benchmark_time)
14
+
15
+ def initialize(opts={})
16
+ @statement = opts[:statement]
17
+ @start_time = opts[:start_time]
18
+ @end_time = opts[:end_time]
19
+ @orm_adapter = opts[:orm_adapter]
20
+ @trace = opts[:trace] || []
21
+ @binds = opts[:binds] || []
22
+ @metadata = opts[:metadata] || {}
23
+ end
24
+
25
+ def duration
26
+ @duration ||= (end_time - start_time)
27
+ end
28
+
29
+ def stripped_statement
30
+ @stripped_statement ||= statement.strip
31
+ end
32
+
33
+ def select?
34
+ @select ||= stripped_statement.upcase.match(/^SELECT/)
35
+ end
36
+
37
+ def insert?
38
+ @insert ||= stripped_statement.upcase.match(/^INSERT/)
39
+ end
40
+
41
+ def digitless
42
+ @digitless ||= stripped_statement.gsub(/\d+/, DIGIT_MARKER)
43
+ end
44
+
45
+ def application_trace
46
+ return @application_trace if @application_trace
47
+
48
+ regex = Regexp.new("^#{Dir.pwd}")
49
+ @application_trace ||= trace.select { |line| regex.match(line) }
50
+ end
51
+
52
+ end
data/lib/hyphy.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  module Hyphy; end
2
+ module Hyphy::Filters; end
2
3
 
3
- require 'hyphy/database'
4
- require 'hyphy/models/sql_statement'
4
+ require 'hyphy/sql_statement'
5
5
  require 'hyphy/orm_adapters/abstract_orm_adapter'
6
6
  require 'hyphy/orm_adapters/activerecord_adapter'
7
7
  require 'hyphy/sampler'
8
8
  require 'hyphy/filters/abstract_filter'
9
9
  require 'hyphy/filters/duration_filter'
10
- require 'hyphy/dataset'
11
- require 'hyphy/dataset_collection'
10
+ require 'hyphy/filters/benchmark_filter'
11
+ require 'hyphy/filters/limit_filter'
12
+ require 'hyphy/filters/sql_filter'
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Hyphy::AbstractFilter do
3
+ describe Hyphy::Filters::AbstractFilter do
4
4
 
5
- it 'stores a dataset' do
6
- dataset = [1, 2]
7
- filter = Hyphy::AbstractFilter.new(dataset)
5
+ it 'stores data' do
6
+ data = [1, 2]
7
+ filter = Hyphy::Filters::AbstractFilter.new(data)
8
8
 
9
- filter.dataset.should == dataset
10
- filter.filter.should == dataset
9
+ filter.data.should == data
10
+ filter.filter.should == data
11
11
  end
12
12
 
13
13
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hyphy::Filters::BenchmarkFilter do
4
+
5
+ before(:each) do
6
+ @sql_statement = Hyphy::SQLStatement.new(:statement => 'select * from table',
7
+ :orm_adapter => Hyphy::AbstractORMAdapter)
8
+ @sql_statement_times = [1.0, 2.0, 3.0]
9
+ @runs = @sql_statement_times.count
10
+
11
+ Hyphy::AbstractORMAdapter.stub(:time_statement).and_return(*@sql_statement_times)
12
+
13
+ @data = [@sql_statement]
14
+ @filter = Hyphy::Filters::BenchmarkFilter.new(@data, :runs => @runs)
15
+ @average_time = @sql_statement_times.reduce(:+) / @runs
16
+ end
17
+
18
+ describe "#filter" do
19
+
20
+ it "modifies the data to include benchmark data" do
21
+ @filter.filter
22
+
23
+ @data[0].benchmark_runs.should == @runs
24
+ @data[0].benchmark_time.should == @average_time
25
+ end
26
+
27
+ end
28
+
29
+ describe ".benchmark" do
30
+
31
+ it "it returns an average of the different run times of a statement" do
32
+ average_time = Hyphy::Filters::BenchmarkFilter.benchmark(@sql_statement, @runs)
33
+ average_time.should == @average_time
34
+ end
35
+
36
+ end
37
+
38
+ end