ccp 0.2.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -157,23 +157,25 @@ This will create following files.
157
157
  % tree tmp/fixtures
158
158
  tmp/fixtures
159
159
  +- tsfc
160
- +- read.json
161
- +- write.json
160
+ +- stub.json
161
+ +- mock.json
162
162
 
163
163
  1 directory, 2 files
164
- % cat tmp/fixtures/tsfc/read.json
164
+ % cat tmp/fixtures/tsfc/stub.json
165
165
  {"a":1}
166
- % cat tmp/fixtures/tsfc/write.json
166
+ % cat tmp/fixtures/tsfc/mock.json
167
167
  {"x":10}
168
168
 
169
+ Where, reading means stub and writing means mock.
170
+
169
171
  === Writing tests
170
172
 
171
173
  Use them as stubs and expected data as you like.
172
174
 
173
175
  describe TSFC do
174
176
  it "should work" do
175
- data = JSON.load(Pathname("tmp/fixtures/tsfc/read.json").read{})
176
- expected = JSON.load(Pathname("tmp/fixtures/tsfc/write.json").read{})
177
+ data = JSON.load(Pathname("tmp/fixtures/tsfc/stub.json").read{})
178
+ expected = JSON.load(Pathname("tmp/fixtures/tsfc/mock.json").read{})
177
179
 
178
180
  cmd = TSFC.execute(data)
179
181
 
@@ -238,8 +240,28 @@ In this case, we want to filter save data. Try fixtures_keys!
238
240
 
239
241
  Cmd.execute(:fixture_save => true, :fixture_keys => ['x'])
240
242
 
241
- This will generate "read.json" that contains only 'x'.
243
+ This will generate "stub.json" that contains only 'x'.
242
244
  And, "!" can be used for negations as same as "Filter commands".
243
245
 
244
246
  Cmd.execute(:fixture_save => true, :fixture_keys => ['!logger'])
245
247
 
248
+ === Static options
249
+
250
+ Static options(hard code) are also available.
251
+
252
+ class Cmd
253
+ include Ccp::Commands::Core
254
+ stub "tmp/stub.json"
255
+ mock "tmp/mock.json"
256
+ # keys ["x"]
257
+ save true
258
+
259
+ def execute
260
+ data[:a]
261
+ data[:x] = 10
262
+ end
263
+ end
264
+
265
+ Cmd.execute(:a=>1)
266
+
267
+ This generates "tmp/stub.json", "tmp/mock.json".
data/ccp.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_dependency "typed", ">= 0.2.2"
22
22
  s.add_dependency "must", ">= 0.2.7"
23
- s.add_dependency "dsl_accessor", ">= 0.4.0"
23
+ s.add_dependency "dsl_accessor", ">= 0.4.1"
24
24
 
25
25
  s.add_development_dependency "rspec"
26
26
  end
data/lib/ccp/commands.rb CHANGED
@@ -4,6 +4,7 @@ module Ccp
4
4
  autoload :Composite , 'ccp/commands/composite'
5
5
  autoload :Executable , 'ccp/commands/executable'
6
6
  autoload :Receivable , 'ccp/commands/receivable'
7
+ autoload :Fixturable , 'ccp/commands/fixturable'
7
8
  autoload :RuntimeArgs , 'ccp/commands/runtime_args'
8
9
  autoload :Commentable , 'ccp/commands/commentable'
9
10
  autoload :Core , 'ccp/commands/core'
@@ -6,6 +6,7 @@ module Ccp
6
6
  base.class_eval do
7
7
  extend ClassMethods
8
8
  extend Executable::ClassMethods
9
+ include Fixturable
9
10
  end
10
11
  end
11
12
 
@@ -6,8 +6,10 @@ module Ccp
6
6
  include Executable
7
7
 
8
8
  def self.included(base)
9
+ super
9
10
  base.class_eval do
10
11
  extend ClassMethods
12
+ include Fixturable
11
13
  end
12
14
  end
13
15
 
@@ -0,0 +1,12 @@
1
+ module Ccp
2
+ module Commands
3
+ module Fixturable
4
+ def self.included(base)
5
+ base.class_eval do
6
+ include Ccp::Utils::Options
7
+ dsl_accessor :fixture, options(:stub, :mock, :fail, :save, :keys, :dir, :kvs, :ext)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
data/lib/ccp/invokers.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  module Ccp
2
2
  module Invokers
3
3
  autoload :Base , 'ccp/invokers/base'
4
+ autoload :Spec , 'ccp/invokers/spec'
4
5
  end
5
6
  end
@@ -4,15 +4,19 @@ module Ccp
4
4
  module Invokers
5
5
  class Base
6
6
  include Commands::Composite
7
+ include Utils::Options
7
8
 
8
9
  dsl_accessor :receiver, Receivers::Base
9
- dsl_accessor :profile , false
10
- dsl_accessor :comment , true
11
- dsl_accessor :logger , proc{ Logger.new($stderr) }
12
10
 
13
- dsl_accessor :builtin_options, :default => {:profile => profile, :comment => comment, :logger => logger}
14
11
  dsl_accessor :default_options, :default => {}
15
12
 
13
+ dsl_accessor :builtins, options(:profile, :comment, :logger)
14
+ dsl_accessor :fixtures, options(:fixture_save, :fixture_keys, :fixture_dir, :fixture_kvs, :fixture_ext)
15
+
16
+ profile false
17
+ comment true
18
+ logger Logger.new($stderr)
19
+
16
20
  ######################################################################
