ditto 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/CHANGELOG +1 -0
- data/README +11 -0
- data/bin/ditto +4 -0
- data/ditto.gemspec +16 -0
- data/features/create_entities.feature +81 -0
- data/features/load_entity.feature +33 -0
- data/features/step_definitions/definition_steps.rb +21 -0
- data/features/support/hooks.rb +3 -0
- data/lib/ditto.rb +3 -0
- data/lib/ditto/dsl.rb +13 -0
- data/lib/ditto/entity.rb +34 -0
- data/lib/ditto/options.rb +33 -0
- data/lib/ditto/runner.rb +13 -0
- data/rakefile +8 -0
- data/samples/simple_object.xml +23 -0
- data/samples/simple_object.yaml +21 -0
- data/samples/simple_object_seq.yaml +18 -0
- data/samples/simple_object_sym.yaml +19 -0
- data/spec/options_spec.rb +31 -0
- metadata +99 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Version 0.0.1: Initial attempts
|
data/README
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Database Independent Test Objects (Ditto)
|
2
|
+
|
3
|
+
Ditto defines a simple DSL that allows test data to be expressed in a database independent format. When the underlying tables are remapped the QA team don't have to go and change all the historical test cases.
|
4
|
+
|
5
|
+
There are two parts, both of them versioned:
|
6
|
+
1. The data declarations
|
7
|
+
2. The mappings to the underlying database
|
8
|
+
|
9
|
+
Idea is to replace an XML dialect with something simpler. See sample at simple_object.xml
|
10
|
+
|
11
|
+
Nick Townsend, Oct 2012
|
data/bin/ditto
ADDED
data/ditto.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'ditto'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2012-10-12'
|
5
|
+
s.summary = "Database independent test objects"
|
6
|
+
s.description = File.read(File.join(File.dirname(__FILE__), 'README'))
|
7
|
+
s.authors = ["Nick Townsend"]
|
8
|
+
s.email = 'nick.townsend@mac.com'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.required_ruby_version = '>=1.9'
|
11
|
+
s.files = Dir['**/**']
|
12
|
+
s.homepage = 'http://rubygems.org/gems/ditto'
|
13
|
+
# s.add_runtime_dependency "daemons", ["= 1.1.0"]
|
14
|
+
s.add_development_dependency "rspec", [">= 0"]
|
15
|
+
s.has_rdoc = false
|
16
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
Feature: Ditto parses simple entities
|
2
|
+
In order to create test data definitions
|
3
|
+
As a user of Ditto
|
4
|
+
I want to load data entity definitions
|
5
|
+
|
6
|
+
Scenario: Ditto parses a single correct entity
|
7
|
+
Given a file named "simple_entity.rb" with:
|
8
|
+
"""
|
9
|
+
require 'ditto'
|
10
|
+
|
11
|
+
entity :currency, {
|
12
|
+
code: [ :mandatory, :unique ],
|
13
|
+
description: nil,
|
14
|
+
exchange_rate: :mandatory,
|
15
|
+
is_designated: nil,
|
16
|
+
}
|
17
|
+
check!
|
18
|
+
"""
|
19
|
+
When I run "simple_entity.rb"
|
20
|
+
Then the exit code should be 0
|
21
|
+
And the stdout should be
|
22
|
+
"""
|
23
|
+
Entities:
|
24
|
+
currency
|
25
|
+
1 entities, 0 relationships, 0 errors
|
26
|
+
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: Ditto parses a faulty entity attribute
|
30
|
+
Given a file named "faulty_attribute.rb" with:
|
31
|
+
"""
|
32
|
+
require 'ditto'
|
33
|
+
|
34
|
+
entity :currency, {
|
35
|
+
code: [ :mandatory, :unique, :radar ],
|
36
|
+
description: nil,
|
37
|
+
exchange_rate: :mandatory,
|
38
|
+
is_designated: nil,
|
39
|
+
}
|
40
|
+
check!
|
41
|
+
"""
|
42
|
+
When I run "faulty_attribute.rb"
|
43
|
+
Then the exit code should be 1
|
44
|
+
And the stdout should be
|
45
|
+
"""
|
46
|
+
Entities:
|
47
|
+
currency
|
48
|
+
unknown properties: radar
|
49
|
+
1 entities, 0 relationships, 1 errors
|
50
|
+
|
51
|
+
"""
|
52
|
+
|
53
|
+
Scenario: Ditto parses a correct entity relationship
|
54
|
+
Given a file named "simple_relationship.rb" with:
|
55
|
+
"""
|
56
|
+
require 'ditto'
|
57
|
+
|
58
|
+
entity :currency, {
|
59
|
+
code: [ :mandatory, :unique ],
|
60
|
+
description: nil,
|
61
|
+
exchange_rate: :mandatory,
|
62
|
+
is_designated: nil,
|
63
|
+
currency_group: :related
|
64
|
+
}
|
65
|
+
entity :currency_group, {
|
66
|
+
:code => [ :mandatory, :unique ],
|
67
|
+
:description => nil,
|
68
|
+
:is_commodity => nil
|
69
|
+
}
|
70
|
+
check!
|
71
|
+
"""
|
72
|
+
When I run "simple_relationship.rb"
|
73
|
+
Then the exit code should be 0
|
74
|
+
And the stdout should be
|
75
|
+
"""
|
76
|
+
Entities:
|
77
|
+
currency
|
78
|
+
currency_group
|
79
|
+
2 entities, 1 relationships, 0 errors
|
80
|
+
|
81
|
+
"""
|
@@ -0,0 +1,33 @@
|
|
1
|
+
Feature: Ditto loads simple entities
|
2
|
+
In order to create test data
|
3
|
+
As a user of Ditto
|
4
|
+
I want to load data definitions
|
5
|
+
|
6
|
+
Scenario: Ditto loads a simple entity
|
7
|
+
Given a file named "simple_entity_data.rb" with:
|
8
|
+
"""
|
9
|
+
version: 1.0.0
|
10
|
+
date: 2012-10-13
|
11
|
+
---
|
12
|
+
currency:
|
13
|
+
code: GBP
|
14
|
+
description: Pounds Sterling
|
15
|
+
exchange_rate: 1.5
|
16
|
+
is_designated: false
|
17
|
+
currency_group: Europe
|
18
|
+
---
|
19
|
+
currency_group:
|
20
|
+
code: Europe
|
21
|
+
description: European Countries
|
22
|
+
is_commodity: false
|
23
|
+
version: 1.0.1
|
24
|
+
"""
|
25
|
+
When I run ditto on "simple_entity.rb"
|
26
|
+
Then the exit code should be 0
|
27
|
+
And the stdout should be
|
28
|
+
"""
|
29
|
+
Data Entities:
|
30
|
+
currency {"code"=>"GBP", "description"=>"Pounds Sterling", "exchange_rate"=>1.5, "is_designated"=>false, "currency_group"=>"Europe"}
|
31
|
+
currency_group {"code"=>"Europe", "description"=>"European Countries", "is_commodity"=>false}
|
32
|
+
2 entities, 1 relationships, 0 errors
|
33
|
+
"""
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
Given /^a file named "(.*?)" with:$/ do |arg1, string|
|
4
|
+
filename = "#{Dir.tmpdir}/#{arg1}"
|
5
|
+
File.open(filename,"w") { |f| f.write string }
|
6
|
+
@files[arg1] = filename
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I run "(.*?)"$/ do |arg1|
|
10
|
+
@out = `ruby -I lib #{@files[arg1]}`
|
11
|
+
raise "Exec failed!" if $?.success?.nil?
|
12
|
+
@rc = $?.exitstatus
|
13
|
+
end
|
14
|
+
|
15
|
+
Then /^the exit code should be (\d+)$/ do |arg1|
|
16
|
+
@rc.should == arg1.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /^the stdout should be$/ do |string|
|
20
|
+
@out.should == string
|
21
|
+
end
|
data/lib/ditto.rb
ADDED
data/lib/ditto/dsl.rb
ADDED
data/lib/ditto/entity.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Entity support for Ditto
|
2
|
+
#
|
3
|
+
module Ditto
|
4
|
+
class Entity
|
5
|
+
PROPS = [ :mandatory, :unique, :related ].freeze
|
6
|
+
@entities = {}
|
7
|
+
def self.define_entity name, details
|
8
|
+
raise "Entity details must be a hash!" unless details.kind_of? Hash
|
9
|
+
raise "Entity #{name.to_sym} already exists" if @entities.has_key?(name.to_sym)
|
10
|
+
@entities[name.to_sym] = details
|
11
|
+
end
|
12
|
+
def self.check
|
13
|
+
nrel = 0
|
14
|
+
nerr = 0
|
15
|
+
nkey = 0
|
16
|
+
puts "Entities:"
|
17
|
+
@entities.each do |name,fields|
|
18
|
+
puts name
|
19
|
+
fields.each do |field, props|
|
20
|
+
symprops = Array(props).select{|p| p.is_a? Symbol}
|
21
|
+
duffprops = symprops - PROPS
|
22
|
+
unless duffprops.empty?
|
23
|
+
puts "unknown properties: #{duffprops.join(' ,')}"
|
24
|
+
nerr += 1
|
25
|
+
end
|
26
|
+
nkey += symprops.count(:unique)
|
27
|
+
nrel += symprops.count(:related)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
puts "#{@entities.size} entities, #{nrel} relationships, #{nerr} errors"
|
31
|
+
return nerr
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Ditto
|
4
|
+
class Options
|
5
|
+
DEFAULT_CONNSTRING = "user/password@//localhost:1521/test"
|
6
|
+
attr_reader :connstring, :files_to_load
|
7
|
+
def initialize(argv)
|
8
|
+
@connstring = DEFAULT_CONNSTRING
|
9
|
+
parse(argv)
|
10
|
+
@files_to_load = argv
|
11
|
+
end
|
12
|
+
private
|
13
|
+
def parse(argv)
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.banner = "Usage: ditto [ options ] files..."
|
16
|
+
opts.on("-d", "--database string", String, "DB Connection string") do |s|
|
17
|
+
@connstring = s
|
18
|
+
end
|
19
|
+
opts.on("-h", "--help", "Show this message") do
|
20
|
+
puts opts
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
begin
|
24
|
+
argv = ["-h"] if argv.empty?
|
25
|
+
opts.parse!(argv)
|
26
|
+
rescue OptionParser::ParseError => e
|
27
|
+
STDERR.puts e.message, "\n", opts
|
28
|
+
exit(-1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ditto/runner.rb
ADDED
data/rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
---------------------------------------- DEFINITIONS ----------------------------------------
|
2
|
+
<object_classes>
|
3
|
+
<object name='currency'>
|
4
|
+
<property name='code' mandatory='Y' is_key='Y' />
|
5
|
+
<property name='description'/>
|
6
|
+
<property name='exchange_rate' mandatory='Y' />
|
7
|
+
<property name='is_designated'/>
|
8
|
+
<relation name='currency_group' relation_object='currency_group' relation_type='unique'/>
|
9
|
+
</object>
|
10
|
+
<object name='currency_group'>
|
11
|
+
<property name='code' mandatory='Y' is_key='Y'/>
|
12
|
+
<property name='description'/>
|
13
|
+
<property name='is_commodity'/>
|
14
|
+
</object>
|
15
|
+
</object_classes>
|
16
|
+
|
17
|
+
---------------------------------------- DATA ----------------------------------------
|
18
|
+
<object_instances>
|
19
|
+
<currency code ='GBP' description='Great Britain Pound' exchange_rate='1.5' is_designated='false'>
|
20
|
+
<currency_group code='Europe' />
|
21
|
+
</currency>
|
22
|
+
<currency_group code='Europe' description='European countries' is_commodity='false'/>
|
23
|
+
</object_instances>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# This format has multiple YAML streams:
|
2
|
+
# The first contains version info, date and author etc.
|
3
|
+
# The subsequent are hashes, each being an entity with key the entity name
|
4
|
+
# Note that strings are used as keys and not symbols for user clarity
|
5
|
+
#
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2012-10-13
|
8
|
+
author: Nick Townsend
|
9
|
+
---
|
10
|
+
currency:
|
11
|
+
code: GBP
|
12
|
+
description: Pounds Sterling
|
13
|
+
exchange_rate: 1.5
|
14
|
+
is_designated: false
|
15
|
+
currency_group: Europe
|
16
|
+
---
|
17
|
+
currency_group:
|
18
|
+
code: Europe
|
19
|
+
description: European Countries
|
20
|
+
is_commodity: false
|
21
|
+
version: 1.0.1
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This format has two streams, the first version info etc.
|
2
|
+
# The second is a sequence of hashes, each has being an entity
|
3
|
+
#
|
4
|
+
:version: 1.0.0
|
5
|
+
---
|
6
|
+
-
|
7
|
+
:currency:
|
8
|
+
:code: GBP
|
9
|
+
:description: Pounds Sterling
|
10
|
+
:exchange_rate: 1.5
|
11
|
+
:is_designated: false
|
12
|
+
:currency_group: Europe
|
13
|
+
-
|
14
|
+
:currency_group:
|
15
|
+
:code: Europe
|
16
|
+
:description: European Countries
|
17
|
+
:is_commodity: false
|
18
|
+
:version: 1.0.1
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This format has multiple streams, the first version info etc.
|
2
|
+
# The subsequent are hashes, each has being an entity
|
3
|
+
# Symbols are used throughout
|
4
|
+
#
|
5
|
+
:version: 1.0.0
|
6
|
+
:date: 2012-10-13
|
7
|
+
---
|
8
|
+
:currency:
|
9
|
+
:code: GBP
|
10
|
+
:description: Pounds Sterling
|
11
|
+
:exchange_rate: 1.5
|
12
|
+
:is_designated: false
|
13
|
+
:currency_group: Europe
|
14
|
+
---
|
15
|
+
:currency_group:
|
16
|
+
:code: Europe
|
17
|
+
:description: European Countries
|
18
|
+
:is_commodity: false
|
19
|
+
:version: 1.0.1
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative '../lib/ditto/options'
|
2
|
+
|
3
|
+
module Ditto
|
4
|
+
describe Options do
|
5
|
+
context "specifying no database" do
|
6
|
+
it "should return default" do
|
7
|
+
opts = Ditto::Options.new(["testfile"])
|
8
|
+
Ditto::Options::DEFAULT_CONNSTRING.should == opts.connstring
|
9
|
+
end
|
10
|
+
end
|
11
|
+
context "specifying a database" do
|
12
|
+
it "should return it" do
|
13
|
+
mydb = "username/password@//myserver:1521/my.service.com"
|
14
|
+
opts = Ditto::Options.new(["-d", "#{mydb}", "afile"])
|
15
|
+
opts.connstring.should == mydb
|
16
|
+
end
|
17
|
+
end
|
18
|
+
context "specifying files and no connection string" do
|
19
|
+
it "should return the files" do
|
20
|
+
opts = Ditto::Options.new(["file1", "file2"])
|
21
|
+
opts.files_to_load.should == ["file1", "file2"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
context "specifying files and a dictionary" do
|
25
|
+
it "should return the files" do
|
26
|
+
opts = Ditto::Options.new(["-d", "u/p@//serv:1521/mydb", "file1", "file2"])
|
27
|
+
opts.files_to_load.should == ["file1", "file2"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ditto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nick Townsend
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: ! 'Database Independent Test Objects (Ditto)
|
31
|
+
|
32
|
+
|
33
|
+
Ditto defines a simple DSL that allows test data to be expressed in a database independent
|
34
|
+
format. When the underlying tables are remapped the QA team don''t have to go and
|
35
|
+
change all the historical test cases.
|
36
|
+
|
37
|
+
|
38
|
+
There are two parts, both of them versioned:
|
39
|
+
|
40
|
+
1. The data declarations
|
41
|
+
|
42
|
+
2. The mappings to the underlying database
|
43
|
+
|
44
|
+
|
45
|
+
Idea is to replace an XML dialect with something simpler. See sample at simple_object.xml
|
46
|
+
|
47
|
+
|
48
|
+
Nick Townsend, Oct 2012
|
49
|
+
|
50
|
+
'
|
51
|
+
email: nick.townsend@mac.com
|
52
|
+
executables: []
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- bin/ditto
|
57
|
+
- CHANGELOG
|
58
|
+
- ditto.gemspec
|
59
|
+
- features/create_entities.feature
|
60
|
+
- features/load_entity.feature
|
61
|
+
- features/step_definitions/definition_steps.rb
|
62
|
+
- features/support/hooks.rb
|
63
|
+
- lib/ditto/dsl.rb
|
64
|
+
- lib/ditto/entity.rb
|
65
|
+
- lib/ditto/options.rb
|
66
|
+
- lib/ditto/runner.rb
|
67
|
+
- lib/ditto.rb
|
68
|
+
- rakefile
|
69
|
+
- README
|
70
|
+
- samples/simple_object.xml
|
71
|
+
- samples/simple_object.yaml
|
72
|
+
- samples/simple_object_seq.yaml
|
73
|
+
- samples/simple_object_sym.yaml
|
74
|
+
- spec/options_spec.rb
|
75
|
+
homepage: http://rubygems.org/gems/ditto
|
76
|
+
licenses: []
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '1.9'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.8.24
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Database independent test objects
|
99
|
+
test_files: []
|