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 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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/ruby
2
+ require 'ditto/runner'
3
+ runner = Ditto::Runner.new(ARGV)
4
+ runner.run
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
@@ -0,0 +1,3 @@
1
+ Before do
2
+ @files = {}
3
+ end
data/lib/ditto.rb ADDED
@@ -0,0 +1,3 @@
1
+ require_relative 'ditto/entity'
2
+ require_relative 'ditto/dsl'
3
+ include Ditto::DSL
data/lib/ditto/dsl.rb ADDED
@@ -0,0 +1,13 @@
1
+ # Define the DSL for Ditto
2
+ #
3
+ module Ditto
4
+ module DSL
5
+ def entity (*args, &block)
6
+ Ditto::Entity.define_entity(*args, &block)
7
+ end
8
+ def check! (*args, &block)
9
+ nerr = Ditto::Entity.check(*args, &block)
10
+ exit(nerr)
11
+ end
12
+ end
13
+ end
@@ -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
@@ -0,0 +1,13 @@
1
+ require_relative 'dsl'
2
+ require_relative 'options'
3
+
4
+ module Ditto
5
+ class Runner
6
+ def initialize(argv)
7
+ @options = Options.new(argv)
8
+ end
9
+ def run
10
+ puts "Ditto has run with options #{@options}"
11
+ end
12
+ end
13
+ end
data/rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # Rakefile for Ditto
2
+ #
3
+ task :default => :test
4
+
5
+ task :test do
6
+ sh "rspec -c"
7
+ sh "cucumber -f progress features"
8
+ end
@@ -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: []