17
21
  ### Class Methods
18
22
 
@@ -23,14 +27,20 @@ module Ccp
23
27
  return cmd
24
28
  end
25
29
 
30
+ def self.receiver_options
31
+ opts = fixtures.options
32
+ opts[:fixture_keys] ||= builtins.options.keys.map{|i| "!#{i}"}
33
+ return opts
34
+ end
35
+
26
36
  ######################################################################
27
37
  ### Instance Methods
28
38
 
29
39
  def initialize(options = {})
30
40
  self.receiver = options.delete(:receiver) || self.class.receiver.new
31
- receiver.parse!(:fixture_keys => self.class.builtin_options.keys.map{|i| "!#{i}"})
41
+ receiver.parse!(self.class.receiver_options)
32
42
  receiver.parse!(options)
33
- receiver.data.default.merge!(self.class.builtin_options)
43
+ receiver.data.default.merge!(self.class.builtins.options)
34
44
  receiver.data.default.merge!(self.class.default_options)
35
45
  end
36
46
 
@@ -0,0 +1,8 @@
1
+ module Ccp
2
+ module Invokers
3
+ class Spec < Base
4
+ def self.spec
5
+ end
6
+ end
7
+ end
8
+ end
@@ -7,6 +7,9 @@ module Ccp::Persistent
7
7
  autoload :Json , 'ccp/persistent/json'
8
8
  autoload :Tsv , 'ccp/persistent/tsv'
9
9
  autoload :Versioned, 'ccp/persistent/versioned'
10
+ autoload :Loadable , 'ccp/persistent/loadable'
11
+
12
+ extend Ccp::Persistent::Loadable
10
13
 
11
14
  def self.lookup(name)
12
15
  case name.to_s
@@ -41,6 +41,16 @@ class Ccp::Persistent::Base
41
41
  raise NotImplementedError, "subclass resposibility"
42
42
  end
43
43
 
44
+ def read
45
+ read!
46
+ rescue Ccp::Persistent::NotFound
47
+ {}
48
+ end
49
+
50
+ def read!
51
+ keys.inject({}) {|h,k| h[k] = v; h}
52
+ end
53
+
44
54
  def keys
45
55
  raise NotImplementedError, "subclass resposibility"
46
56
  end
@@ -11,13 +11,13 @@ class Ccp::Persistent::File < Ccp::Persistent::Base
11
11
  end
12
12
 
13
13
  def exist?(key)
14
- read_data.has_key?(key.to_s)
14
+ read.has_key?(key.to_s)
15
15
  end
16
16
 
17
17
  def load!(key)
18
- hash = read_data
18
+ hash = read
19
19
  if hash.has_key?(key.to_s)
20
- read_data[key.to_s]
20
+ hash[key.to_s]
21
21
  else
22
22
  raise Ccp::Persistent::NotFound, key.to_s
23
23
  end
@@ -30,13 +30,13 @@ class Ccp::Persistent::File < Ccp::Persistent::Base
30
30
  end
31
31
 
32
32
  def []=(key, val)
33
- hash = read_data
33
+ hash = read
34
34
  hash[key.to_s] = val
35
35
  raw_write(encode(hash))
36
36
  end
37
37
 
38
38
  def keys
39
- read_data.keys.sort
39
+ read.keys.sort
40
40
  end
41
41
 
42
42
  def truncate
@@ -47,11 +47,18 @@ class Ccp::Persistent::File < Ccp::Persistent::Base
47
47
  @path ||= Pathname(@source)
48
48
  end
49
49
 
50
- private
51
- def read_data
52
- path.exist? ? decode(path.read{}).must(Hash) : {}
53
- end
50
+ def read
51
+ read!
52
+ rescue Ccp::Persistent::NotFound
53
+ {}
54
+ end
54
55
 
56
+ def read!
57
+ path.exist? or raise Ccp::Persistent::NotFound, path.to_s
58
+ decode(path.read{}).must(Hash)
59
+ end
60
+
61
+ private
55
62
  def raw_write(buf)
56
63
  path.parent.mkpath
57
64
  path.open("w+"){|f| f.print buf}
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Ccp::Persistent::Loadable
4
+ def load(file)
5
+ ext = Ccp::Serializers.lookup(Pathname(file).extname.to_s.delete("."))
6
+ kvs = load_kvs_lookup_by_filename(file)
7
+ kvs.new(file.sub(%r{/$},''), ext)
8
+ end
9
+
10
+ private
11
+ def load_kvs_lookup_by_filename(file)
12
+ case file.to_s
13
+ when %r{/$} ; Ccp::Persistent::Dir
14
+ when %r{\.tsv$}; Ccp::Persistent::Tsv
15
+ else ; Ccp::Persistent::File
16
+ end
17
+ end
18
+ end
@@ -1,31 +1,18 @@
1
1
  module Ccp
2
2
  module Receivers
3
3
  module Fixtures
4
- class Storage
5
- def initialize(kvs)
6
- @kvs = kvs
7
- end
8
-
9
- def save(data)
10
- data.keys.each do |key|
11
- @kvs[key.to_s] = data[key]
12
- end
13
- end
14
-
15
- def load
16
- raise NotImplementedError
17
- end
18
- end
19
-
20
4
  def execute(cmd)
