slacker 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +4 -4
  3. data/README.markdown +22 -22
  4. data/Rakefile +11 -11
  5. data/bin/slacker +28 -29
  6. data/bin/slacker_new +34 -34
  7. data/lib/slacker.rb +175 -175
  8. data/lib/slacker/application.rb +211 -206
  9. data/lib/slacker/command_line_formatter.rb +59 -59
  10. data/lib/slacker/command_line_formatter2.rb +61 -0
  11. data/lib/slacker/configuration.rb +59 -59
  12. data/lib/slacker/formatter.rb +14 -19
  13. data/lib/slacker/query_result_matcher.rb +178 -178
  14. data/lib/slacker/rspec_ext.rb +49 -49
  15. data/lib/slacker/rspec_monkey.rb +7 -7
  16. data/lib/slacker/sql.rb +39 -39
  17. data/lib/slacker/sql_preprocessor.rb +23 -23
  18. data/lib/slacker/string_helper.rb +16 -16
  19. data/lib/slacker/version.rb +3 -3
  20. data/lib/slacker_new/project/data/sample_1/my_table_expected_power_results.csv +11 -11
  21. data/lib/slacker_new/project/data/sample_1/my_table_initial_data.csv +11 -11
  22. data/lib/slacker_new/project/data/sample_1/numbers_expected_output.csv +3 -3
  23. data/lib/slacker_new/project/database.yml +9 -9
  24. data/lib/slacker_new/project/lib/helpers/my_helper.rb +1 -1
  25. data/lib/slacker_new/project/spec/sample_1.rb +66 -66
  26. data/lib/slacker_new/project/sql/sample_1/my_table_on_power.sql.erb +1 -1
  27. data/lib/slacker_new/project/sql/sample_1/play_with_numbers.sql.erb +16 -16
  28. data/lib/slacker_new/project/sql/sample_1/sysobjects_with_params.sql.erb +1 -1
  29. data/slacker.gemspec +27 -26
  30. data/spec/application_spec.rb +13 -13
  31. data/spec/query_result_matcher_spec.rb +268 -268
  32. data/spec/rspec_ext_spec.rb +87 -87
  33. data/spec/slacker_spec.rb +59 -59
  34. data/spec/spec_helper.rb +9 -9
  35. data/spec/test_files/matcher/test_1.csv +3 -3
  36. data/spec/test_files/test_slacker_project/data/test_1.csv +3 -3
  37. data/spec/test_files/test_slacker_project/sql/nest/nested_1.sql.erb +1 -1
  38. data/spec/test_files/test_slacker_project/sql/no_params.sql.erb +2 -2
  39. data/spec/test_files/test_slacker_project/sql/params.sql.erb +1 -1
  40. metadata +19 -20
