dbexpect 0.11.0

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.
Files changed (46) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +41 -0
  4. data/COPYING +674 -0
  5. data/Gemfile +20 -0
  6. data/Gemfile.lock +45 -0
  7. data/LICENSE.txt +2 -0
  8. data/README.md +106 -0
  9. data/Rakefile +65 -0
  10. data/VERSION +1 -0
  11. data/bin/dbexpect +33 -0
  12. data/bin/great-expectations +28 -0
  13. data/bin/ready-rig +27 -0
  14. data/database.yml +9 -0
  15. data/lib/dbexpect.rb +19 -0
  16. data/lib/dbexpect/command_runner.rb +21 -0
  17. data/lib/dbexpect/console_formatter.rb +40 -0
  18. data/lib/dbexpect/d_s_l_parser.rb +124 -0
  19. data/lib/dbexpect/database.rb +59 -0
  20. data/lib/dbexpect/db_null.rb +25 -0
  21. data/lib/dbexpect/db_sequence.rb +26 -0
  22. data/lib/dbexpect/db_string.rb +29 -0
  23. data/lib/dbexpect/dbexpect.rb +87 -0
  24. data/lib/dbexpect/defaulting_row_set.rb +68 -0
  25. data/lib/dbexpect/expectation_checker.rb +32 -0
  26. data/lib/dbexpect/expectation_tree_node.rb +67 -0
  27. data/lib/dbexpect/expectations/expectation.rb +45 -0
  28. data/lib/dbexpect/expectations/row_count_expectation.rb +32 -0
  29. data/lib/dbexpect/expectations/row_expectation.rb +32 -0
  30. data/lib/dbexpect/odbc_connection.rb +47 -0
  31. data/lib/dbexpect/row.rb +43 -0
  32. data/lib/dbexpect/table.rb +71 -0
  33. data/spec/dbexpect_integration_spec.rb +131 -0
  34. data/spec/defaulting_row_set_spec.rb +37 -0
  35. data/spec/expectation_checker_spec.rb +47 -0
  36. data/spec/expectations/row_expectation_spec.rb +51 -0
  37. data/spec/fixtures/basic_test_expected_inserts.sql +6 -0
  38. data/spec/fixtures/cleanup_db.sql +2 -0
  39. data/spec/fixtures/expected_output.txt +11 -0
  40. data/spec/fixtures/sample_db.sql +12 -0
  41. data/spec/fixtures/sample_project/database.yml +9 -0
  42. data/spec/fixtures/sample_project/defaults/defaults.rb +5 -0
  43. data/spec/fixtures/sample_project/tests/basic_test.rb +41 -0
  44. data/spec/fixtures/sample_project/tests/test2.rb +3 -0
  45. data/spec/spec_helper.rb +28 -0
  46. metadata +186 -0