21
- return super unless fixture_save?(cmd)
22
-
23
- observer = Ccp::Fixtures::Observer.new(data)
24
- observer.start
25
- super
26
- observer.stop
27
-
28
- fixture_save(cmd, observer.read, observer.write)
5
+ if fixture_save?(cmd)
6
+ observer = Ccp::Fixtures::Observer.new(data)
7
+ observer.start
8
+ super
9
+ observer.stop
10
+ fixture_save(cmd, observer.read, observer.write)
11
+ else
12
+ fixture_stub(cmd)
13
+ super
14
+ fixture_mock(cmd)
15
+ end
29
16
  end
30
17
 
31
18
  def setup
@@ -52,7 +39,49 @@ module Ccp
52
39
  super
53
40
  end
54
41
 
42
+ def fixture_stub(cmd)
43
+ path = cmd.class.stub or return
44
+ hash = Ccp::Persistent.load(path).read!
45
+ data.merge!(hash)
46
+ end
47
+
48
+ def fixture_mock(cmd)
49
+ path = cmd.class.mock or return
50
+ hash = Ccp::Persistent.load(path).read!
51
+
52
+ hash.keys.each do |key|
53
+ fixture_validate(cmd, key, data, hash)
54
+ end
55
+ end
56
+
57
+ def fixture_validate(cmd, key, data, hash)
58
+ data.exist?(key) or fixture_fail(cmd, key)
59
+ data[key] == hash[key] or fixture_fail(cmd, key, hash[key], data[key])
60
+ # or, success
61
+ end
62
+
63
+ def fixture_fail(cmd, key, expected = nil, got = nil)
64
+ block = fixture_fail_for(cmd)
65
+ instance_exec(cmd, key, expected, got, &block)
66
+ end
67
+
68
+ def fixture_fail_for(cmd)
69
+ cmd.class.fail || method(:default_fixture_fail)
70
+ end
71
+
72
+ def default_fixture_fail(cmd, key, exp, got)
73
+ if exp == nil and got == nil
74
+ raise "#{cmd.class} should write #{key} but not found"
75
+ end
76
+
77
+ exp_info = "%s(%s)" % [exp.inspect.truncate(200), Must::StructInfo.new(exp).compact.inspect]
78
+ got_info = "%s(%s)" % [got.inspect.truncate(200), Must::StructInfo.new(got).compact.inspect]
79
+ raise "%s should create %s for %s, but got %s" % [cmd.class, exp_info, key, got_info]
80
+ end
81
+
55
82
  def fixture_save?(cmd)
83
+ return true if cmd.class.save # highest priority
84
+
56
85
  case (obj = self[:fixture_save])
57
86
  when true ; true
58
87
  when false ; false
@@ -68,19 +97,31 @@ module Ccp
68
97
  end
69
98
  end
70
99
 
71
- def fixture_save(cmd, read, write)
72
- path = self[:fixture_path_for].call(cmd)
73
- versioned = Ccp::Persistent::Versioned.new(path, :kvs=>self[:fixture_kvs], :ext=>self[:fixture_ext])
74
- versioned["read" ].save(read , fixture_keys_filter(read.keys))
75
- versioned["write"].save(write, fixture_keys_filter(write.keys))
100
+ def fixture_save(cmd, stub, mock)
101
+ path = self[:fixture_path_for].call(cmd)
102
+ path = Pathname(cmd.class.dir) + cmd.class.name.underscore if cmd.class.dir
103
+
104
+ keys = cmd.class.keys || self[:fixture_keys]
105
+ kvs = cmd.class.kvs || self[:fixture_kvs]
106
+ ext = cmd.class.ext || self[:fixture_ext]
107
+
108
+ versioned = Ccp::Persistent::Versioned.new(path, :kvs=>kvs, :ext=>ext)
109
+
110
+ # stub
111
+ storage = cmd.class.stub ? Ccp::Persistent.lookup(kvs).new(cmd.class.stub, ext) : versioned["stub"]
112
+ storage.save(stub, fixture_keys_filter(keys, stub.keys))
113
+
114
+ # mock
115
+ storage = cmd.class.mock ? Ccp::Persistent.lookup(kvs).new(cmd.class.mock, ext) : versioned["mock"]
116
+ storage.save(mock, fixture_keys_filter(keys, mock.keys))
76
117
  end
77
118
 
78
- def fixture_keys_filter(keys)
79
- case (obj = self[:fixture_keys])
119
+ def fixture_keys_filter(acl, keys)
120
+ case acl
80
121
  when true ; keys
81
122
  when false; []
82
123
  when Array
83
- ary = obj.map(&:to_s)
124
+ ary = acl.map(&:to_s)
84
125
  return keys if ary == []
85
126
  if ary.size == ary.grep(/^!/).size
86
127
  return keys.dup.reject{|v| ary.include?("!#{v}")}
@@ -88,17 +129,10 @@ module Ccp
88
129
  ary & keys
89
130
  end
90
131
  else
91
- raise ":fixture_keys is invalid: #{obj.class}"
132
+ raise ":fixture_keys is invalid: #{acl.class}"
92
133
  end
93
134
  end
94
135
 
95
- def fixture_for(cmd, key)
96
- kvs = Ccp::Persistent.lookup(self[:fixture_kvs])
97
- code = Ccp::Serializers.lookup(self[:fixture_ext])
98
- path = instance_exec(cmd, &self[:fixture_path_for]) + "#{key}.#{code.ext}.#{kvs.ext}"
99
- return Storage.new(kvs.new(path, code))
100
- end
101
-
102
136
  def default_fixture_path_for
103
137
  proc{|cmd| settings.path(:fixture_dir) + cmd.class.name.underscore}
