storexplore 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ffcb1b7ac49f590bdeafde98b7c6e3f6a4aecb8
4
- data.tar.gz: fbb03b9a51c7eab05ffea0d1498cf5b8f15413ec
3
+ metadata.gz: f9aad6223151eb82e5a00d692857bae568271a7f
4
+ data.tar.gz: 02565e1894429c9afbafe786817a7991c41248f4
5
5
  SHA512:
6
- metadata.gz: 94933a0836b830b49ac03fe4f604bf9f8be35cf6e1518a1ceb92b42ae03f76deb7d10e7e9a38cbff4753ea1a8eb3c4607d82445e28397ff3e45f1053bb2306ce
7
- data.tar.gz: 94c3a3291e638198fba5b19071449eeaa40cfbaac57db6cb28cb4f7294c515d4a895524448e618aad404dd412bff240eb386e99a329046dda79ba2a0e2e2766e
6
+ metadata.gz: 232031993870546c1bd5abcf442f5710eac133dd75bcd3342aacd41e7d87ec7c68bff2b7b8c911ecb8b3fadc20f3c6a1763b2474a2b9c065204ac756aacddbb1
7
+ data.tar.gz: 52d3a90be6cc7bc8c4805752c7fab05083efc6d8f9f0c5d3e255d19abaecd470538850edc8c2b234b6ae01d329e33eef37688eff384640474d16acca1dae9e28
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -20,6 +20,7 @@
20
20
  # MA 02110-1301 USA
21
21
 
22
22
  require 'storexplore'
23
+ require 'storexplore/testing/api_shared_context'
23
24
  require 'storexplore/testing/api_shared_examples'
24
25
  require 'storexplore/testing/configuration'
25
26
  require 'storexplore/testing/dummy_data'
@@ -0,0 +1,83 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # api_shared_context.rb
4
+ #
5
+ # Copyright (c) 2010-2014 by Philippe Bourgau. All rights reserved.
6
+ #
7
+ # This library is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation; either
10
+ # version 3.0 of the License, or (at your option) any later version.
11
+ #
12
+ # This library is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public
18
+ # License along with this library; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301 USA
21
+
22
+ module Storexplore
23
+ module Testing
24
+
25
+ shared_context "a scrapped store" do
26
+
27
+ before :all do
28
+ @range = 0..1
29
+
30
+ expect(self).to(respond_to(:generate_store), "You should implement generate_store to include the scrapped store shared context")
31
+
32
+ self.store = generate_store
33
+ explore_store
34
+ end
35
+
36
+ def explore_store
37
+ @sample_categories = dig([store], :categories)
38
+ @all_sample_categories, @sample_items = dig_deep(@sample_categories)
39
+ @valid_sample_items = valid_items(@sample_items)
40
+ @sample_items_attributes = (valid_sample_items.map &:attributes).uniq
41
+ @parseable_categories_attributes = all_sample_categories.map do |category|
42
+ category.attributes rescue {}
43
+ end
44
+ end
45
+
46
+ attr_accessor :store, :sample_categories, :all_sample_categories, :sample_items, :valid_sample_items, :sample_items_attributes, :parseable_categories_attributes
47
+
48
+ def dig(categories, message)
49
+ categories.map { |cat| cat.send(message).to_a[@range] }.flatten
50
+ end
51
+
52
+ def dig_deep(categories)
53
+ all_categories = [categories]
54
+
55
+ while (items = dig(categories, :items)).empty?
56
+ categories = dig(categories, :categories)
57
+ all_categories << categories
58
+ end
59
+
60
+ [all_categories.flatten, items]
61
+ end
62
+
63
+ def valid_items(items)
64
+ result = []
65
+ sample_items.each do |item|
66
+ begin
67
+ item.attributes
68
+ result.push(item)
69
+ rescue BrowsingError => e
70
+ Testing.logger.debug e.message
71
+ end
72
+ end
73
+ result
74
+ end
75
+
76
+ def logger
77
+ Testing.config.logger
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+ end
@@ -22,119 +22,54 @@
22
22
  module Storexplore
23
23
  module Testing