@@ -1,49 +1,49 @@
1
- require 'slacker'
2
- require 'slacker/query_result_matcher'
3
- require 'csv'
4
-
5
- module Slacker
6
- module RSpecExt
7
- def query(query_string, options = {}, log_name = nil)
8
- log_name ||= Slacker.construct_log_name('query', query_string, options)
9
- sql = Slacker.sql_from_query_string(query_string, options)
10
- @results = Slacker.query_script(example, sql, log_name)
11
- if block_given?
12
- yield @results
13
- end
14
- @results
15
- end
16
-
17
- def sql
18
- Slacker.sql(self)
19
- end
20
-
21
- # Get a matcher which will compare the query results to a golden master
22
- def match(golden_master)
23
- QueryResultMatcher.new(Slacker.filter_golden_master(golden_master))
24
- end
25
-
26
- def csv(csv_file)
27
- Slacker.get_csv(csv_file)
28
- end
29
-
30
- def touch_csv(csv_file_or_object, fields, field_generators = {})
31
- Slacker.touch_csv(csv_file_or_object, fields, field_generators)
32
- end
33
-
34
- def load_csv(csv_file_or_object, table_name, log_name = nil)
35
- log_name ||= "load_csv '#{csv_file_or_object.kind_of?(CSV::Table) ? 'CSV Object' : csv_file_or_object }', 'table_name'"
36
- csv_object = case csv_file_or_object
37
- when String then Slacker.get_csv(csv_file_or_object)
38
- when CSV::Table then csv_file_or_object
39
- when Array then Slacker.hash_array_to_csv(csv_file_or_object)
40
- end
41
-
42
- Slacker.load_csv(example, csv_object, table_name, log_name)
43
- end
44
-
45
- def yes?(val)
46
- val != nil && val.downcase == 'yes'
47
- end
48
- end
49
- end
1
+ require 'slacker'
2
+ require 'slacker/query_result_matcher'
3
+ require 'csv'
4
+
5
+ module Slacker
6
+ module RSpecExt
7
+ def query(query_string, options = {}, log_name = nil)
8
+ log_name ||= Slacker.construct_log_name('query', query_string, options)
9
+ sql = Slacker.sql_from_query_string(query_string, options)
10
+ @results = Slacker.query_script(example, sql, log_name)
11
+ if block_given?
12
+ yield @results
13
+ end
14
+ @results
15
+ end
16
+
17
+ def sql
18
+ Slacker.sql(self)
19
+ end
20
+
21
+ # Get a matcher which will compare the query results to a golden master
22
+ def match(golden_master)
23
+ QueryResultMatcher.new(Slacker.filter_golden_master(golden_master))
24
+ end
25
+
26
+ def csv(csv_file)
27
+ Slacker.get_csv(csv_file)
28
+ end
29
+
30
+ def touch_csv(csv_file_or_object, fields, field_generators = {})
31
+ Slacker.touch_csv(csv_file_or_object, fields, field_generators)
32
+ end
33
+
34
+ def load_csv(csv_file_or_object, table_name, log_name = nil)
35
+ log_name ||= "load_csv '#{csv_file_or_object.kind_of?(CSV::Table) ? 'CSV Object' : csv_file_or_object }', 'table_name'"
36
+ csv_object = case csv_file_or_object
37
+ when String then Slacker.get_csv(csv_file_or_object)
38
+ when CSV::Table then csv_file_or_object
39
+ when Array then Slacker.hash_array_to_csv(csv_file_or_object)
40
+ end
41
+
42
+ Slacker.load_csv(example, csv_object, table_name, log_name)
43
+ end
44
+
45
+ def yes?(val)
46
+ val != nil && val.downcase == 'yes'
47
+ end
48
+ end
49
+ end
@@ -1,7 +1,7 @@
1
- # Monkeypatch a method to reset RSpec to reset it
2
- module RSpec
3
- def self.slacker_reset
4
- @world = nil
5
- @configuration = nil
6
- end
7
- end
1
+ # Monkeypatch a method to reset RSpec
2
+ module RSpec
3
+ def self.slacker_reset
4
+ @world = nil
5
+ @configuration = nil
6
+ end
7
+ end
@@ -1,39 +1,39 @@
1
- require 'slacker'
2
- require 'slacker/rspec_ext'
3
-
4
- module Slacker
5
- class Sql < BasicObject
6
- attr_accessor :base_folder, :rspec_ext
7
-
8
- def initialize(base_folder, rspec_ext)
9
- @base_folder = base_folder
10
- @rspec_ext = rspec_ext
11
- end
12
-
13
- def method_missing(method_name, *params, &block)
14
- ::Kernel.raise "Slacker::Sql.rspec_ext not initialized" if rspec_ext.nil?
15
- ::Kernel.raise "Missing folder #{base_folder}" if !::File.directory?(base_folder)
16
-
17
- method_name = method_name.to_s
18
-
19
- if ::File.directory?(::File.join(base_folder, method_name))
20
- ::Slacker::Sql.new(::File.join(base_folder, method_name), rspec_ext)
21
- else
22
- sql_file = ::Slacker.sql_file_from_method_name(base_folder, method_name)
23
- case sql_file
24
- when nil
25
- ::Kernel.raise "No SQL file found corresponding to method '#{method_name}' in folder #{base_folder}"
26
- else
27
- rspec_ext.query sql_file, *params, &block
28
- end
29
- end
30
- end
31
-
32
- def respond_to?(method_name)
33
- method_name = method_name.to_s
34
- ::Kernel.raise "Slacker::Sql.rspec_ext not initialized" if rspec_ext.nil?
35
- ::File.directory?(::File.join(base_folder, method_name)) ||
36
- !(::Slacker.sql_file_from_method_name(base_folder, method_name).nil?)
37
- end
38
- end
39
- end
1
+ require 'slacker'
2
+ require 'slacker/rspec_ext'
3
+
4
+ module Slacker
5
+ class Sql < BasicObject
6
+ attr_accessor :base_folder, :rspec_ext
7
+
8
+ def initialize(base_folder, rspec_ext)
9
+ @base_folder = base_folder
10
+ @rspec_ext = rspec_ext
11
+ end
12
+
13
+ def method_missing(method_name, *params, &block)
14
+ ::Kernel.raise "Slacker::Sql.rspec_ext not initialized" if rspec_ext.nil?
15
+ ::Kernel.raise "Missing folder #{base_folder}" if !::File.directory?(base_folder)
16
+
17
+ method_name = method_name.to_s
18
+
19
+ if ::File.directory?(::File.join(base_folder, method_name))
20
+ ::Slacker::Sql.new(::File.join(base_folder, method_name), rspec_ext)
21
+ else
22
+ sql_file = ::Slacker.sql_file_from_method_name(base_folder, method_name)
23
+ case sql_file
24
+ when nil
25
+ ::Kernel.raise "No SQL file found corresponding to method '#{method_name}' in folder #{base_folder}"
26
+ else
27
+ rspec_ext.query sql_file, *params, &block
28
+ end
29
+ end
30
+ end
31
+
32
+ def respond_to?(method_name)
33
+ method_name = method_name.to_s
34
+ ::Kernel.raise "Slacker::Sql.rspec_ext not initialized" if rspec_ext.nil?
35
+ ::File.directory?(::File.join(base_folder, method_name)) ||
36
+ !(::Slacker.sql_file_from_method_name(base_folder, method_name).nil?)
37
+ end
38
+ end
39
+ end
@@ -1,24 +1,24 @@
1
- module Slacker
2
- module SqlPreprocessor
3
- IVAR_REX = /%{\s*(.*?)\s*}/
4
-
5
- def self.executable_sql(sql, example)
6
- # Replace all appearances of %{} with the values of the corresponding example instance variables
7
- sql.gsub(IVAR_REX) do
8
- ivar = $1.to_sym
9
- instance = example.example_group_instance
10
-
11
- if instance.instance_variable_defined?(ivar)
12
- instance.instance_variable_get(ivar).to_s
13
- else
14
- raise "Example is missing instance variable #{ivar}"
15
- end
16
- end
17
- end
18
-
19
- def self.debuggable_sql(sql)
20
- # Replace all appearances of %{} with the names of the sql variables
21
- sql.gsub(IVAR_REX) {$1}
22
- end
23
- end
1
+ module Slacker
2
+ module SqlPreprocessor
3
+ IVAR_REX = /%{\s*(.*?)\s*}/
4
+
5
+ def self.executable_sql(sql, example)
6
+ # Replace all appearances of %{} with the values of the corresponding example instance variables
7
+ sql.gsub(IVAR_REX) do
8
+ ivar = $1.to_sym
9
+ instance = example.example_group_instance
10
+
11
+ if instance.instance_variable_defined?(ivar)
12
+ instance.instance_variable_get(ivar).to_s
13
+ else
14
+ raise "Example is missing instance variable #{ivar}"
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.debuggable_sql(sql)
20
+ # Replace all appearances of %{} with the names of the sql variables
21
+ sql.gsub(IVAR_REX) {$1}
22
+ end
23
+ end
24
24
  end