104
138
  end
data/lib/ccp/utils.rb CHANGED
@@ -2,5 +2,6 @@ module Ccp
2
2
  module Utils
3
3
  autoload :Data , 'ccp/utils/data'
4
4
  autoload :Colorize , 'ccp/utils/colorize'
5
+ autoload :Options , 'ccp/utils/options'
5
6
  end
6
7
  end
@@ -0,0 +1,6 @@
1
+ module Ccp
2
+ module Utils
3
+ class FixtureOptions < Options::Proxy
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ module Ccp
2
+ module Utils
3
+ module Options
4
+ def self.included(base)
5
+ super
6
+
7
+ class << base
8
+ def options(*keys)
9
+ Proxy.new(self, *keys)
10
+ end
11
+ end
12
+ end
13
+
14
+ class Proxy
15
+ include Enumerable
16
+
17
+ attr_reader :keys
18
+
19
+ def initialize(base, *keys)
20
+ @base = base
21
+ @keys = keys.map(&:to_sym)
22
+
23
+ @keys.each do |key|
24
+ @base.dsl_accessor key
25
+ # instance_eval "def self.#{key}; :#{key}; end"
26
+ end
27
+ end
28
+
29
+ def [](key)
30
+ @base.__send__(key)
31
+ end
32
+
33
+ def each(&block)
34
+ keys.each do |key|
35
+ yield(self[key])
36
+ end
37
+ end
38
+
39
+ def options
40
+ opts = {}
41
+ keys.each do |key|
42
+ val = self[key]
43
+ opts[key] = val unless val.nil?
44
+ end
45
+ return opts
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/ccp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ccp
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -1,5 +1,23 @@
1
1
  require "spec_helper"
2
2
 
3
+ describe Ccp::Commands::Composite do
4
+ describe "(instance)" do
5
+ subject { Object.new.extend Ccp::Commands::Composite }
6
+
7
+ # data container
8
+ it { should respond_to(:data?) }
9
+ it { should respond_to(:data) }
10
+ its(:data) { should be_kind_of(Typed::Hash) }
11
+
12
+ # executable
13
+ it { should respond_to(:execute) }
14
+
15
+ # receivable
16
+ it { should respond_to(:receiver) }
17
+ its(:receiver) { should be_kind_of(Ccp::Receivers::Base) }
18
+ end
19
+ end
20
+
3
21
  describe Ccp::Commands::Composite do
4
22
  describe "#execute" do
5
23
  it "should call its execute and sub commands's {before,execute,after} in declared order" do
@@ -0,0 +1,66 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Commands::Core do
4
+ subject { Class.new{include Ccp::Commands::Core} }
5
+
6
+ it { should include(Ccp::Commands::Fixturable) }
7
+ end
8
+
9
+ describe Ccp::Commands::Fixturable do
10
+ context "Ccp::Commands::Core" do
11
+ subject { Cmd1 }
12
+ it { should respond_to("stub") }
13
+ it { should respond_to("mock") }
14
+ it { should respond_to("fail") }
15
+ it { should respond_to("save") }
16
+ it { should respond_to("keys") }
17
+ it { should respond_to("dir") }
18
+ it { should respond_to("kvs") }
19
+ it { should respond_to("ext") }
20
+ it { should respond_to("fixture") }
21
+ its(:fixture) { should respond_to("options") }
22
+ end
23
+
24
+ context "Ccp::Commands::Composite" do
25
+ subject { Program }
26
+ it { should respond_to("stub") }
27
+ it { should respond_to("mock") }
28
+ it { should respond_to("fail") }
29
+ it { should respond_to("save") }
30
+ it { should respond_to("keys") }
31
+ it { should respond_to("dir") }
32
+ it { should respond_to("kvs") }
33
+ it { should respond_to("ext") }
34
+ it { should respond_to("fixture") }
35
+ its(:fixture) { should respond_to("options") }
36
+ end
37
+
38
+ context "Ccp::Invokers::Base" do
39
+ subject { CompositeInvoker }
40
+ it { should respond_to("stub") }
41
+ it { should respond_to("mock") }
42
+ it { should respond_to("fail") }
43
+ it { should respond_to("save") }
44
+ it { should respond_to("keys") }
45
+ it { should respond_to("dir") }
46
+ it { should respond_to("kvs") }
47
+ it { should respond_to("ext") }
48
+ it { should respond_to("fixture") }
49
+ its(:fixture) { should respond_to("options") }
50
+ end
51
+
52
+ context "included class" do
53
+ subject { Class.new{include Ccp::Commands::Fixturable} }
54
+ it { should respond_to("stub") }
55
+ it { should respond_to("mock") }
56
+ it { should respond_to("fail") }
57
+ it { should respond_to("save") }
58
+ it { should respond_to("keys") }
59
+ it { should respond_to("dir") }
60
+ it { should respond_to("kvs") }
61
+ it { should respond_to("ext") }
62
+ it { should respond_to("fixture") }
63
+ its(:fixture) { should respond_to("options") }
64
+ end
65
+ end
66
+
@@ -0,0 +1 @@
1
+ {"breadcrumbs":["Cmd1StubMock#before", "Cmd1StubMock#execute", "Cmd1StubMock#after"]}
@@ -0,0 +1 @@
1
+ {"breadcrumbs":[]}
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+ require 'fileutils'
3
+
4
+ describe Ccp::Invokers::Base do
5
+ describe "(class)" do
6
+ subject {Class.new(Ccp::Invokers::Base)}
7
+ it { should respond_to(:fixture_save) }
8
+ it { should respond_to(:fixture_keys) }
9
+ it { should respond_to(:fixture_dir) }
10
+ it { should respond_to(:fixture_kvs) }
11
+ it { should respond_to(:fixture_ext) }
12
+ end
13
+ end
@@ -2,29 +2,21 @@ require "spec_helper"
2
2
  require 'fileutils'