@@ -0,0 +1,59 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ require_relative 'odbc_connection'
18
+
19
+ class Database
20
+ def self.from_connection(con)
21
+ new(con)
22
+ end
23
+
24
+ def self.hash_from_config
25
+ databases = {}
26
+ YAML.load_file('database.yml').each do |(dsn,config)|
27
+ databases[dsn.to_sym] = from_connection(OdbcConnection.new(dsn,config))
28
+ end
29
+
30
+ databases
31
+ end
32
+
33
+ def initialize(con)
34
+ @connection = con
35
+ end
36
+
37
+ def num_rows_match(schema,table,query)
38
+ @connection.run("select * from #{schema}.#{table} where (#{query})").count
39
+ end
40
+
41
+ def truncate_table(schema,name)
42
+ if @connection.type == 'db2'
43
+ @connection.run("truncate table #{schema}.#{name} immediate")
44
+ else
45
+ @connection.run("truncate table #{schema}.#{name}")
46
+ end
47
+ end
48
+
49
+ def insert_rows(insert_statements)
50
+ insert_statements.each do |stmt|
51
+ @connection.run(stmt)
52
+ end
53
+ end
54
+
55
+ def close
56
+ #@connection.close
57
+ end
58
+
59
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ class DbNull
18
+ def db_str
19
+ 'NULL'
20
+ end
21
+
22
+ def equality_test
23
+ "is null"
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ class DbSequence
18
+ def initialize
19
+ @sequence = 0
20
+ end
21
+
22
+ def db_str
23
+ @sequence += 1
24
+ @sequence.to_s
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ class DbString
18
+ def initialize(str)
19
+ @string = str
20
+ end
21
+
22
+ def db_str
23
+ "'#{@string}'"
24
+ end
25
+
26
+ def equality_test
27
+ " = '#{@string}'"
28
+ end
29
+ end
@@ -0,0 +1,87 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ require_relative 'db_sequence'
18
+ require_relative 'db_null'
19
+ require_relative 'db_string'
20
+ require_relative 'table'
21
+ require_relative 'd_s_l_parser'
22
+ require_relative 'expectation_checker'
23
+ require_relative 'console_formatter'
24
+
25
+ class Dbexpect
26
+
27
+ def initialize(output = STDOUT)
28
+ @output = ConsoleFormatter.new(output)
29
+ end
30
+
31
+ def run_test(script,databases,command_runner)
32
+ setup_test(script,databases)
33
+ run_etl(script,command_runner)
34
+ great_expectations(script,databases)
35
+ end
36
+
37
+ def great_expectations(script, databases)
38
+ eval_script(script)
39
+
40
+ check_table_expectations(databases)
41
+
42
+ if validates_expectations?
43
+ @output.notify_passed
44
+ return 0
45
+ else
46
+ @output.notify_failed(failed_expectations)
47
+ return 1
48
+ end
49
+ end
50
+
51
+ def setup_test(script,databases)
52
+ eval_script(script)
53
+ @tables.each do |table|
54
+ table.set_up_for_test(databases)
55
+ end
56
+ return 0
57
+ end
58
+
59
+
60
+ protected
61
+ def run_etl(script,command_runner)
62
+ @commands_to_run.each {|c| command_runner.run(c) }
63
+ end
64
+
65
+ def eval_script(script)
66
+ parser = DSLParser.new
67
+ parser.parse(File.read(script))
68
+ @tables = parser.tables
69
+ @expectation_tree = parser.expectation_tree
70
+ @commands_to_run = parser.commands
71
+ end
72
+
73
+ def check_table_expectations(databases)
74
+ @expectation_checker = ExpectationChecker.new(databases)
75
+ @expectation_checker.check_expectations(@expectation_tree)
76
+ end
77
+
78
+ def failed_expectations
79
+ @expectation_checker.failed_expectations
80
+ end
81
+
82
+ def validates_expectations?
83
+ @expectation_checker.validates_expectations?
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,68 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ require_relative 'row'
18
+ class DefaultingRowSet
19
+ attr_accessor :defaults
20
+ attr_accessor :columns_in_order
21
+ attr_accessor :rows
22
+
23
+ def initialize
24
+ @defaults = Hash.new
25
+ @rows = []
26
+
27
+ @columns_in_order = []
28
+ end
29
+
30
+ def set_default(column,value)
31
+ add_column(column)
32
+ @defaults[column] = value
33
+ end
34
+
35
+ def add_row(column_values)
36
+ column_values.keys.map {|col| add_column(col) }
37
+
38
+ defaulted_row = set_defaults_at_time_of_addition(column_values)
39
+ @rows << Row.new(defaulted_row,@columns_in_order & defaulted_row.keys)
40
+ @rows.last
41
+ end
42
+
43
+ def insert_statements(schema,name)
44
+ @rows.collect do |row|
45
+ row.insert_stmt(schema,name)
46
+ end
47
+ end
48
+
49
+ def where_clauses
50
+ @rows.map(&:where_clause)
51
+ end
52
+
53
+ def empty?
54
+ @rows.empty?
55
+ end
56
+
57
+ protected
58
+ def add_column(column)
59
+ @columns_in_order << column
60
+ @columns_in_order.uniq!
61
+ end
62
+
63
+ def set_defaults_at_time_of_addition(row)
64
+ @defaults.merge(row)
65
+ end
66
+
67
+
68
+ end
@@ -0,0 +1,32 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ class ExpectationChecker
18
+ attr_accessor :failed_expectations
19
+ def initialize(databases)
20
+ @databases = databases
21
+ end
22
+
23
+ def check_expectations(expectations)
24
+ expectations.map {|e| e.validate_expectation(@databases) }
25
+
26
+ @failed_expectations = expectations.select {|e| e.failed_validation? }
27
+ end
28
+
29
+ def validates_expectations?
30
+ @failed_expectations.empty?
31
+ end
32
+ end
@@ -0,0 +1,67 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ class ExpectationTreeNode
18
+ include Enumerable
19
+
20
+ def initialize(desc,children = [], expectations = [])
21
+ @description = desc
22
+ @children = children
23
+ @expectations = expectations
24
+ end
25
+
26
+ def each(&block)
27
+ @expectations.map(&block)
28
+ @children.each {|c| c.each(&block) }
29
+ end
30
+
31
+ def select(&block)
32
+ matching_children = @children.collect {|c| c.select(&block) }.
33
+ reject {|node| node === EmptyTreeNode }
34
+
35
+ matching_expectations = @expectations.select(&block)
36
+
37
+ return EmptyTreeNode.new if matching_children.empty? && matching_expectations.empty?
38
+
39
+ ExpectationTreeNode.new(@description,matching_children,matching_expectations)
40
+ end
41
+
42
+ def create_child(desc)
43
+ @children << ExpectationTreeNode.new(desc)
44
+ @children.last
45
+ end
46
+
47
+ def add(expectations)
48
+ @expectations += expectations
49
+ end
50
+
51
+ def empty?
52
+ @expectations.empty? && @children.all?(&:empty?)
53
+ end
54
+
55
+ def traverse(depth = 0, &block)
56
+ block.call(depth,@description,@expectations)
57
+ @children.map {|c| c.traverse(depth + 1, &block) }
58
+ end
59
+
60
+ class EmptyTreeNode
61
+ include Enumerable
62
+ def each(&block); end
63
+ def empty?; true; end
64
+ def traverse(depth = 0, &block)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright 2012 C3 Business Solutions
2
+ #
3
+ # This file is part of dbexpect.
4
+ #
5
+ # dbexpect is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # dbexpect is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with dbexpect. If not, see <http://www.gnu.org/licenses/>.
17
+ class Expectation
18
+ def initialize(db_name,schema,table)
19
+ @schema = schema
20
+ @table = table
21
+ @db_name = db_name
22
+ end
23
+
24
+ def validate_expectation(databases)
25
+ database = databases[@db_name]
26
+ begin
27
+ num = database.num_rows_match(@schema,@table,where_clause)
28
+ rescue OdbcConnection::DatabaseException => e
29
+ @failure = expect_msg + "instead database raised error: #{e.message}"
30
+ return
31
+ end
32
+
33
+ if num != @count
34
+ @failure = expect_msg + "got #{num}"
35
+ end
36
+ end
37
+
38
+ def failed_validation?
39
+ @failure
40
+ end
41
+
42
+ def failure_message
43
+ @failure
44
+ end
45
+ end