@@ -1,17 +1,17 @@
1
- module Slacker
2
- module StringHelper
3
- class << self
4
- def camelize(lower_case_and_underscored_word)
5
- lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
6
- end
7
-
8
- def constantize(camel_cased_word)
9
- unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
10
- raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
11
- end
12
-
13
- Object.module_eval("::#{$1}", __FILE__, __LINE__)
14
- end
15
- end
16
- end
1
+ module Slacker
2
+ module StringHelper
3
+ class << self
4
+ def camelize(lower_case_and_underscored_word)
5
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
6
+ end
7
+
8
+ def constantize(camel_cased_word)
9
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
10
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
11
+ end
12
+
13
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
14
+ end
15
+ end
16
+ end
17
17
  end
@@ -1,3 +1,3 @@
1
- module Slacker
2
- VERSION = "1.0.9"
3
- end
1
+ module Slacker
2
+ VERSION = "1.0.10"
3
+ end
@@ -1,11 +1,11 @@
1
- "x","y","power"
2
- "2","1","2"
3
- "3","2","9"
4
- "4","3","64"
5
- "5","4","625"
6
- "4","2","16"
7
- "3","3","27"
8
- "2","4","16"
9
- "1","5","1"
10
- "-1","2","1"
11
- "-2","5","-32"
1
+ "x","y","power"
2
+ "2","1","2"
3
+ "3","2","9"
4
+ "4","3","64"
5
+ "5","4","625"
6
+ "4","2","16"
7
+ "3","3","27"
8
+ "2","4","16"
9
+ "1","5","1"
10
+ "-1","2","1"
11
+ "-2","5","-32"
@@ -1,11 +1,11 @@
1
- "x","y"
2
- 2,1
3
- 3,2
4
- 4,3
5
- 5,4
6
- 4,2
7
- 3,3
8
- 2,4
9
- 1,5
10
- -1,2
11
- -2,5
1
+ "x","y"
2
+ 2,1
3
+ 3,2
4
+ 4,3
5
+ 5,4
6
+ 4,2
7
+ 3,3
8
+ 2,4
9
+ 1,5
10
+ -1,2
11
+ -2,5
@@ -1,3 +1,3 @@
1
- "p","s"
2
- 2,34
3
- 12,44
1
+ "p","s"
2
+ 2,34
3
+ 12,44
@@ -1,9 +1,9 @@
1
- # Database connection.
2
- # When Slacker is executed, it will attempt to connect to this database.
3
-
4
- # Replace the following with your connection information.
5
- # Note that at this point Slacker only works with SQL Server authentication.
6
- server: my_server
7
- database: my_database
8
- user: user_name
9
- password: password
1
+ # Database connection.
2
+ # When Slacker is executed, it will attempt to connect to this database.
3
+
4
+ # Replace the following with your connection information.
5
+ # Note that at this point Slacker only works with SQL Server authentication.
6
+ server: my_server
7
+ database: my_database
8
+ user: user_name
9
+ password: password
@@ -1,2 +1,2 @@
1
- module MyHelper
1
+ module MyHelper
2
2
  end
