plsql_unit_test 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -104,22 +104,30 @@ When testing database code, it can be useful to ensure a given table has zero, o
104
104
  To assert the users table has a single row for the username foouser:
105
105
 
106
106
  assert_table_has_one_row("users",
107
- "where username = 'foouser',
107
+ "where username = 'foouser'",
108
108
  "Ensure the users table has a single row")
109
109
 
110
110
  Similarly, to ensure the users table does not have a row:
111
111
 
112
112
  assert_table_has_zero_rows("users",
113
- "where username = 'foouser',
113
+ "where username = 'foouser'",
114
114
  "Ensure the users table zero rows")
115
115
 
116
116
  Finally, to check a table has a given number of rows:
117
117
 
118
- assert_table_has_zero_rows("users",
118
+ assert_table_has_many_rows("users",
119
119
  10
120
- "where status = 'locked'
120
+ "where status = 'locked'"
121
121
  "Ensure 10 users are locked")
122
122
 
123
+ It is also possible to pass an array as the where clause instead of a string. In this case, the first element of the array should be a string containing the where clause with bind variable placeholders. The remaining elements of the array are the bind variables. Ruby types are automatically converted to Oracle types by SimpleOracleJDBC behind the scenes. For example:
124
+
125
+ assert_table_has_many_rows("users",
126
+ 10
127
+ ["where status = ?", 'locked']
128
+ "Ensure 10 users are locked")
129
+
130
+
123
131
  ## Set The Database Interface
124
132
 
125
133
  An additional class method is available on Test::Unit::TestCase called set_db_interface. This stores the passed in object in @@db_interface. As this is a class variable, it is shared by all classes that sub-class Test::Unit::TestCase.
data/README.md~ ADDED
@@ -0,0 +1,153 @@
1
+ # PLSQL Unit Test
2
+
3
+ This gem is intended to be used to test PLSQL code. Most of the test framework is provided by Test::Unit, and this gem simply adds a few convenience methods that are useful when unit testing PLSQL code.
4
+
5
+ # Dependencies
6
+
7
+ This gem depends on:
8
+
9
+ * [SimpleOracleJDBC](http://rubygems.org/gems/simpleOracleJDBC) to provide a JDBC interface to Oracle
10
+ * [Data_Factory](http://rubygems.org/gems/data_factory) to provide an mechanism for generating test data
11
+ * The Oracle ojdbc6.jar drivers should be in the jruby lib directory
12
+
13
+ The gem also requires JRuby, mostly because SimpleOracleJDBC requires JRuby. It would be possible to make it run in MRI Ruby, but a different database interface would be required, using perhaps OCI8.
14
+
15
+ # How to Create a PLSQL Unit Test Suite
16
+
17
+ ## Test Helper
18
+
19
+ First, create a new directory for the tests. Then create a file called test_helper.rb, it should contain something like the following:
20
+
21
+ require 'rubygems'
22
+ require 'plsql_unit_test'
23
+
24
+ PLSQLUnitTest::Setup.connect('sodonnel', # user
25
+ 'sodonnell', # password
26
+ 'local11gr2.world', # service
27
+ 'localhost', # IP address
28
+ '1521') # port
29
+
30
+ This code does two things. It loads the plsql\_unit\_test gem (which also requires SimpleOracleJDBC and data_factory), and then establishes a database interface / connection. The database interface is provided by an instance of SimpleOracleJDBC::Interface - check out the documentation of SimpleOracleJDBC to understand how to use it.
31
+
32
+ This single database interface is shared across all the test classes in the test suite. It is actually stored in a class instance variable called @@db_interface within the Test::Unit::TestCase class.
33
+
34
+ ## Creating a Test
35
+
36
+ The test framework is all provided by Test::Unit, so tests can be coded in exactly the same way as usual - have a look at the Test::Unit documentation to learn about all the features of Test::Unit. An example of a very simple test is as follows:
37
+
38
+ require './test_helper'
39
+
40
+ class FirstTest < Test::Unit::TestCase
41
+
42
+ def setup
43
+ end
44
+
45
+ def teardown
46
+ end
47
+
48
+ def test_db_connection_works
49
+ query = @@db_interface.execute_sql("select 1 from dual")
50
+ results = query.all_array
51
+
52
+ assert_equal(1, results.length, 'There should be one row in the result set')
53
+ assert_equal(1, results[0][0], 'The first and only row in the result set should contain the value 1')
54
+ end
55
+
56
+ end
57
+
58
+ There are two important points:
59
+
60
+ * Notice that the test_helper file is required as the first line of code. This is important as it connects to the database and loads the other required modules.
61
+ * The variable @@db_interface is available for database interactions
62
+
63
+ ## Running a Test
64
+
65
+ As with simple Test::Unit test suites, tests can be executed by simply passing the test filename to JRuby:
66
+
67
+ $ jruby first_test_test.rb
68
+ Run options:
69
+
70
+ # Running tests:
71
+
72
+ .
73
+
74
+ Finished tests in 0.125000s, 8.0000 tests/s, 16.0000 assertions/s.
75
+
76
+ 1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
77
+
78
+ ## Test Runner
79
+
80
+ Ideally, there should be one Ruby test class for each PLSQL procedure, function or package under test. In a large application there could be many files, so there needs to be a way to run all the tests in the suite. Create a file called test_runner.rb in the same directory as the tests, and put the following code in it:
81
+
82
+ current_dir = File.expand_path(File.dirname(__FILE__))
83
+
84
+ # Find all files that end in _test.rb and require them ...
85
+ files = Dir.entries(current_dir).grep(/^[^#].+_test\.rb$/).sort
86
+ files.each do |f|
87
+ require File.join(current_dir, f)
88
+ end
89
+
90
+ Now all the test files in the directory can be executed with a single command:
91
+
92
+ $ jruby test_runner.rb
93
+
94
+ For this code to work, all files that contain tests should have filenames that end in _test.rb.
95
+
96
+ # Additional Methods in Test::Unit::TestCase
97
+
98
+ PLSQL\_Unit\_Test adds a few extra methods to Test::Unit.
99
+
100
+ ## Assert Methods
101
+
102
+ When testing database code, it can be useful to ensure a given table has zero, one or a number of rows for a given where clause.
103
+
104
+ To assert the users table has a single row for the username foouser:
105
+
106
+ assert_table_has_one_row("users",
107
+ "where username = 'foouser',
108
+ "Ensure the users table has a single row")
109
+
110
+ Similarly, to ensure the users table does not have a row:
111
+
112
+ assert_table_has_zero_rows("users",
113
+ "where username = 'foouser',
114
+ "Ensure the users table zero rows")
115
+
116
+ Finally, to check a table has a given number of rows:
117
+
118
+ assert_table_has_zero_rows("users",
119
+ 10
120
+ "where status = 'locked'
121
+ "Ensure 10 users are locked")
122
+
123
+ ## Set The Database Interface
124
+
125
+ An additional class method is available on Test::Unit::TestCase called set_db_interface. This stores the passed in object in @@db_interface. As this is a class variable, it is shared by all classes that sub-class Test::Unit::TestCase.
126
+
127
+ Test::Unit::TestCase.set_db_interface(my_db_interface)
128
+
129
+ ## Oracle Dates and Times
130
+
131
+ Two further helper methods are available to format a Ruby Time object as an Oracle to_date string:
132
+
133
+ # Return a string representing the passed in Time object
134
+ # as an Oracle to_date string, down to the second
135
+ def time_as_oracle_dtm(time)
136
+ "to_date('#{time.strftime('%Y%m%d %H:%M:%S')}', 'YYYYMMDD HH24:MI:SS')"
137
+ end
138
+
139
+ # Return a string representing the passed in Time object
140
+ # as an Oracle to_date string, down to the day
141
+ def time_as_oracle_dt(time)
142
+ "to_date('#{time.strftime('%Y%m%d')}', 'YYYYMMDD')"
143
+ end
144
+
145
+ # The Setup Class
146
+
147
+ The only other class in PLSQL\_Unit\_Test is the setup class, and it contains a single class method:
148
+
149
+ def self.connect(user, password, service, host, port)
150
+ # ...
151
+ end
152
+
153
+ It takes the given parameters, creates an instance of SimpleOracleJDBC and passes it to both Test::Unit::TestCase and DataFactory::Base via their set_database_interface methods.
@@ -1,55 +1,88 @@
1
1
  class Test::Unit::TestCase
2
2
 
3
- # Sets the class instance variable @@db_interface to the
3
+ # Sets the class instance variable @@db_interface to the
4
4
  # object that is passed in
5
5
  def self.set_database_interface(interface)
6
6
  @@db_interface = interface
7
7
  end
8
8
 
9
9
  # Used to assert / test a given table has only a single row.
10
- # If a where clause is passed, it should start with 'where'. The table
10
+ # If a where clause is passed, it should start with 'where'. The table
11
11
  # name and where clause are used to form a select statement in the form:
12
12
  #
13
13
  # "select count(*) from #{table} #{where_clause}"
14
14
  #
15
15
  # @example Assert the users table has a single row for user foouser
16
- # assert_table_has_one_row('users',
16
+ # assert_table_has_one_row('users',
17
17
  # "where username = 'foouser'",
18
18
  # "Ensure the users table has a single row")
19
- #
19
+ #
20
+ # It is possible to pass an array for the where clause, where the first
21
+ # element is the where string with bind placeholders, and the remaining
22
+ # elements are the bind variables:
23
+ #
24
+ # @example Assert the users table has a single row for user foouser
25
+ # assert_table_has_one_row('users',
26
+ # ["where username = ?", 'foouser'],
27
+ # "Ensure the users table has a single row")
28
+ #
20
29
  def assert_table_has_one_row(table, where_clause=nil, message=nil)
21
30
  assert_table_has_many_rows(table, 1, where_clause, message)
22
31
  end
23
32
 
24
33
  # Used to assert / test a given table has zero rows.
25
- # If a where clause is passed, it should start with 'where'. The table
34
+ # If a where clause is passed, it should start with 'where'. The table
26
35
  # name and where clause are used to form a select statement in the form:
27
36
  #
28
37
  # "select count(*) from #{table} #{where_clause}"
29
38
  #
30
39
  # @example Assert the users table has zero rows for user foouser
31
- # assert_table_has_zero_rows('users',
40
+ # assert_table_has_zero_rows('users',
32
41
  # "where username = 'foouser'",
33
42
  # "Ensure the users table has zero rows")
34
- #
43
+ #
44
+ # It is possible to pass an array for the where clause, where the first
45
+ # element is the where string with bind placeholders, and the remaining
46
+ # elements are the bind variables:
47
+ #
48
+ # @example Assert the users table has a single row for user foouser
49
+ # assert_table_has_zero_row('users',
50
+ # ["where username = ?", 'foouser'],
51
+ # "Ensure the users table has zero rows")
52
+ #
35
53
  def assert_table_has_zero_rows(table, where_clause=nil, message=nil)
36
54
  assert_table_has_many_rows(table, 0, where_clause, message)
37
55
  end
38
56
 
39
57
  # Used to assert / test a given table has a given number of rows.
40
- # If a where clause is passed, it should start with 'where'. The table
58
+ # If a where clause is passed, it should start with 'where'. The table
41
59
  # name and where clause are used to form a select statement in the form:
42
60
  #
43
61
  # "select count(*) from #{table} #{where_clause}"
44
62
  #
45
63
  # @example Assert the users table has zero rows for user foouser
46
- # assert_table_has_many_rows('users',
64
+ # assert_table_has_many_rows('users',
47
65
  # 10
48
66
  # "where status = 'locked'",
49
67
  # "Ensure the users table has 10 locked rows")
50
- #
68
+ #
69
+ # It is possible to pass an array for the where clause, where the first
70
+ # element is the where string with bind placeholders, and the remaining
71
+ # elements are the bind variables:
72
+ #
73
+ # @example Assert the users table has a single row for user foouser
74
+ # assert_table_has_many_rows('users',
75
+ # ["where status = ?", 'locked'],
76
+ # "Ensure the users table has 10 locked rows")
77
+ #
51
78
  def assert_table_has_many_rows(table, row_count, where_clause=nil, message=nil)
52
- results = @@db_interface.execute_sql("select count(*) from #{table} #{where_clause}").all_array
79
+ where = where_clause
80
+ binds = Array.new
81
+ if where_clause and where_clause.is_a? Array
82
+ where = where_clause.shift
83
+ binds = where_clause
84
+ end
85
+ results = @@db_interface.execute_sql("select count(*) from #{table} #{where}", *binds).all_array
53
86
  message = build_message(message, "A count of <?> was expected but was <?> for <?> <?>", row_count.to_s, results[0][0].to_i, table, where_clause)
54
87
  assert_block(message) do
55
88
  row_count == results[0][0].to_i
@@ -68,4 +101,4 @@ class Test::Unit::TestCase
68
101
  "to_date('#{time.strftime('%Y%m%d')}', 'YYYYMMDD')"
69
102
  end
70
103
 
71
- end
104
+ end
@@ -0,0 +1,71 @@
1
+ class Test::Unit::TestCase
2
+
3
+ # Sets the class instance variable @@db_interface to the
4
+ # object that is passed in
5
+ def self.set_database_interface(interface)
6
+ @@db_interface = interface
7
+ end
8
+
9
+ # Used to assert / test a given table has only a single row.
10
+ # If a where clause is passed, it should start with 'where'. The table
11
+ # name and where clause are used to form a select statement in the form:
12
+ #
13
+ # "select count(*) from #{table} #{where_clause}"
14
+ #
15
+ # @example Assert the users table has a single row for user foouser
16
+ # assert_table_has_one_row('users',
17
+ # "where username = 'foouser'",
18
+ # "Ensure the users table has a single row")
19
+ #
20
+ def assert_table_has_one_row(table, where_clause=nil, message=nil)
21
+ assert_table_has_many_rows(table, 1, where_clause, message)
22
+ end
23
+
24
+ # Used to assert / test a given table has zero rows.
25
+ # If a where clause is passed, it should start with 'where'. The table
26
+ # name and where clause are used to form a select statement in the form:
27
+ #
28
+ # "select count(*) from #{table} #{where_clause}"
29
+ #
30
+ # @example Assert the users table has zero rows for user foouser
31
+ # assert_table_has_zero_rows('users',
32
+ # "where username = 'foouser'",
33
+ # "Ensure the users table has zero rows")
34
+ #
35
+ def assert_table_has_zero_rows(table, where_clause=nil, message=nil)
36
+ assert_table_has_many_rows(table, 0, where_clause, message)
37
+ end
38
+
39
+ # Used to assert / test a given table has a given number of rows.
40
+ # If a where clause is passed, it should start with 'where'. The table
41
+ # name and where clause are used to form a select statement in the form:
42
+ #
43
+ # "select count(*) from #{table} #{where_clause}"
44
+ #
45
+ # @example Assert the users table has zero rows for user foouser
46
+ # assert_table_has_many_rows('users',
47
+ # 10
48
+ # "where status = 'locked'",
49
+ # "Ensure the users table has 10 locked rows")
50
+ #
51
+ def assert_table_has_many_rows(table, row_count, where_clause=nil, message=nil)
52
+ results = @@db_interface.execute_sql("select count(*) from #{table} #{where_clause}").all_array
53
+ message = build_message(message, "A count of <?> was expected but was <?> for <?> <?>", row_count.to_s, results[0][0].to_i, table, where_clause)
54
+ assert_block(message) do
55
+ row_count == results[0][0].to_i
56
+ end
57
+ end
58
+
59
+ # Returns a string representing an Ruby Time object in Oracle to_date
60
+ # format, accurate to a second.
61
+ def time_as_oracle_dtm(time)
62
+ "to_date('#{time.strftime('%Y%m%d %H:%M:%S')}', 'YYYYMMDD HH24:MI:SS')"
63
+ end
64
+
65
+ # Returns a string representing an Ruby Time object in Oracle to_date
66
+ # format, accurate to a day.
67
+ def time_as_oracle_dt(time)
68
+ "to_date('#{time.strftime('%Y%m%d')}', 'YYYYMMDD')"
69
+ end
70
+
71
+ end
metadata CHANGED
@@ -1,86 +1,94 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plsql_unit_test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
5
- prerelease:
4
+ version: 0.2.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Stephen O'Donnell
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-17 00:00:00.000000000 Z
12
+ date: 2013-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: data_factory
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
16
+ version_requirements: !ruby/object:Gem::Requirement
18
17
  requirements:
19
18
  - - ! '>='
20
19
  - !ruby/object:Gem::Version
21
20
  version: 0.1.2
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
21
  none: false
22
+ requirement: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 0.1.2
27
+ none: false
28
+ prerelease: false
29
+ type: :runtime
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: simpleOracleJDBC
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
32
+ version_requirements: !ruby/object:Gem::Requirement
34
33
  requirements:
35
34
  - - ! '>='
36
35
  - !ruby/object:Gem::Version
37
- version: 0.1.1
38
- type: :runtime
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
36
+ version: 0.3.0
41
37
  none: false
38
+ requirement: !ruby/object:Gem::Requirement
42
39
  requirements:
43
40
  - - ! '>='
44
41
  - !ruby/object:Gem::Version
45
- version: 0.1.1
46
- description: Monkey patches Test::Unit::TestCase to add some additional assert methods,
47
- a global database_interface object (via a class variable) and a few helper functions
48
- designed to enable plsql unit testing
42
+ version: 0.3.0
43
+ none: false
44
+ prerelease: false
45
+ type: :runtime
46
+ description: Monkey patches Test::Unit::TestCase to add some additional assert methods, a global database_interface object (via a class variable) and a few helper functions designed to enable plsql unit testing
49
47
  email: stephen@betteratoracle.com
50
48
  executables: []
51
49
  extensions: []
52
50
  extra_rdoc_files:
53
51
  - README.md
54
52
  files:
55
- - lib/plsql_unit_test/setup.rb
56
- - lib/plsql_unit_test/test_unit_patch.rb
57
- - lib/plsql_unit_test.rb
58
- - Rakefile.rb
59
- - README.md
53
+ - !binary |-
54
+ bGliL3Bsc3FsX3VuaXRfdGVzdC5yYg==
55
+ - !binary |-
56
+ bGliL3Bsc3FsX3VuaXRfdGVzdC9zZXR1cC5yYg==
57
+ - !binary |-
58
+ bGliL3Bsc3FsX3VuaXRfdGVzdC90ZXN0X3VuaXRfcGF0Y2gucmI=
59
+ - !binary |-
60
+ bGliL3Bsc3FsX3VuaXRfdGVzdC90ZXN0X3VuaXRfcGF0Y2gucmJ+
61
+ - !binary |-
62
+ UmFrZWZpbGUucmI=
63
+ - !binary |-
64
+ UkVBRE1FLm1k
65
+ - !binary |-
66
+ UkVBRE1FLm1kfg==
60
67
  homepage: http://betteratoracle.com
61
68
  licenses: []
62
- post_install_message:
69
+ post_install_message:
63
70
  rdoc_options: []
64
71
  require_paths:
65
72
  - lib
66
73
  required_ruby_version: !ruby/object:Gem::Requirement
67
- none: false
68
74
  requirements:
69
75
  - - ! '>='
70
76
  - !ruby/object:Gem::Version
71
- version: '0'
72
- required_rubygems_version: !ruby/object:Gem::Requirement
77
+ version: !binary |-
78
+ MA==
73
79
  none: false
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
81
  requirements:
75
82
  - - ! '>='
76
83
  - !ruby/object:Gem::Version
77
- version: '0'
84
+ version: !binary |-
85
+ MA==
86
+ none: false
78
87
  requirements: []
79
- rubyforge_project:
80
- rubygems_version: 1.8.24
81
- signing_key:
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.25
90
+ signing_key:
82
91
  specification_version: 3
83
- summary: A gem that monkey patches Test::Unit::TestCase to add some features to allow
84
- unit testing of PLSQL code
92
+ summary: A gem that monkey patches Test::Unit::TestCase to add some features to allow unit testing of PLSQL code
85
93
  test_files: []
86
94
  has_rdoc: true