24
24
 
25
- module ApiSpecMacros
25
+ shared_examples "an API" do
26
26
 
27
- def self.included(base)
28
- base.send :extend, ClassMethods
27
+ it "should have many item categories" do
28
+ # TODO remove .first(3) once rspec handles lazy enums
29
+ expect(store.categories.first(3)).to have_at_least(3).items
29
30
  end
30
31
 
31
- module ClassMethods
32
-
33
- def it_should_behave_like_any_store_items_api
34
-
35
- before :all do
36
- @range = 0..1
37
-
38
- generate_store
39
- explore_store
40
- end
41
-
42
- it "should have many item categories" do
43
- # TODO remove .first(3) once rspec handles lazy enums
44
- expect(@store.categories.first(3)).to have_at_least(3).items
45
- end
46
-
47
- it "should have many items" do
48
- expect(sample_items).to have_at_least(3).items
49
- end
50
-
51
- it "should have item categories with different names" do
52
- categories_attributes = sample_categories.map { |cat| cat.attributes }
53
- expect(categories_attributes).to mostly have_unique(:name).in(categories_attributes)
54
- end
55
-
56
- it "should have items with different names" do
57
- expect(sample_items_attributes).to mostly have_unique(:name).in(sample_items_attributes)
58
- end
59
-
60
- it "should have parseable item category attributes" do
61
- expect(parseable_categories_attributes).to mostly have_key(:name)
62
- end
63
-
64
- it "should have some valid item attributes" do
65
- expect(sample_items_attributes).not_to be_empty
66
- end
67
-
68
- it "should have items with a price" do
69
- expect(sample_items_attributes).to all_ { have_key(:price) }
70
- end
71
-
72
- it "should mostly have items with an image" do
73
- expect(sample_items_attributes).to mostly have_key(:image)
74
- end
75
-
76
- it "should mostly have items with a brand" do
77
- expect(sample_items_attributes).to mostly have_key(:brand)
78
- end
79
-
80
- it "should have items with unique remote id" do
81
- expect(sample_items_attributes).to all_ { have_unique(:remote_id).in(sample_items_attributes) }
82
- end
83
-
84
- it "should have items with unique uris" do
85
- expect(valid_sample_items).to mostly have_unique(:uri).in(valid_sample_items)
86
- end
87
- end
32
+ it "should have many items" do
33
+ expect(sample_items).to have_at_least(3).items
88
34
  end
89
35
 
90
- def generate_store
91
- # by default, the store already exists
36
+ it "should have item categories with different names" do
37
+ categories_attributes = sample_categories.map { |cat| cat.attributes }
38
+ expect(categories_attributes).to mostly have_unique(:name).in(categories_attributes)
92
39
  end
93
40
 
94
- def explore_store
95
- @sample_categories = dig([@store], :categories)
96
- @all_sample_categories, @sample_items = dig_deep(@sample_categories)
97
- @valid_sample_items = valid_items(@sample_items)
98
- @sample_items_attributes = (valid_sample_items.map &:attributes).uniq
99
- @parseable_categories_attributes = all_sample_categories.map do |category|
100
- category.attributes rescue {}
101
- end
41
+ it "should have items with different names" do
42
+ expect(sample_items_attributes).to mostly have_unique(:name).in(sample_items_attributes)
102
43
  end
103
44
 
104
- attr_accessor :sample_categories, :all_sample_categories, :sample_items, :valid_sample_items, :sample_items_attributes, :parseable_categories_attributes
105
-
106
- def dig(categories, message)
107
- categories.map { |cat| cat.send(message).to_a[@range] }.flatten
45
+ it "should have parseable item category attributes" do
46
+ expect(parseable_categories_attributes).to mostly have_key(:name)
108
47
  end
109
48
 
110
- def dig_deep(categories)
111
- all_categories = [categories]
49
+ it "should have some valid item attributes" do
50
+ expect(sample_items_attributes).not_to be_empty
51
+ end
112
52
 