3
3
 
4
4
  describe Ccp::Invokers::Base do
5
- def load(path)
6
- case path.extname
7
- when ".json"; JSON.load(Pathname(path).read{})
8
- when ".yaml"; YAML.load(Pathname(path).read{})
9
- else; raise "load doesn't support #{path.extname}"
10
- end
11
- end
12
-
13
5
  describe ".execute" do
14
6
  before do
15
7
  FileUtils.rm_rf("tmp")
16
8
  end
17
9
 
18
10
  context "(:fixture_save=>true)" do
19
- it "should generate read/write fixtures in tmp/fixtures as json files" do
11
+ it "should generate stub/mock fixtures in tmp/fixtures as json files" do
20
12
  path = Pathname("tmp/fixtures")
21
13
  data = {:breadcrumbs => []}
22
14
  opts = {:fixture_save=>true}
23
15
 
24
16
  CompositeInvoker.execute(data.merge(opts))
25
17
 
26
- (read = path + "composite_invoker/read.json" ).should exist
27
- load(read)["breadcrumbs"].should ==
18
+ (stub = path + "composite_invoker/stub.json" ).should exist
19
+ load_fixture(stub)["breadcrumbs"].should ==
28
20
  ["CompositeInvoker#before",
29
21
  "Cmd1#before", "Cmd1#execute", "Cmd1#after",
30
22
  "Cmd23#before",
@@ -0,0 +1,36 @@
1
+ require "spec_helper"
2
+ require 'fileutils'
3
+
4
+ describe Ccp::Invokers::Spec do
5
+ it "should inherit Ccp::Invokers::Base" do
6
+ subject.should be_kind_of(Ccp::Invokers::Base)
7
+ end
8
+
9
+ describe "(class)" do
10
+ subject { Ccp::Invokers::Spec }
11
+ it { should respond_to("spec") }
12
+ end
13
+ end
14
+
15
+
16
+ __END__
17
+
18
+ class Cmd1Spec < Ccp::Invokers::Spec
19
+ fixture_dir "spec/fixtures/invokers/spec/stub"
20
+ command Cmd1
21
+ end
22
+
23
+ it "should stub data" do
24
+ path = truncate_pathname("tmp/fixtures/spec/invokers/spec/stub")
25
+ save_fixture(path + "stub.json", "breadcrumbs"=>[])
26
+
27
+ lambda {
28
+ Cmd1Spec.execute
29
+ }.should raise_error(Typed::NotDefined)
30
+
31
+ lambda {
32
+ Cmd1Spec.spec
33
+ }.should_not raise_error
34
+ end
35
+ end
36
+
@@ -11,39 +11,15 @@ describe Ccp::Persistent::Base do
11
11
  end
12
12
  end
13
13
 
14
- it "should provide ext" do
15
- subject.methods.include?("ext").should == true
16
- end
17
-
18
- it "should provide exist?" do
19
- subject.methods.include?("exist?").should == true
20
- end
21
-
22
- it "should provide #save" do
23
- subject.methods.include?("save").should == true
24
- end
25
-
26
- it "should provide #load!" do
27
- subject.methods.include?("load!").should == true
28
- end
29
-
30
- it "should provide #load" do
31
- subject.methods.include?("load").should == true
32
- end
33
-
34
- it "should provide #[]" do
35
- subject.methods.include?("[]").should == true
36
- end
37
-
38
- it "should provide #[]=" do
39
- subject.methods.include?("[]=").should == true
40
- end
41
-
42
- it "should provide #keys" do
43
- subject.methods.include?("keys").should == true
44
- end
45
-
46
- it "should provide #truncate" do
47
- subject.methods.include?("truncate").should == true
48
- end
14
+ it { should respond_to("ext") }
15
+ it { should respond_to("exist?") }
16
+ it { should respond_to("save") }
17
+ it { should respond_to("load!") }
18
+ it { should respond_to("load") }
19
+ it { should respond_to("[]") }
20
+ it { should respond_to("[]=") }
21
+ it { should respond_to("read") }
22
+ it { should respond_to("read!") }
23
+ it { should respond_to("keys") }
24
+ it { should respond_to("truncate") }
49
25
  end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'fileutils'
4
+
5
+ describe Ccp::Persistent do
6
+ it { should respond_to("load") }
7
+
8
+ describe ".load" do
9
+ context "('tmp/foo.json')" do
10
+ subject { Ccp::Persistent.load('tmp/foo.json') }
11
+ its(:class) { should == Ccp::Persistent::File }
12
+ its(:ext) { should == "json" }
13
+ its(:source) { should == 'tmp/foo.json' }
14
+ end
15
+
16
+ context "('tmp/foo.yaml')" do
17
+ subject { Ccp::Persistent.load('tmp/foo.yaml') }
18
+ its(:class) { should == Ccp::Persistent::File }
19
+ its(:ext) { should == "yaml" }
20
+ its(:source) { should == 'tmp/foo.yaml' }
21
+ end
22
+
23
+ context "('tmp/foo.json/')" do
24
+ subject { Ccp::Persistent.load('tmp/foo.json/') }
25
+ its(:class) { should == Ccp::Persistent::Dir }
26
+ its(:ext) { should == "json" }
27
+ its(:source) { should == 'tmp/foo.json' }
28
+ end
29
+
30
+ context "('tmp/foo')" do
31
+ it "should raise Ccp::Serializers::NotFound" do
32
+ lambda {
33
+ Ccp::Persistent.load('tmp/foo')
34
+ }.should raise_error(Ccp::Serializers::NotFound)
35
+ end
36
+ end
37
+
38
+ context "('tmp/foo/')" do
39
+ it "should raise Ccp::Serializers::NotFound" do
40
+ lambda {
41
+ Ccp::Persistent.load('tmp/foo/')
42
+ }.should raise_error(Ccp::Serializers::NotFound)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -8,41 +8,41 @@ describe "Ccp::Commands::Core" do
8
8
  end
9
9
 
10
10
  context "(:fixture_save=>true)" do
11
- it "should generate read/write fixtures in tmp/fixtures as json files" do
11
+ it "should generate stub/mock fixtures in tmp/fixtures as json files" do
12
12
  path = Pathname("tmp/fixtures")
13
13
  data = {:a=>"a", :b=>"b", :x=>1, :y=>2}
14
14
  opts = {:fixture_save=>true}
15
15
 
16
16
  TSFC.execute(data.merge(opts))
17
17
 
18
- load_fixture(path + "tsfc/read.json" ).should == {"a" => "a"}
19
- load_fixture(path + "tsfc/write.json").should == {"x" => 10}
18
+ load_fixture(path + "tsfc/stub.json").should == {"a" => "a"}
19
+ load_fixture(path + "tsfc/mock.json").should == {"x" => 10}
20
20
  end
21
21
  end
22
22
 
23
23
  context "(:fixture_save=>true, :fixture_ext=>:yaml)" do
24
- it "should generate read/write fixtures in tmp/fixtures as yaml files" do
24
+ it "should generate stub/mock fixtures in tmp/fixtures as yaml files" do
25
25
  path = Pathname("tmp/fixtures")
26
26
  data = {:a=>"a", :b=>"b", :x=>1, :y=>2}
27
27
  opts = {:fixture_save=>true, :fixture_ext=>:yaml}
28
28
 
29
29
  TSFC.execute(data.merge(opts))
30
30
 
31
- load_fixture(path + "tsfc/read.yaml" ).should == {"a" => "a"}
32
- load_fixture(path + "tsfc/write.yaml").should == {"x" => 10}
31
+ load_fixture(path + "tsfc/stub.yaml" ).should == {"a" => "a"}
32
+ load_fixture(path + "tsfc/mock.yaml").should == {"x" => 10}
33
33
  end
34
34
  end
35
35
 
36
36
  context "(:fixture_save=>true, :fixture_kvs=>:dir)" do
37
- it "should generate json files in read/write dir" do
37
+ it "should generate json files in stub/mock dir" do
38
38
  path = Pathname("tmp/fixtures")
39
39
  data = {:a=>"a", :b=>"b", :x=>1, :y=>2}
40
40
  opts = {:fixture_save=>true, :fixture_kvs=>:dir}
41
41
 
42
42
  TSFC.execute(data.merge(opts))
43
43
 
44
- load_fixture(path + "tsfc/read.json/a.json" ).should == "a"
45
- load_fixture(path + "tsfc/write.json/x.json").should == 10
44
+ load_fixture(path + "tsfc/stub.json/a.json" ).should == "a"
45
+ load_fixture(path + "tsfc/mock.json/x.json").should == 10
46
46
  end
47
47
  end
48
48
  end
@@ -21,8 +21,8 @@ describe Ccp::Invokers::Base do
21
21
  it "should ignore :logger in default" do
22
22
  ULI.execute(:a=>"a", :fixture_save=>true)
23
23
 
24
- load_fixture("tmp/fixtures/uli/read.json" ).should == {"a" => "a"}
25
- load_fixture("tmp/fixtures/uli/write.json" ).should == {"x" => 10}
24
+ load_fixture("tmp/fixtures/uli/stub.json").should == {"a" => "a"}
25
+ load_fixture("tmp/fixtures/uli/mock.json").should == {"x" => 10}
26
26
  end
27
27
  end
28
28
  end
@@ -13,7 +13,7 @@ describe Cmd1 do
13
13
  end
14
14
 
15
15
  def created_keys
16
- load_fixture(FIXTURE_PATH + "read.json").keys.sort
16
+ load_fixture(FIXTURE_PATH + "stub.json").keys.sort
17
17
  rescue Errno::ENOENT
18
18
  []
19
19
  end
@@ -8,15 +8,51 @@ describe "Ccp::Commands::Core" do
8
8
  end
9
9
 
10
10
  context "(:fixture_save=>true, :fixture_dir=>...)" do
11
- it "should generate read/write fixtures in <save_fixture_dir> as json files" do
11
+ it "should generate stub/mock fixtures in <save_fixture_dir> as json files" do
12
12
  path = Pathname("tmp/test/fixtures")
13
13
  data = {:a=>"a", :b=>"b", :x=>1, :y=>2}
14
14
  opts = {:fixture_save=>true, :fixture_dir=>path.to_s}
15
15
 
16
16
  TSFC.execute(data.merge(opts))
17
17
 
18
- load_fixture(path + "tsfc/read.json" ).should == {"a" => "a"}
19
- load_fixture(path + "tsfc/write.json").should == {"x" => 10}
18
+ load_fixture(path + "tsfc/stub.json").should == {"a" => "a"}
19
+ load_fixture(path + "tsfc/mock.json").should == {"x" => 10}
20
+ end
21
+ end
22
+
23
+ context "(:fixture_save=>true) with hard coded" do
24
+ it "should generate fixtures in given path" do
25
+ data = {:a=>"a", :b=>"b", :x=>1, :y=>2}
26
+ opts = {:fixture_save=>true}
27
+
28
+ begin
29
+ TSFC.stub "tmp/tsfc/in.json"
30
+ TSFC.mock "tmp/tsfc/out.json"
31
+
32
+ TSFC.execute(data.merge(opts))
33
+ ensure
34
+ TSFC.stub nil
35
+ TSFC.mock nil
36
+ end
37
+
38
+ load_fixture("tmp/tsfc/in.json").should == {"a" => "a"}
39
+ load_fixture("tmp/tsfc/out.json").should == {"x" => 10}
40
+ end
41
+
42
+ it "should generate stub/mock fixtures in <dir> as json files" do
43
+ data = {:a=>"a", :b=>"b", :x=>1, :y=>2}
44
+ opts = {:fixture_save=>true}
45
+
46
+ begin
47
+ TSFC.dir "tmp/foo"
48
+
49
+ TSFC.execute(data.merge(opts))
50
+ ensure
51
+ TSFC.dir nil
52
+ end
53
+
54
+ load_fixture("tmp/foo/tsfc/stub.json").should == {"a" => "a"}
55
+ load_fixture("tmp/foo/tsfc/mock.json").should == {"x" => 10}
20
56
  end
21
57
  end
22
58
  end
@@ -13,7 +13,7 @@ describe Ccp::Commands::Composite do
13
13
  end
14
14
 
15
15
  def created_fixtures
16
- Dir.chdir(FIXTURE_ROOT){Dir["*/read.json"].map{|i| File.dirname(i)}.sort}
16
+ Dir.chdir(FIXTURE_ROOT){Dir["*/stub.json"].map{|i| File.dirname(i)}.sort}
17
17
  rescue Errno::ENOENT
18
18
  []
19
19
  end
@@ -88,5 +88,27 @@ describe Ccp::Commands::Composite do
88
88
  execute(:fixture_save => ['Cmd1','!Cmd1']) do
89
89
  ['cmd1']
90
90
  end
91
+
92
+ ######################################################################
93
+ ### hard coded
94
+ context "(hard coded)" do
95
+ before { Cmd2.save true }
96
+ after { Cmd2.save false }
97
+
98
+ # will save if hard coded is enabled
99
+ execute do
100
+ ['cmd2']
101
+ end
102
+
103
+ # respect hard coded even if runtime args are given
104
+ execute(:fixture_save => ['Cmd1']) do
105
+ ['cmd1', 'cmd2']
106
+ end
107
+
108
+ # respect it even if it is rejected by runtime args
109
+ execute(:fixture_save => ['!Cmd1', '!Cmd2']) do
110
+ ["cmd2", "cmd3", "program"]
111
+ end
112
+ end
91
113
  end
92
114
  end
@@ -0,0 +1,64 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Receivers::Fixtures do
4
+ context "(stub)" do
5
+ class Cmd1Stub < Cmd1
6
+ stub "spec/fixtures/stub/breadcrumbs.json"
7
+ end
8
+
9
+ it "should merge given data file into data variable" do
10
+ lambda {
11
+ Cmd1.execute
12
+ }.should raise_error(Typed::NotDefined)
13
+
14
+ lambda {
15
+ Cmd1Stub.execute
16
+ }.should_not raise_error
17
+ end
18
+ end
19
+
20
+ context "(stub and mock)" do
21
+ class Cmd1StubMock < Cmd1
22
+ stub "spec/fixtures/stub/breadcrumbs.json"
23
+ mock "spec/fixtures/cmd1stub_mock/mock.json"
24
+ end
25
+
26
+ it "should raise when current data doesn't match the given data" do
27
+ lambda {
28
+ Cmd1StubMock.execute
29
+ }.should_not raise_error
30
+ end
31
+ end
32
+
33
+ context "(stub and invalid mock)" do
34
+ class Cmd1StubInvalidMock < Cmd1
35
+ stub "spec/fixtures/stub/breadcrumbs.json"
36
+ mock "spec/fixtures/stub/breadcrumbs.json"
37
+ end
38
+
39
+ it "should raise when current data doesn't match the given data" do
40
+ lambda {
41
+ Cmd1StubInvalidMock.execute
42
+ }.should raise_error(/should create/)
43
+ end
44
+ end
45
+
46
+ context "(stub and mock and fail)" do
47
+ class Cmd1StubInvalidMockWithFail < Cmd1
48
+ dsl_accessor :failed, false
49
+
50
+ stub "spec/fixtures/stub/breadcrumbs.json"
51
+ mock "spec/fixtures/stub/breadcrumbs.json"
52
+
53
+ fail do |cmd, key, expected, got|
54
+ Cmd1StubInvalidMockWithFail.failed true
55
+ end
56
+ end
57
+
58
+ it "should raise when current data doesn't match the given data" do
59
+ Cmd1StubInvalidMockWithFail.failed.should == false
60
+ Cmd1StubInvalidMockWithFail.execute
61
+ Cmd1StubInvalidMockWithFail.failed.should == true
62
+ end
63
+ end
64
+ end
@@ -5,15 +5,7 @@ require 'fileutils'
5
5
  describe Ccp::Serializers::Core do
6
6
  subject { Object.new.extend Ccp::Serializers::Core }
7
7
 
8
- it "should provide ext" do
9
- subject.methods.include?("ext").should == true
10
- end
11
-
12
- it "should provide encode" do
13
- subject.methods.include?("encode").should == true
14
- end
15
-
16
- it "should provide decode" do
17
- subject.methods.include?("decode").should == true
18
- end
8
+ it { should respond_to("ext") }
9
+ it { should respond_to("encode") }
10
+ it { should respond_to("decode") }
19
11
  end
data/spec/spec_helper.rb CHANGED
@@ -12,11 +12,24 @@ def breadcrumbs_receiver
12
12
  return r
13
13
  end
14
14
 
15
+ def lookup_serializer(extname)
16
+ {".json"=>JSON, ".yaml"=>YAML}[extname] or raise "no serializers for #{extname}"
17
+ end
18
+
15
19
  def load_fixture(path)
16
20
  path = Pathname(path)
17
- case path.extname
18
- when ".json"; JSON.load(Pathname(path).read{})
19
- when ".yaml"; YAML.load(Pathname(path).read{})
20
- else; raise "load doesn't support #{path.extname}"
21
- end
21
+ lookup_serializer(path.extname).load(path.read{})
22
+ end
23
+
24
+ def save_fixture(path, obj)
25
+ path = Pathname(path)
26
+ buf = lookup_serializer(path.extname).dump(obj)
27
+ path.open("w+"){|f| f.print buf}
28
+ end
29
+
30
+ def truncate_pathname(dir)
31
+ path = Pathname(dir)
32
+ FileUtils.rm_rf(path.to_s)
33
+ path.mkpath
34
+ return path
22
35
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 1
10
- version: 0.2.1
9
+ - 3
10
+ version: 0.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - maiha
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-07 00:00:00 +09:00
18
+ date: 2012-05-10 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -58,12 +58,12 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- hash: 15
61
+ hash: 13
62
62
  segments:
63
63
  - 0
64
64
  - 4
65
- - 0
66
- version: 0.4.0
65
+ - 1
66
+ version: 0.4.1
67
67
  type: :runtime
68
68
  version_requirements: *id003
69
69
  - !ruby/object:Gem::Dependency
@@ -103,6 +103,7 @@ files:
103
103
  - lib/ccp/commands/composite.rb
104
104
  - lib/ccp/commands/core.rb
105
105
  - lib/ccp/commands/executable.rb
106
+ - lib/ccp/commands/fixturable.rb
106
107
  - lib/ccp/commands/receivable.rb
107
108
  - lib/ccp/commands/resolvable.rb
108
109
  - lib/ccp/fixtures.rb
@@ -110,10 +111,12 @@ files:
110
111
  - lib/ccp/fixtures/writers.rb
111
112
  - lib/ccp/invokers.rb
112
113
  - lib/ccp/invokers/base.rb
114
+ - lib/ccp/invokers/spec.rb
113
115
  - lib/ccp/persistent.rb
114
116
  - lib/ccp/persistent/base.rb
115
117
  - lib/ccp/persistent/dir.rb
116
118
  - lib/ccp/persistent/file.rb
119
+ - lib/ccp/persistent/loadable.rb
117
120
  - lib/ccp/persistent/tsv.rb
118
121
  - lib/ccp/persistent/versioned.rb
119
122
  - lib/ccp/receivers.rb
@@ -134,17 +137,25 @@ files:
134
137
  - lib/ccp/serializers/yaml.rb
135
138
  - lib/ccp/utils.rb
136
139
  - lib/ccp/utils/colorize.rb
140
+ - lib/ccp/utils/fixture_options.rb
141
+ - lib/ccp/utils/options.rb
137
142
  - lib/ccp/version.rb
138
143
  - spec/commands/base_spec.rb
139
144
  - spec/commands/composite_spec.rb
140
145
  - spec/commands/core_spec.rb
141
146
  - spec/commands/executable_spec.rb
147
+ - spec/commands/fixturable_spec.rb
148
+ - spec/fixtures/cmd1stub_mock/mock.json
149
+ - spec/fixtures/stub/breadcrumbs.json
142
150
  - spec/invokers/base_spec.rb
151
+ - spec/invokers/fixture_spec.rb
143
152
  - spec/invokers/save_fixture_spec.rb
153
+ - spec/invokers/spec_spec.rb
144
154
  - spec/models.rb
145
155
  - spec/persistent/base_spec.rb
146
156
  - spec/persistent/dir_spec.rb
147
157
  - spec/persistent/file_spec.rb
158
+ - spec/persistent/loadable_spec.rb
148
159
  - spec/persistent/tsv_spec.rb
149
160
  - spec/persistent/versioned_spec.rb
150
161
  - spec/receivers/fixture_save_how_spec.rb
@@ -152,6 +163,7 @@ files:
152
163
  - spec/receivers/fixture_save_what_spec.rb
153
164
  - spec/receivers/fixture_save_where_spec.rb
154
165
  - spec/receivers/fixture_save_why_spec.rb
166
+ - spec/receivers/fixture_stub_spec.rb
155
167
  - spec/serializers/core_spec.rb
156
168
  - spec/serializers/json_spec.rb
157
169
  - spec/serializers/spec.rb