ditto 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []