dbtap 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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +2 -0
- data/bin/dbtap +4 -0
- data/dbtap.gemspec +25 -0
- data/examples/basic_example.rb +18 -0
- data/lib/dbtap/cli.rb +15 -0
- data/lib/dbtap/tapper.rb +72 -0
- data/lib/dbtap/testers/performs_within.rb +53 -0
- data/lib/dbtap/testers/set_eq.rb +52 -0
- data/lib/dbtap/testers/tester.rb +21 -0
- data/lib/dbtap/version.rb +3 -0
- data/lib/dbtap.rb +23 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8ff6f5b046d3324a54837496af2f0727b541a34f
|
4
|
+
data.tar.gz: 42f106382e26df6a255f32172f5e9f5c0423745a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e464b3b5d0f57c32185d6029381c9cd6442037527854d7e75134c8ad240f62ab39b70dde72be71bebc0f4c46738d5c1c6a5977de4cbf714156ec4eefa2eae910
|
7
|
+
data.tar.gz: 8ee1dd7ca87dc7ced01251f65fa250dc06eea9f67db701ad93c9760c63e6a1baf7d5d553cfde7d982e8c1f9bf29e03fa62921542e9e2746ecc94651555da5bd5
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Outcomes Insights, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Dbtap
|
2
|
+
|
3
|
+
Dbtap aims to eventually be a database-agnostic replacement for the __amazing__ [pgTAP](http://pgtap.org/)
|
4
|
+
|
5
|
+
## Why?
|
6
|
+
|
7
|
+
[One of my projects](https://github.com/outcomesinsights/conceptql) started off using PostgreSQL as its sole RDBMS. I had employed pgTAP to run the [tests for that project](https://github.com/outcomesinsights/test_conceptql) and was __very__ happy. But, sadly, other databases needed to be supported and so my tests would no longer run against those new RDBMSs.
|
8
|
+
|
9
|
+
But fortunately, [Sequel](http://sequel.jeremyevans.net/) exists and is great for writing database-agnostic SQL. I am now porting over any functions I liked in pgTAP over into Dbtap.
|
10
|
+
|
11
|
+
I'll probably never need the majority of functions that pgTAP provides, meaning I won't be porting them over myself, but I'll update this library as my needs arise.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
gem 'dbtap'
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install dbtap
|
26
|
+
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
1. Define a set of tests in a ruby file (see the examples directory)
|
31
|
+
2. Run that file using Dbtap's command line tool, `dbtap`
|
32
|
+
- e.g. `dbtap run_file my_test_file.rb`
|
33
|
+
3. Marvel at the TAP-compatible output that issues forth
|
34
|
+
|
35
|
+
|
36
|
+
## Contributing
|
37
|
+
|
38
|
+
1. Fork it ( http://github.com/outcomesinsights/dbtap/fork )
|
39
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
40
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
41
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
42
|
+
5. Create new Pull Request
|
43
|
+
|
44
|
+
## Thanks
|
45
|
+
|
46
|
+
- [Outcomes Insights, Inc.](http://outins.com)
|
47
|
+
- Many thanks for allowing me to release a portion of my work as Open Source Software!
|
48
|
+
- David E. Wheeler
|
49
|
+
- For writing [pgTAP](http://pgtap.org/)!
|
50
|
+
- Jeremy Evans
|
51
|
+
- For writing [Sequel](http://sequel.jeremyevans.net/)!
|
52
|
+
|
53
|
+
## License
|
54
|
+
Released under the MIT license, Copyright (c) 2014 Outcomes Insights, Inc.
|
data/Rakefile
ADDED
data/bin/dbtap
ADDED
data/dbtap.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dbtap/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dbtap"
|
8
|
+
spec.version = Dbtap::VERSION
|
9
|
+
spec.authors = ["Ryan Duryea"]
|
10
|
+
spec.email = ["aguynamedryan@gmail.com"]
|
11
|
+
spec.summary = %q{Write database-agnostic, TAP-emitting unit tests for your database}
|
12
|
+
spec.description = %q{A database-agnostic reimplementation of my favorite methods from pgTAP}
|
13
|
+
spec.homepage = "https://github.com/outcomesinsights/dbtap"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.3"
|
23
|
+
spec.add_dependency 'thor', '~> 0.19'
|
24
|
+
spec.add_dependency 'sequelizer', '~> 0.0', '>= 0.0.3'
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Use the `dbtap` command line utility to run this file, e.g.:
|
2
|
+
# bundle exec dbtap run_test examples/basic_example.rb
|
3
|
+
|
4
|
+
# Start defining a set of tests
|
5
|
+
define_tests do
|
6
|
+
# Test if these two queries return the same set of rows
|
7
|
+
set_eq(db[:person], db[:person], 'person should equal self')
|
8
|
+
# See if this query runs within 1.0 seconds (plus or minus 0.99999)
|
9
|
+
performs_within(db[:person], 1.0, 0.99999, 'person should be quick')
|
10
|
+
end
|
11
|
+
|
12
|
+
# Define another set of results
|
13
|
+
define_tests do
|
14
|
+
set_eq(db['SELECT * FROM "person"'], db[:person], 'person should equal text-based self')
|
15
|
+
set_eq(db['SELECT * FROM "person"'], db['SELECT * FROM "person"'], 'text-based person should equal text-based self')
|
16
|
+
set_eq(db[:person], db[:person].limit(1), 'person should equal self')
|
17
|
+
performs_within(db[:person], 1.0, 0.99999, 'person should be quick')
|
18
|
+
end
|
data/lib/dbtap/cli.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative '../dbtap'
|
3
|
+
|
4
|
+
module Dbtap
|
5
|
+
class CLI < Thor
|
6
|
+
include Dbtap
|
7
|
+
|
8
|
+
desc 'run_test file1 [file2 ...]', 'runs tests in the selected file(s)'
|
9
|
+
def run_test(*files)
|
10
|
+
files.flatten.each do |file|
|
11
|
+
instance_eval(File.read(file))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/dbtap/tapper.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'sequelizer'
|
2
|
+
|
3
|
+
module Dbtap
|
4
|
+
# The Tapper class provides the DSL for Dbtap#define_tests
|
5
|
+
#
|
6
|
+
# It also drives the evaluation of all the tests via #run
|
7
|
+
class Tapper
|
8
|
+
include Sequelizer
|
9
|
+
|
10
|
+
attr :tests
|
11
|
+
def initialize
|
12
|
+
@tests = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# Drives the evaluation of each test, emitting TAP-compliant messages
|
16
|
+
# for each test
|
17
|
+
def run
|
18
|
+
puts (1..tests.length).to_s
|
19
|
+
tests.each_with_index do |test, i|
|
20
|
+
if test.is_ok?
|
21
|
+
ok(test, i)
|
22
|
+
else
|
23
|
+
not_ok(test, i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
# Emits a TAP-compliant OK message
|
30
|
+
def ok(test, i)
|
31
|
+
message = "ok #{i + 1}"
|
32
|
+
message += ' - ' + test.name if test.name
|
33
|
+
puts message
|
34
|
+
end
|
35
|
+
|
36
|
+
# Emits a TAP-compliant NOT OK message
|
37
|
+
def not_ok(test, i)
|
38
|
+
message = "not ok #{i + 1}"
|
39
|
+
message += ' - ' + test.name if test.name
|
40
|
+
message += "\n " + test.errors.split.join("\n ") if test.errors
|
41
|
+
puts message
|
42
|
+
end
|
43
|
+
|
44
|
+
# When dbtap is gem, this will require testers from the proper
|
45
|
+
# relative path
|
46
|
+
def local_require(file)
|
47
|
+
path = base_dir + 'testers' + file.to_s
|
48
|
+
require_relative path
|
49
|
+
end
|
50
|
+
|
51
|
+
# When we install dbtap as a gem, it will need to refer to the testers
|
52
|
+
# directory, so we'll first find where the gem lives
|
53
|
+
def base_dir
|
54
|
+
Pathname.new(__FILE__).dirname
|
55
|
+
end
|
56
|
+
|
57
|
+
# The following methods are hard-coded, and used to instantiate
|
58
|
+
# each type of test. I imagine I can do some sort of thing where
|
59
|
+
# each Tester class can register with Tapper to get dynamically create
|
60
|
+
# a set of methods for Tapper to use, but for now, this is my approach
|
61
|
+
def set_eq(*args)
|
62
|
+
local_require(:set_eq)
|
63
|
+
tests << SetEq.new(*args)
|
64
|
+
end
|
65
|
+
|
66
|
+
def performs_within(*args)
|
67
|
+
local_require(:performs_within)
|
68
|
+
tests << PerformsWithin.new(*args)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require_relative 'tester'
|
3
|
+
|
4
|
+
module Dbtap
|
5
|
+
# Tests if a query performs within a certain period of time.
|
6
|
+
#
|
7
|
+
# Each query is run ten times and
|
8
|
+
#
|
9
|
+
# This is useful for benchmarking, and will verify that a query ran
|
10
|
+
# neither too slow nor too fast.
|
11
|
+
class PerformsWithin < Tester
|
12
|
+
attr :expected_time, :query, :elapsed_time, :delta
|
13
|
+
# +query+ - The query to benchmark
|
14
|
+
# +expected_time+ - The average expected time to run the query once (in milliseconds)
|
15
|
+
# +delta+ - The amount of time + or - that the query is allowed to deviate (in milliseconds)
|
16
|
+
# +name+ - (optional) the name of the test
|
17
|
+
def initialize(query, expected_time, delta, name = nil)
|
18
|
+
@name = name
|
19
|
+
@query = query
|
20
|
+
@expected_time = expected_time
|
21
|
+
@delta = delta
|
22
|
+
end
|
23
|
+
|
24
|
+
def ok?
|
25
|
+
(expected_time - elapsed_time).abs.to_f / repetitions <= delta
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors
|
29
|
+
output = []
|
30
|
+
output << " average runtime: #{elapsed_time} ms"
|
31
|
+
output << " desired average: #{expected_time} +/- #{delta} ms"
|
32
|
+
|
33
|
+
output.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def elapsed_time
|
38
|
+
@elapsed_time ||= bench_it
|
39
|
+
end
|
40
|
+
|
41
|
+
def bench_it
|
42
|
+
Benchmark.realtime do
|
43
|
+
repetitions.times do
|
44
|
+
query.count
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def repetitions
|
50
|
+
10
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'tester'
|
2
|
+
|
3
|
+
module Dbtap
|
4
|
+
# Tests to see if two sets of results are equal
|
5
|
+
#
|
6
|
+
# Sets is a bit of a misnomer in that if a query returns duplicate rows,
|
7
|
+
# those rows are NOT deduplicated.
|
8
|
+
#
|
9
|
+
# The order in which either query returns the results is ignored when testing
|
10
|
+
# for equality.
|
11
|
+
class SetEq < Tester
|
12
|
+
attr :actual, :expected
|
13
|
+
|
14
|
+
# +actual+ - The query being tested
|
15
|
+
# +expected+ - The set of results expected. Should be another query.
|
16
|
+
# +name+ - (optional) the name of the test
|
17
|
+
def initialize(actual, expected, name = nil)
|
18
|
+
@name = name
|
19
|
+
@actual = actual
|
20
|
+
@expected = expected
|
21
|
+
end
|
22
|
+
|
23
|
+
def ok?
|
24
|
+
missing.empty? && extras.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
output = []
|
29
|
+
unless missing.empty?
|
30
|
+
output << "Missing #{missing.count}/#{expected_count} Records:\n " + missing.first.inspect
|
31
|
+
end
|
32
|
+
|
33
|
+
unless extras.empty?
|
34
|
+
output << "Extra #{extras.count} over #{expected_count} Records:\n " + extras.first.inspect
|
35
|
+
end
|
36
|
+
output.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def missing
|
41
|
+
@missing ||= expected.except(actual).all
|
42
|
+
end
|
43
|
+
|
44
|
+
def extras
|
45
|
+
@extras ||= actual.except(expected).all
|
46
|
+
end
|
47
|
+
|
48
|
+
def expected_count
|
49
|
+
@expected_count = expected.count
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Dbtap
|
2
|
+
# Parent class to all classes that provide some sort of test
|
3
|
+
#
|
4
|
+
# Child classes must provide an <tt>ok?</tt> method which returns
|
5
|
+
# true if the test passes, or false otherwise
|
6
|
+
#
|
7
|
+
# Child classes can opt to provide an <tt>errors</tt> method with
|
8
|
+
# should return a string with any error information relavent to the test
|
9
|
+
class Tester
|
10
|
+
attr :name
|
11
|
+
|
12
|
+
def is_ok?
|
13
|
+
ok?
|
14
|
+
rescue
|
15
|
+
puts "Bail out! #{$!.message}"
|
16
|
+
puts $!.backtrace.join("\n")
|
17
|
+
raise
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/lib/dbtap.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "dbtap/version"
|
2
|
+
require "dbtap/tapper"
|
3
|
+
|
4
|
+
module Dbtap
|
5
|
+
# Starts a new set of tests. Use like so:
|
6
|
+
#
|
7
|
+
# require 'dbtap'
|
8
|
+
# include Dbtap
|
9
|
+
#
|
10
|
+
# define_tests do
|
11
|
+
# set_eq(db[:table], db['select * from table'],
|
12
|
+
# 'Sequel selects all from table')
|
13
|
+
# # Your other tests here
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Within the block, `db` is defined as a Sequel-based connection
|
17
|
+
# to your database as defined by your Sequelizer configuration
|
18
|
+
def define_tests(&block)
|
19
|
+
t = Tapper.new
|
20
|
+
t.instance_eval(&block)
|
21
|
+
t.run
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dbtap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Duryea
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.19'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.19'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sequelizer
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.0'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 0.0.3
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0.0'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.0.3
|
75
|
+
description: A database-agnostic reimplementation of my favorite methods from pgTAP
|
76
|
+
email:
|
77
|
+
- aguynamedryan@gmail.com
|
78
|
+
executables:
|
79
|
+
- dbtap
|
80
|
+
extensions: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
files:
|
83
|
+
- ".gitignore"
|
84
|
+
- CHANGELOG.md
|
85
|
+
- Gemfile
|
86
|
+
- LICENSE.txt
|
87
|
+
- README.md
|
88
|
+
- Rakefile
|
89
|
+
- bin/dbtap
|
90
|
+
- dbtap.gemspec
|
91
|
+
- examples/basic_example.rb
|
92
|
+
- lib/dbtap.rb
|
93
|
+
- lib/dbtap/cli.rb
|
94
|
+
- lib/dbtap/tapper.rb
|
95
|
+
- lib/dbtap/testers/performs_within.rb
|
96
|
+
- lib/dbtap/testers/set_eq.rb
|
97
|
+
- lib/dbtap/testers/tester.rb
|
98
|
+
- lib/dbtap/version.rb
|
99
|
+
homepage: https://github.com/outcomesinsights/dbtap
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
metadata: {}
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.2.2
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: Write database-agnostic, TAP-emitting unit tests for your database
|
123
|
+
test_files: []
|
124
|
+
has_rdoc:
|