@@ -1,66 +1,66 @@
1
- # Method "describe" opens up an example group.
2
- describe 'My database' do
3
- # Simple inline query example.
4
- it 'contains system tables' do
5
- # Make sure we have at least one system object in the database.
6
- query("select * from sysobjects where xtype = 'S';").count.should > 0
7
- end
8
-
9
- # The same query, this time using a SQL template stored in file "sql/sample_1/sysobject.sql.erb".
10
- it 'contains system tables (take two)' do
11
- # Every (*.sql.erb) file in folder "sql" can be called as a method on object "sql".
12
- # Subfolders of folder "sql" appear as children of object "sql" with their (*.sql.erb) files automatically available as methods.
13
- sql.sample_1.sysobjects.count.should > 0
14
- end
15
-
16
- # This time we'll use a parameterized template.
17
- it 'contains system tables (take three)' do
18
- # Every template can accept parameters; see file "sql/sample_1/sysobject_with_params.sql.erb".
19
- sql.sample_1.sysobjects_with_params(:xtype => 'S').count.should > 0
20
- end
21
-
22
- # SQL Templates can contain multiple statements and can return multiple resultsets.
23
- it 'can play with numbers' do
24
- # Note that this time we're calling the template with a block which receives the results as a block parameter.
25
- sql.sample_1.play_with_numbers(:x => 2, :y => 12) do |results|
26
- # The results object contains an array of all the resultsets generated by the query script.
27
- # A resultset contains an array of records. Each record is a hash of field => value pairs.
28
-
29
- # First resultset; First record; Column "product".
30
- results[0][0][:product].should == 24
31
-
32
- # A resultset can be matched directly against an array of hashes using method "match".
33
- results[1].should match([{:x => 2, :y => 12, :sum => 14}])
34
-
35
- # Or against a CSV file stored in project's "data" folder (see file "data/sample_1/numbers_expected_output.csv").
36
- results[2].should match('sample_1/numbers_expected_output.csv')
37
-
38
- # A resultset's values can be matched one-by-one.
39
- results[2][0][:p].should == 2
40
- results[2][0][:s].should == 34
41
- results[2][1][:p].should == 12
42
- results[2][1][:s].should == 44
43
- end
44
- end
45
-
46
- # Every "it" (example) is executed in a T-SQL transaction which is rolled back once the example is complete.
47
- # No example can ever interfere with the results of another example.
48
- #
49
- # CSV files can be used to load data directly into a table.
50
- # In this example, we will create a table, populate it with data,
51
- # calculate the exponentiation of one column based on another column
52
- # and verify the results against an expected resultset stored in a CSV file.
53
- it 'can play with numbers (take two)' do
54
- # Create the table - see file "sql/sample_1/create_my_table.sql.erb".
55
- sql.sample_1.create_my_table
56
- # We can populate any table with data from the "data" folder by calling method "load_csv".
57
- # See file "data/sample_1/my_table_initial_data.csv".
58
- load_csv('sample_1/my_table_initial_data.csv', 'MyTable')
59
-
60
- # Now let's test the system scalar function Power.
61
- # We will use it in a query expression executed agaings MyTable and we
62
- # will compare the results against a CSV file - we should expect them to match.
63
- # See files "sql/sample_1/my_table_on_power.sql.erb" and "data/sample_1/my_table_expected_power_results.csv".
64
- sql.sample_1.my_table_on_power.should match('sample_1/my_table_expected_power_results.csv')
65
- end
66
- end
1
+ # Method "describe" opens up an example group.
2
+ describe 'My database' do
3
+ # Simple inline query example.
4
+ it 'contains system tables' do
5
+ # Make sure we have at least one system object in the database.
6
+ query("select * from sysobjects where xtype = 'S';").count.should > 0
7
+ end
8
+
9
+ # The same query, this time using a SQL template stored in file "sql/sample_1/sysobject.sql.erb".
10
+ it 'contains system tables (take two)' do
11
+ # Every (*.sql.erb) file in folder "sql" can be called as a method on object "sql".
12
+ # Subfolders of folder "sql" appear as children of object "sql" with their (*.sql.erb) files automatically available as methods.
13
+ sql.sample_1.sysobjects.count.should > 0
14
+ end
15
+
16
+ # This time we'll use a parameterized template.
17
+ it 'contains system tables (take three)' do
18
+ # Every template can accept parameters; see file "sql/sample_1/sysobject_with_params.sql.erb".
19
+ sql.sample_1.sysobjects_with_params(:xtype => 'S').count.should > 0
20
+ end
21
+
22
+ # SQL Templates can contain multiple statements and can return multiple resultsets.
23
+ it 'can play with numbers' do
24
+ # Note that this time we're calling the template with a block which receives the results as a block parameter.
25
+ sql.sample_1.play_with_numbers(:x => 2, :y => 12) do |results|
26
+ # The results object contains an array of all the resultsets generated by the query script.
27
+ # A resultset contains an array of records. Each record is a hash of field => value pairs.
28
+
29
+ # First resultset; First record; Column "product".
30
+ results[0][0][:product].should == 24
31
+
32
+ # A resultset can be matched directly against an array of hashes using method "match".
33
+ results[1].should match([{:x => 2, :y => 12, :sum => 14}])
34
+
35
+ # Or against a CSV file stored in project's "data" folder (see file "data/sample_1/numbers_expected_output.csv").
36
+ results[2].should match('sample_1/numbers_expected_output.csv')
37
+
38
+ # A resultset's values can be matched one-by-one.
39
+ results[2][0][:p].should == 2
40
+ results[2][0][:s].should == 34
41
+ results[2][1][:p].should == 12
42
+ results[2][1][:s].should == 44
43
+ end
44
+ end
45
+
46
+ # Every "it" (example) is executed in a T-SQL transaction which is rolled back once the example is complete.
47
+ # No example can ever interfere with the results of another example.
48
+ #
49
+ # CSV files can be used to load data directly into a table.
50
+ # In this example, we will create a table, populate it with data,
51
+ # calculate the exponentiation of one column based on another column
52
+ # and verify the results against an expected resultset stored in a CSV file.
53
+ it 'can play with numbers (take two)' do
54
+ # Create the table - see file "sql/sample_1/create_my_table.sql.erb".
55
+ sql.sample_1.create_my_table
56
+ # We can populate any table with data from the "data" folder by calling method "load_csv".
57
+ # See file "data/sample_1/my_table_initial_data.csv".
58
+ load_csv('sample_1/my_table_initial_data.csv', 'MyTable')
59
+
60
+ # Now let's test the system scalar function Power.
61
+ # We will use it in a query expression executed agaings MyTable and we
62
+ # will compare the results against a CSV file - we should expect them to match.
63
+ # See files "sql/sample_1/my_table_on_power.sql.erb" and "data/sample_1/my_table_expected_power_results.csv".
64
+ sql.sample_1.my_table_on_power.should match('sample_1/my_table_expected_power_results.csv')
65
+ end
66
+ end