113
- while (items = dig(categories, :items)).empty?
114
- categories = dig(categories, :categories)
115
- all_categories << categories
116
- end
53
+ it "should have items with a price" do
54
+ expect(sample_items_attributes).to all_ { have_key(:price) }
55
+ end
117
56
 
118
- [all_categories.flatten, items]
57
+ it "should mostly have items with an image" do
58
+ expect(sample_items_attributes).to mostly have_key(:image)
119
59
  end
120
60
 
121
- def valid_items(items)
122
- result = []
123
- sample_items.each do |item|
124
- begin
125
- item.attributes
126
- result.push(item)
127
- rescue BrowsingError => e
128
- Testing.logger.debug e.message
129
- end
130
- end
131
- result
61
+ it "should mostly have items with a brand" do
62
+ expect(sample_items_attributes).to mostly have_key(:brand)
132
63
  end
133
64
 
134
- def logger
135
- Testing.config.logger
65
+ it "should have items with unique remote id" do
66
+ expect(sample_items_attributes).to all_ { have_unique(:remote_id).in(sample_items_attributes) }
136
67
  end
137
68
 
69
+ it "should have items with unique uris" do
70
+ expect(valid_sample_items).to mostly have_unique(:uri).in(valid_sample_items)
71
+ end
138
72
  end
73
+
139
74
  end
140
75
  end
@@ -20,5 +20,5 @@
20
20
  # MA 02110-1301 USA
21
21
 
22
22
  module Storexplore
23
- VERSION = "0.1.1"
23
+ VERSION = "0.2.0"
24
24
  end
@@ -0,0 +1,47 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # dummy_store_api_shared_context.rb
4
+ #
5
+ # Copyright (c) 2011-2014 by Philippe Bourgau. All rights reserved.
6
+ #
7
+ # This library is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation; either
10
+ # version 3.0 of the License, or (at your option) any later version.
11
+ #
12
+ # This library is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public
18
+ # License along with this library; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301 USA
21
+
22
+ require 'spec_helper'
23
+
24
+ module Storexplore
25
+ module Testing
26
+
27
+ shared_context "a generated dummy store" do
28
+ def default_store_name
29
+ "www.spec-store.com"
30
+ end
31
+
32
+ def generate_store(store_name = default_store_name, item_count = 3)
33
+ DummyStore.wipe_out_store(store_name)
34
+ @store_generator = DummyStore.open(store_name)
35
+ @store_generator.generate(3).categories.and(3).categories.and(item_count).items
36
+
37
+ new_store(store_name)
38
+ end
39
+
40
+ def new_store(store_name = default_store_name)
41
+ Api.browse(DummyStore.uri(store_name))
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -20,27 +20,15 @@
20
20
  # MA 02110-1301 USA
21
21
 
22
22
  require 'spec_helper'
23
+ require_relative 'dummy_store_api_shared_context'
23
24
 
24
25
  module Storexplore
25
26
  module Testing
26
27
 
27
28
  describe "DummyStoreApi", slow: true do
28
- include ApiSpecMacros
29
-
30
- it_should_behave_like_any_store_items_api
31
-
32
- DEFAULT_STORE_NAME = "www.spec-store.com"
33
-
34
- def generate_store(store_name = DEFAULT_STORE_NAME, item_count = 3)
35
- DummyStore.wipe_out_store(store_name)
36
- @store_generator = DummyStore.open(store_name)
37
- @store_generator.generate(3).categories.and(3).categories.and(item_count).items
38
- @store = new_store(store_name)
39
- end
40
-
41
- def new_store(store_name = DEFAULT_STORE_NAME)
42
- Api.browse(DummyStore.uri(store_name))
43
- end
29
+ include_context "a generated dummy store"
30
+ include_context "a scrapped store"
31
+ it_should_behave_like "an API"
44
32
 
45
33
  it "should not truncate long item names" do
46
34
  @store_generator.
@@ -58,84 +46,6 @@ module Storexplore
58
46
  expect(item.attributes[:name]).to eq item_name
59
47
  end
60
48
 
61
- it "should use constant memory" do
62
- FEW = 10
63
- MANY = 100
64
- RUNS = 2
65
-
66
- many_inputs_memory = memory_usage_for_items(MANY, RUNS)
67
- few_inputs_memory = memory_usage_for_items(FEW, RUNS)
68
-
69
- slope = (many_inputs_memory - few_inputs_memory) / (MANY - FEW)
70
-
71
- zero_inputs_memory = few_inputs_memory - FEW * slope
72
-
73
- expect(slope).to be_within(zero_inputs_memory * 0.05).of(0.0)
74
- end
75
-
76
- def memory_usage_for_items(item_count, runs)
77
- generate_store(store_name = "www.spec-perf-store.com", item_count)
78
- data = runs.times.map do
79
- memory_peak_of do
80
- walk_store(store_name)
81
- end
82
- end
83
- mean(data)
84
- end
85
-
86
- def memory_peak_of
87
- peak_usage = 0
88
- finished = false
89
-
90
- initial_usage = current_living_objects
91
- profiler = Thread.new do
92
- while not finished
93
- peak_usage = [peak_usage, current_living_objects].max
94
- sleep(0.01)
95
- end
96
- end
97
-
98
- yield
99
-
100
- finished = true
101
- profiler.join
102
-
103
- peak_usage - initial_usage
104
- end
105
-
106
- def current_living_objects
107
- object_counts = ObjectSpace.count_objects
108
- object_counts[:TOTAL] - object_counts[:FREE]
109
- end
110
-
111
- def walk_store(store_name)
112
- new_store(store_name).categories.each do |category|
113
- register(category)
114
-
115
- category.categories.each do |sub_category|
116
- register(sub_category)
117
-
118
- sub_category.items.each do |item|
119
- register(item)
120
- end
121
- end
122
- end
123
- end
124
-
125
- def register(store_node)
126
- @title = store_node.title
127
- @attributes = store_node.attributes
128
-
129
- # No GC is explicitly done, because:
130
- # - large inputs forces it anyway
131
- # - it greatly slows tests
132
- # - GCing should not change the complexity of the system
133
- # GC.start
134
- end
135
-
136
- def mean(data)
137
- data.reduce(:+)/data.size
138
- end
139
49
  end
140
50
 
141
51
  end
@@ -0,0 +1,127 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # memory_usage_spec.rb
4
+ #
5
+ # Copyright (c) 2011-2014 by Philippe Bourgau. All rights reserved.
6
+ #
7
+ # This library is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation; either
10
+ # version 3.0 of the License, or (at your option) any later version.
11
+ #
12
+ # This library is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public
18
+ # License along with this library; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301 USA
21
+
22
+ require 'spec_helper'
23
+ require_relative 'dummy_store_api_shared_context'
24
+
25
+ module Storexplore
26
+ module Testing
27
+
28
+ describe "DummyStoreApi", slow: true do
29
+ include_context "a generated dummy store"
30
+ include_context "a scrapped store"
31
+
32
+ DEFAULT_STORE_NAME = "www.spec-store.com"
33
+
34
+ def generate_store(store_name = DEFAULT_STORE_NAME, item_count = 3)
35
+ DummyStore.wipe_out_store(store_name)
36
+ @store_generator = DummyStore.open(store_name)
37
+ @store_generator.generate(3).categories.and(3).categories.and(item_count).items
38
+
39
+ new_store(store_name)
40
+ end
41
+
42
+ def new_store(store_name = DEFAULT_STORE_NAME)
43
+ Api.browse(DummyStore.uri(store_name))
44
+ end
45
+
46
+ it "should use constant memory" do
47
+ FEW = 10
48
+ MANY = 100
49
+ RUNS = 2
50
+
51
+ many_inputs_memory = memory_usage_for_items(MANY, RUNS)
52
+ few_inputs_memory = memory_usage_for_items(FEW, RUNS)
53
+
54
+ slope = (many_inputs_memory - few_inputs_memory) / (MANY - FEW)
55
+
56
+ zero_inputs_memory = few_inputs_memory - FEW * slope
57
+
58
+ expect(slope).to be_within(zero_inputs_memory * 0.05).of(0.0)
59
+ end
60
+
61
+ def memory_usage_for_items(item_count, runs)
62
+ generate_store(store_name = "www.spec-perf-store.com", item_count)
63
+ data = runs.times.map do
64
+ memory_peak_of do
65
+ walk_store(store_name)
66
+ end
67
+ end
68
+ mean(data)
69
+ end
70
+
71
+ def memory_peak_of
72
+ peak_usage = 0
73
+ finished = false
74
+
75
+ initial_usage = current_living_objects
76
+ profiler = Thread.new do
77
+ while not finished
78
+ peak_usage = [peak_usage, current_living_objects].max
79
+ sleep(0.01)
80
+ end
81
+ end
82
+
83
+ yield
84
+
85
+ finished = true
86
+ profiler.join
87
+
88
+ peak_usage - initial_usage
89
+ end
90
+
91
+ def current_living_objects
92
+ object_counts = ObjectSpace.count_objects
93
+ object_counts[:TOTAL] - object_counts[:FREE]
94
+ end
95
+
96
+ def walk_store(store_name)
97
+ new_store(store_name).categories.each do |category|
98
+ register(category)
99
+
100
+ category.categories.each do |sub_category|
101
+ register(sub_category)
102
+
103
+ sub_category.items.each do |item|
104
+ register(item)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ def register(store_node)
111
+ @title = store_node.title
112
+ @attributes = store_node.attributes
113
+
114
+ # No GC is not explicitly done, because:
115
+ # - large inputs forces it anyway
116
+ # - it greatly slows tests
117
+ # - GCing should not change the complexity of the system
118
+ # GC.start
119
+ end
120
+
121
+ def mean(data)
122
+ data.reduce(:+)/data.size
123
+ end
124
+ end
125
+
126
+ end
127
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: storexplore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philou
@@ -31,7 +31,7 @@ cert_chain:
31
31
  yLcl1cmm5ALtJ/+Bkkmp0i4amXeTDMvq9r8PBsVsQwxYOYJBP+Umxz3PX6HjFHrQ
32
32
  XdkXx3oZ
33
33
  -----END CERTIFICATE-----
34
- date: 2014-01-16 00:00:00.000000000 Z
34
+ date: 2014-01-21 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: mechanize
@@ -142,6 +142,7 @@ files:
142
142
  - lib/storexplore/hash_utils.rb
143
143
  - lib/storexplore/null_digger.rb
144
144
  - lib/storexplore/testing.rb
145
+ - lib/storexplore/testing/api_shared_context.rb
145
146
  - lib/storexplore/testing/api_shared_examples.rb
146
147
  - lib/storexplore/testing/configuration.rb
147
148
  - lib/storexplore/testing/dummy_data.rb
@@ -159,7 +160,9 @@ files:
159
160
  - spec/lib/storexplore/api_spec.rb
160
161
  - spec/lib/storexplore/dsl_spec.rb
161
162
  - spec/lib/storexplore/store_walker_page_spec_fixture.html
163
+ - spec/lib/storexplore/testing/dummy_store_api_shared_context.rb
162
164
  - spec/lib/storexplore/testing/dummy_store_api_spec.rb
165
+ - spec/lib/storexplore/testing/memory_usage_spec.rb
163
166
  - spec/lib/storexplore/uri_utils_spec.rb
164
167
  - spec/lib/storexplore/walker_page_spec.rb
165
168
  - spec/spec_helper.rb
@@ -192,7 +195,9 @@ test_files:
192
195
  - spec/lib/storexplore/api_spec.rb
193
196
  - spec/lib/storexplore/dsl_spec.rb
194
197
  - spec/lib/storexplore/store_walker_page_spec_fixture.html
198
+ - spec/lib/storexplore/testing/dummy_store_api_shared_context.rb
195
199
  - spec/lib/storexplore/testing/dummy_store_api_spec.rb
200
+ - spec/lib/storexplore/testing/memory_usage_spec.rb
196
201
  - spec/lib/storexplore/uri_utils_spec.rb
197
202
  - spec/lib/storexplore/walker_page_spec.rb
198
203
  - spec/spec_helper.rb
metadata.gz.sig CHANGED
Binary file