spout 0.8.0.beta14 → 0.8.0.beta15

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44da8a99f11bf9cf6c779e891428be644ed2caf8
4
- data.tar.gz: 1880dbb0521218e67434e10912c0802c4b64b836
3
+ metadata.gz: c0ad7fac5482c072ad581a633a31afe12086a659
4
+ data.tar.gz: 20de4cb06ae7b431d5e96aa3d82308088986ee43
5
5
  SHA512:
6
- metadata.gz: 9ab9390da28670115f571beec8d1a266398a0e41906668aa926e200277b115e2f267ad2a52ed07fd492b4053590bec1effb9767aabcecc779a9bb4029243e69b
7
- data.tar.gz: 246aeeec4351aa0558e10d00320d3e1317d9801f942d9a8677742b4c9be5af16596cb9da5f669d445d6b8ed4d9bb875f5c819916652fbe3be7d584e50dd549b5
6
+ metadata.gz: 5b12a3c4217018bf0cd8f55344a3d0aace8693a538555ed1d234487872631841a4c4526cabd73f44b438368729cda39ed176086ca3bfebbd1c8769d38c7c9cb1
7
+ data.tar.gz: 48936868e7b7732ebd84eb2d7c71ff4724889a4395afa9e8adbbaca3ce270a3d95ec982342dde2b3a1a5258d79b9628b44f9b82c4ac0bd0fc04d1e7644458c44
data/CHANGELOG.md CHANGED
@@ -5,6 +5,9 @@
5
5
  - `include Spout::Tests::FormExistenceValidation`
6
6
  - `include Spout::Tests::FormNameUniqueness`
7
7
  - `include Spout::Tests::FormNameMatch`
8
+ - Test iterators have been added to provide access to `@variables`, `@forms`, and `@domains` to build custom tests in `dictionary_test.rb`
9
+ - Add the line `include Spout::Helpers::Iterators` to `dictionary_test.rb` to access the iterators
10
+ - See [README.md](https://github.com/sleepepi/spout/blob/master/README.md) for examples
8
11
  - Added `spout graphs` command that generates JSON charts and tables of each variable in a dataset
9
12
  - This command requires a .spout.yml file to be specified to identify the following variables:
10
13
  - `visit`: This variable is used to separate subject encounters in a histogram
@@ -15,6 +18,12 @@
15
18
  - Added `spout outliers` command that returns a list of integer or numeric variables that contain major and minor outliers
16
19
  - Removed the deprecated `spout hybrid` command
17
20
  - Spout tests are now run using minitest in favor of test unit
21
+ - Spout dictionary can now be loaded using the following command in irb:
22
+ - `require 'spout'; dictionary = Spout::Models::Dictionary.new(Dir.pwd)`
23
+ - `dictionary.load_all!`
24
+ - `dictionary.variables.count`
25
+ - `dictionary.domains.count`
26
+ - `dictionary.forms.count`
18
27
  - **Gem Changes**
19
28
  - Updated to colorize 0.7.2
20
29
  - Updated to minitest
data/README.md CHANGED
@@ -101,19 +101,20 @@ If not, you can add the following to your `test` directory to include all Spout
101
101
 
102
102
  `test/dictionary_test.rb`
103
103
 
104
- ```
104
+ ```ruby
105
105
  require 'spout/tests'
106
106
 
107
107
  class DictionaryTest < Minitest::Test
108
+ # This line includes all default Spout Dictionary tests
108
109
  include Spout::Tests
109
110
  end
110
111
  ```
111
112
 
112
- ```
113
+ ```ruby
113
114
  require 'spout/tests'
114
115
 
115
116
  class DictionaryTest < Minitest::Test
116
- # Or only include certain tests
117
+ # You can include only certain Spout tests by including them individually
117
118
  include Spout::Tests::JsonValidation
118
119
  include Spout::Tests::VariableTypeValidation
119
120
  include Spout::Tests::VariableNameUniqueness
@@ -128,10 +129,54 @@ end
128
129
 
129
130
  Then run either `spout test` or `bundle exec rake` to run your tests.
130
131
 
132
+ You can also use Spout iterators to create custom tests for variables, forms, and domains in your data dictionary.
133
+
134
+ **Example Custom Test 1:** Test that `integer` and `numeric` variables have a valid unit type
135
+
136
+ ```ruby
137
+ class DictionaryTest < Minitest::Test
138
+ # This line includes all default Spout Dictionary tests
139
+ include Spout::Tests
140
+
141
+ # This line provides access to @variables, @forms, and @domains iterators
142
+ # iterators that can be used to write custom tests
143
+ include Spout::Helpers::Iterators
144
+
145
+ VALID_UNITS = ['minutes', 'hours']
146
+
147
+ @variables.select{|v| v.type == 'numeric' or v.type == 'integer'}.each do |variable|
148
+ define_method("test_valid_units: "+variable.path) do
149
+ puts variable.class
150
+ # => Spout::Models::Variable
151
+ assert VALID_UNITS.include?(variable.units)
152
+ end
153
+ end
154
+ end
155
+ ```
156
+
157
+ **Example Custom Test 2:** Tests that variables have at least 2 or more labels.
158
+
159
+ ```ruby
160
+ class DictionaryTest < Minitest::Test
161
+ # This line includes all default Spout Dictionary tests
162
+ include Spout::Tests
163
+
164
+ # This line provides access to @variables, @forms, and @domains
165
+ # iterators that can be used to write custom tests
166
+ include Spout::Helpers::Iterators
167
+
168
+ @variables.select{|v| ['numeric','integer'].include?(v.type)}.each do |variable|
169
+ define_method("test_at_least_two_labels: "+variable.path) do
170
+ assert_operator 2, :<=, variable.labels.size
171
+ end
172
+ end
173
+ end
174
+ ```
175
+
131
176
 
132
177
  ### Test your data dictionary coverage of your dataset
133
178
 
134
- Spout lets you generate a nice visual coverage report that displays how well the data dictionary covers your dataset. Place your dataset csvs into `./csvs/` and then run the following Spout command:
179
+ Spout lets you generate a nice visual coverage report that displays how well the data dictionary covers your dataset. Place your dataset csvs into `./csvs/<version>/` and then run the following Spout command:
135
180
 
136
181
  ```
137
182
  spout coverage
@@ -1,6 +1,7 @@
1
1
  require 'csv'
2
2
  require 'json'
3
3
  require 'fileutils'
4
+ require 'colorize'
4
5
 
5
6
  module Spout
6
7
  module Commands
@@ -15,7 +15,8 @@ module Spout
15
15
  @variable_files = Dir.glob('variables/**/*.json')
16
16
  @standard_version = standard_version
17
17
  @pretend = (argv.delete('--pretend') != nil)
18
-
18
+ @sizes = sizes
19
+ @types = types
19
20
 
20
21
  @valid_ids = variable_ids
21
22
 
@@ -47,13 +48,12 @@ module Spout
47
48
  FileUtils.mkpath( options_folder )
48
49
  tmp_options_file = File.join( options_folder, 'options.json' )
49
50
 
50
- sizes = []
51
-
52
51
  variable_files_count = @variable_files.count
53
52
  @variable_files.each_with_index do |variable_file, file_index|
54
53
  json = JSON.parse(File.read(variable_file)) rescue json = nil
55
54
  next unless json
56
55
  next unless @valid_ids.include?(json["id"].to_s.downcase) or @valid_ids.size == 0
56
+ next unless @types.include?(json["type"]) or @types.size == 0
57
57
  next unless ["numeric", "integer", "choices"].include?(json["type"])
58
58
  variable_name = json['id'].to_s.downcase
59
59
  next unless Spout::Models::Subject.method_defined?(variable_name)
@@ -96,170 +96,14 @@ module Spout
96
96
  }
97
97
  eos
98
98
  end
99
- run_phantom_js("#{json['id']}-lg.png", 600, tmp_options_file) if sizes.size == 0 or sizes.include?('lg')
100
- run_phantom_js("#{json['id']}.png", 75, tmp_options_file) if sizes.size == 0 or sizes.include?('sm')
99
+ run_phantom_js("#{json['id']}-lg.png", 600, tmp_options_file) if @sizes.size == 0 or @sizes.include?('lg')
100
+ run_phantom_js("#{json['id']}.png", 75, tmp_options_file) if @sizes.size == 0 or @sizes.include?('sm')
101
101
  end
102
102
 
103
103
  end
104
- File.delete(tmp_options_file) if File.exists?(tmp_options_file)
104
+ File.delete(tmp_options_file) if File.exist?(tmp_options_file)
105
105
  end
106
106
 
107
-
108
- # def initialize(types, variable_ids, sizes, standard_version)
109
- # @standard_version = standard_version
110
- # total_index_count = Dir.glob("variables/**/*.json").count
111
-
112
- # last_completed = 0
113
-
114
- # options_folder = "images/#{@standard_version}"
115
- # FileUtils.mkpath( options_folder )
116
- # tmp_options_file = File.join( options_folder, 'options.json' )
117
-
118
- # Dir.glob("csvs/#{standard_version}/*.csv").each do |csv_file|
119
- # puts "Working on: #{csv_file}"
120
- # t = Time.now
121
- # csv_table = CSV.table(csv_file, encoding: 'iso-8859-1').by_col!
122
- # puts "Loaded #{csv_file} in #{Time.now - t} seconds."
123
-
124
- # total_header_count = csv_table.headers.count
125
- # csv_table.headers.each_with_index do |header, index|
126
- # puts "Column #{ index + 1 } of #{ total_header_count } for #{header} in #{csv_file}"
127
- # if variable_file = Dir.glob("variables/**/#{header.downcase}.json", File::FNM_CASEFOLD).first
128
- # json = JSON.parse(File.read(variable_file)) rescue json = nil
129
- # next unless json
130
- # next unless ["choices", "numeric", "integer"].include?(json["type"])
131
- # next unless types.size == 0 or types.include?(json['type'])
132
- # next unless variable_ids.size == 0 or variable_ids.include?(json['id'].to_s.downcase)
133
-
134
- # basename = File.basename(variable_file).gsub(/\.json$/, '').downcase
135
- # col_data = csv_table[header]
136
-
137
- # case json["type"] when "choices"
138
- # domain_file = Dir.glob("domains/**/#{json['domain']}.json").first
139
- # domain_json = JSON.parse(File.read(domain_file)) rescue domain_json = nil
140
- # next unless domain_json
141
-
142
- # create_pie_chart_options_file(col_data, tmp_options_file, domain_json)
143
- # when 'numeric', 'integer'
144
- # create_line_chart_options_file(col_data, tmp_options_file, json["units"])
145
- # else
146
- # next
147
- # end
148
-
149
- # run_phantom_js("#{basename}-lg.png", 600, tmp_options_file) if sizes.size == 0 or sizes.include?('lg')
150
- # run_phantom_js("#{basename}.png", 75, tmp_options_file) if sizes.size == 0 or sizes.include?('sm')
151
- # end
152
- # end
153
- # end
154
- # File.delete(tmp_options_file) if File.exists?(tmp_options_file)
155
- # end
156
-
157
- # def graph_values(col_data)
158
- # categories = []
159
-
160
- # col_data = col_data.select{|v| !['', 'null'].include?(v.to_s.strip.downcase)}.collect(&:to_f)
161
-
162
- # all_integers = false
163
- # all_integers = (col_data.count{|i| i.denominator != 1} == 0)
164
-
165
- # minimum = col_data.min || 0
166
- # maximum = col_data.max || 100
167
-
168
- # default_max_buckets = 30
169
- # max_buckets = all_integers ? [maximum - minimum + 1, default_max_buckets].min : default_max_buckets
170
- # bucket_size = (maximum - minimum + 1).to_f / max_buckets
171
-
172
- # (0..(max_buckets-1)).each do |bucket|
173
- # val_min = (bucket_size * bucket) + minimum
174
- # val_max = bucket_size * (bucket + 1) + minimum
175
- # # Greater or equal to val_min, less than val_max
176
- # # categories << "'#{val_min} to #{val_max}'"
177
- # categories << "#{all_integers || (maximum - minimum) > (default_max_buckets / 2) ? val_min.round : "%0.02f" % val_min}"
178
- # end
179
-
180
- # new_values = []
181
- # (0..max_buckets-1).each do |bucket|
182
- # val_min = (bucket_size * bucket) + minimum
183
- # val_max = bucket_size * (bucket + 1) + minimum
184
- # # Greater or equal to val_min, less than val_max
185
- # new_values << col_data.count{|i| i >= val_min and i < val_max}
186
- # end
187
-
188
- # values = []
189
-
190
- # values << { name: '', data: new_values, showInLegend: false }
191
-
192
- # [ values, categories ]
193
- # end
194
-
195
-
196
- # def create_pie_chart_options_file(values, options_file, domain_json)
197
-
198
- # values.select!{|v| !['', 'null'].include?(v.to_s.strip.downcase) }
199
- # counts = values.group_by{|a| a}.collect{|k,v| [(domain_json.select{|h| h['value'] == k.to_s}.first['display_name'] rescue (k.to_s == '' ? 'NULL' : k)), v.count]}
200
-
201
- # total_count = counts.collect(&:last).inject(&:+)
202
-
203
- # data = counts.collect{|value, count| [value, (count * 100.0 / total_count)]}
204
-
205
- # File.open(options_file, "w") do |outfile|
206
- # outfile.puts <<-eos
207
- # {
208
- # "title": {
209
- # "text": ""
210
- # },
211
-
212
- # "credits": {
213
- # "enabled": false,
214
- # },
215
- # "series": [{
216
- # "type": "pie",
217
- # "name": "",
218
- # "data": #{data.to_json}
219
- # }]
220
- # }
221
- # eos
222
- # end
223
- # end
224
-
225
-
226
- # def create_line_chart_options_file(values, options_file, units)
227
- # ( series, categories ) = graph_values(values)
228
-
229
- # File.open(options_file, "w") do |outfile|
230
- # outfile.puts <<-eos
231
- # {
232
- # "chart": {
233
- # "type": "areaspline"
234
- # },
235
- # "title": {
236
- # "text": ""
237
- # },
238
- # "credits": {
239
- # "enabled": false,
240
- # },
241
- # "xAxis": {
242
- # "categories": #{categories.to_json},
243
- # "labels": {
244
- # "step": #{(categories.size.to_f / 12).ceil}
245
- # },
246
- # "title": {
247
- # "text": #{units.to_json}
248
- # }
249
- # },
250
- # "yAxis": {
251
- # "maxPadding": 0,
252
- # "minPadding": 0,
253
- # "title": {
254
- # "text": "Count"
255
- # }
256
- # },
257
- # "series": #{series.to_json}
258
- # }
259
- # eos
260
- # end
261
- # end
262
-
263
107
  def run_phantom_js(png_name, width, tmp_options_file)
264
108
  graph_path = File.join(Dir.pwd, 'images', @standard_version, png_name)
265
109
  directory = File.join( File.dirname(__FILE__), '..', 'support', 'javascripts' )
@@ -1,6 +1,7 @@
1
1
  require 'csv'
2
2
  require 'json'
3
3
  require 'fileutils'
4
+ require 'colorize'
4
5
 
5
6
  module Spout
6
7
  module Commands
@@ -10,7 +11,7 @@ module Spout
10
11
 
11
12
  @csv_file = argv[1].to_s
12
13
 
13
- unless File.exists?(@csv_file)
14
+ unless File.exist?(@csv_file)
14
15
  puts csv_usage
15
16
  return self
16
17
  end
@@ -1,3 +1,5 @@
1
+ require 'colorize'
2
+
1
3
  TEMPLATES_DIRECTORY = File.expand_path('../../templates', __FILE__)
2
4
 
3
5
  module Spout
@@ -35,6 +37,8 @@ EOT
35
37
  copy_file 'keep', 'domains/.keep'
36
38
  directory 'variables'
37
39
  copy_file 'keep', 'variables/.keep'
40
+ directory 'forms'
41
+ copy_file 'keep', 'forms/.keep'
38
42
  directory 'test'
39
43
  copy_file 'test/dictionary_test.rb'
40
44
  copy_file 'test/test_helper.rb'
@@ -1,5 +1,3 @@
1
- # array_statistics.rb
2
-
3
1
  class Array
4
2
  def n
5
3
  self.compact.count
@@ -0,0 +1,17 @@
1
+ require 'spout/models/dictionary'
2
+
3
+ module Spout
4
+ module Helpers
5
+ module Iterators
6
+
7
+ def self.included(c)
8
+ class << c; attr_accessor :dictionary, :variables, :domains, :forms; end
9
+ c.instance_variable_set(:@dictionary, Spout::Models::Dictionary.new(Dir.pwd).load_all!)
10
+ c.instance_variable_set(:@variables, c.instance_variable_get(:@dictionary).variables)
11
+ c.instance_variable_set(:@domains, c.instance_variable_get(:@dictionary).domains)
12
+ c.instance_variable_set(:@forms, c.instance_variable_get(:@dictionary).forms)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Spout
2
4
  module Helpers
3
5
  class JsonLoader
@@ -0,0 +1,59 @@
1
+ require 'spout/models/variable'
2
+ require 'spout/models/domain'
3
+ require 'spout/models/form'
4
+
5
+ module Spout
6
+ module Models
7
+ class Dictionary
8
+ attr_accessor :variables, :domains, :forms
9
+ attr_accessor :app_path
10
+
11
+ attr_reader :variable_files, :domain_files, :form_files
12
+
13
+ def initialize(app_path)
14
+ @app_path = app_path
15
+
16
+ @variable_files = json_files('variables')
17
+ @domain_files = json_files('domains')
18
+ @form_files = json_files('forms')
19
+
20
+ @variables = []
21
+ @domains = []
22
+ @forms = []
23
+ end
24
+
25
+ def load_all!
26
+ load_variables!
27
+ load_domains!
28
+ load_forms!
29
+ self
30
+ end
31
+
32
+ def load_variables!
33
+ load_type!('Variable')
34
+ end
35
+
36
+ def load_domains!
37
+ load_type!('Domain')
38
+ end
39
+
40
+ def load_forms!
41
+ load_type!('Form')
42
+ end
43
+
44
+ private
45
+
46
+ def json_files(type)
47
+ Dir.glob(File.join(@app_path, type, "**", "*.json"))
48
+ end
49
+
50
+ def load_type!(method)
51
+ results = instance_variable_get("@#{method.downcase}_files").collect do |file|
52
+ Object.const_get("Spout::Models::#{method}").new(file, @app_path)
53
+ end
54
+
55
+ instance_variable_set("@#{method.downcase}s", results)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+
3
+ require 'spout/models/option'
4
+
5
+ module Spout
6
+ module Models
7
+
8
+ class Domain
9
+ attr_accessor :id, :folder, :options
10
+ attr_reader :errors
11
+
12
+ def initialize(file_name, dictionary_root)
13
+ @errors = []
14
+ @id = file_name.to_s.gsub(/^(.*)\/|\.json$/, '').downcase
15
+
16
+ @folder = file_name.to_s.gsub(/^#{dictionary_root}\/domains\/|#{@id}\.json$/, '')
17
+ @options = []
18
+
19
+ json = begin
20
+ if File.exist?(file_name)
21
+ JSON.parse(File.read(file_name))
22
+ else
23
+ @errors << "No corresponding #{@id}.json file found."
24
+ nil
25
+ end
26
+ rescue => e
27
+ @errors << "Parsing error found in #{@id}.json: #{e.message}" if file_name != nil
28
+ nil
29
+ end
30
+
31
+ if json and json.kind_of? Array
32
+ @id = file_name.to_s.gsub(/^(.*)\/|\.json$/, '').downcase
33
+ @options = (json || []).collect do |option|
34
+ Spout::Models::Option.new(option)
35
+ end
36
+ elsif json
37
+ @errors << "Domain must be a valid array in the following format: [\n {\n \"value\": \"1\",\n \"display_name\": \"First Choice\",\n \"description\": \"First Description\"\n },\n {\n \"value\": \"2\",\n \"display_name\": \"Second Choice\",\n \"description\": \"Second Description\"\n }\n]"
38
+ end
39
+
40
+ end
41
+
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ # {
2
+ # "id": "intake_questionnaire",
3
+ # "display_name": "Intake Questionnaire at Baseline Visit",
4
+ # "code_book": "Baseline-Visit-Intake-Questionnaire.pdf"
5
+ # }
6
+
7
+ require 'json'
8
+
9
+ module Spout
10
+ module Models
11
+ class Form
12
+ attr_accessor :id, :display_name, :code_book
13
+ attr_accessor :errors
14
+
15
+ def initialize(file_name, dictionary_root)
16
+ @errors = []
17
+ @id = file_name.to_s.gsub(/^(.*)\/|\.json$/, '').downcase
18
+ @folder = file_name.to_s.gsub(/^#{dictionary_root}\/forms\/|#{@id}\.json$/, '')
19
+
20
+ json = begin
21
+ JSON.parse(File.read(file_name))
22
+ rescue => e
23
+ form_name = file_name.to_s.gsub(/^(.*)\/|\.json$/, '').downcase
24
+ @errors << "Error Parsing #{form_name}.json: #{e.message}"
25
+ nil
26
+ end
27
+
28
+ if json and json.kind_of? Hash
29
+ %w( display_name code_book ).each do |method|
30
+ instance_variable_set("@#{method}", json[method])
31
+ end
32
+
33
+ @errors << "'id': #{json['id'].inspect} does not match filename #{@id.inspect}" if @id != json['id']
34
+ elsif json
35
+ @errors << "Form must be a valid hash in the following format: {\n\"id\": \"FORM_ID\",\n \"display_name\": \"FORM DISPLAY NAME\",\n \"code_book\": \"FORMPDF.pdf\"\n}"
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ module Spout
2
+ module Models
3
+ class Option
4
+ attr_accessor :display_name, :value, :description
5
+
6
+ def initialize(option_hash)
7
+ %w( display_name value description ).each do |method|
8
+ instance_variable_set("@#{method}", (option_hash.kind_of?(Hash) ? option_hash : {})[method])
9
+ end
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ require 'json'
2
+
3
+ module Spout
4
+ module Models
5
+ class Variable
6
+ # VARIABLE_TYPES = ['choices', 'numeric', 'integer']
7
+
8
+ attr_accessor :id, :folder, :display_name, :description, :type, :units, :labels, :commonly_used
9
+ attr_accessor :domain_name, :form_names
10
+ attr_accessor :domain, :forms
11
+ attr_reader :errors
12
+
13
+ def initialize(file_name, dictionary_root)
14
+ @errors = []
15
+ @id = file_name.to_s.gsub(/^(.*)\/|\.json$/, '').downcase
16
+ @folder = file_name.to_s.gsub(/^#{dictionary_root}\/variables\/|#{@id}\.json$/, '')
17
+
18
+
19
+ json = begin
20
+ JSON.parse(File.read(file_name))
21
+ rescue => e
22
+ error = e.message
23
+ nil
24
+ end
25
+
26
+ if json and json.kind_of? Hash
27
+
28
+ %w( display_name description type units commonly_used ).each do |method|
29
+ instance_variable_set("@#{method}", json[method])
30
+ end
31
+
32
+ @errors << "'id': #{json['id'].inspect} does not match filename #{@id.inspect}" if @id != json['id']
33
+
34
+ @domain_name = json['domain'] # Spout::Models::Domain.new(json['domain'], dictionary_root)
35
+ @labels = (json['labels'] || [])
36
+ @form_names = (json['forms'] || []).collect do |form_name|
37
+ form_name
38
+ end
39
+ elsif json
40
+ @errors << "Variable must be a valid hash in the following format: {\n\"id\": \"VARIABLE_ID\",\n \"display_name\": \"VARIABLE DISPLAY NAME\",\n \"description\": \"VARIABLE DESCRIPTION\"\n}"
41
+ end
42
+
43
+ @errors = (@errors + [error]).compact
44
+ end
45
+
46
+ def path
47
+ File.join(@folder, "#{@id}.json")
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -1,2 +1 @@
1
- require 'spout'
2
- Spout::Application.new.load_tasks
1
+ require 'spout/tasks'
@@ -1,8 +1,32 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DictionaryTest < Minitest::Test
4
+ # This line includes all default Spout Dictionary tests
4
5
  include Spout::Tests
5
6
 
7
+ # This line provides access to @variables, @forms, and @domains iterators
8
+ # iterators that can be used to write custom tests
9
+ include Spout::Helpers::Iterators
10
+
11
+ # Example 1: Create custom tests to show that `integer` and `numeric` variables have a valid unit type
12
+ # VALID_UNITS = ['minutes', 'hours'] # Add your own valid units to this array
13
+ # @variables.select{|v| v.type == 'numeric' or v.type == 'integer'}.each do |variable|
14
+ # define_method("test_units: "+variable.path) do
15
+ # message = "\"#{variable.units}\"".colorize( :red ) + " invalid units.\n" +
16
+ # " Valid types: " +
17
+ # VALID_UNITS.sort.collect{|u| u.inspect.colorize( :white )}.join(', ')
18
+ # assert VALID_UNITS.include?(variable.units), message
19
+ # end
20
+ # end
21
+
22
+ # Example 2: Create custom tests to show that variables have 2 or more labels.
23
+ # @variables.select{|v| ['numeric','integer'].include?(v.type)}.each do |variable|
24
+ # define_method("test_at_least_two_labels: "+variable.path) do
25
+ # assert_operator 2, :<=, variable.labels.size
26
+ # end
27
+ # end
28
+
29
+ # Example 3: Create regular Ruby tests
6
30
  # You may add additional tests here
7
31
  # def test_truth
8
32
  # assert true
data/lib/spout/tests.rb CHANGED
@@ -75,6 +75,8 @@ require 'spout/tests/form_existence_validation'
75
75
  require 'spout/tests/form_name_uniqueness'
76
76
  require 'spout/tests/form_name_match'
77
77
 
78
+ require 'spout/helpers/iterators'
79
+
78
80
  module Spout
79
81
  module Tests
80
82
  include Spout::Tests::JsonValidation
data/lib/spout/version.rb CHANGED
@@ -3,7 +3,7 @@ module Spout
3
3
  MAJOR = 0
4
4
  MINOR = 8
5
5
  TINY = 0
6
- BUILD = "beta14" # nil, "pre", "rc", "rc2"
6
+ BUILD = "beta15" # nil, "pre", "rc", "rc2"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, BUILD].compact.join('.')
9
9
  end
data/lib/spout.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require "spout/version"
2
- require "spout/application"
3
- require 'spout/tasks'
2
+
3
+ require 'spout/models/dictionary'
4
4
 
5
5
  Spout::COMMANDS = {
6
6
  'n' => :new_project,
@@ -108,7 +108,7 @@ EOT
108
108
  private
109
109
 
110
110
  def self.flag_values(flags, param)
111
- flags.select{|f| f[0..((param.size + 3) - 1)] == "--#{param}-" and f.length > param.size + 3}.collect{|f| f[(param.size + 3)..-1]}
111
+ flags.select{|f| f =~ /^--#{param}-/}.collect{|f| f[(param.size + 3)..-1]}
112
112
  end
113
113
 
114
114
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0.beta14
4
+ version: 0.8.0.beta15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Remo Mueller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-05 00:00:00.000000000 Z
11
+ date: 2014-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -109,7 +109,6 @@ files:
109
109
  - Rakefile
110
110
  - bin/spout
111
111
  - lib/spout.rb
112
- - lib/spout/application.rb
113
112
  - lib/spout/commands/coverage.rb
114
113
  - lib/spout/commands/exporter.rb
115
114
  - lib/spout/commands/graphs.rb
@@ -117,16 +116,21 @@ files:
117
116
  - lib/spout/commands/importer.rb
118
117
  - lib/spout/commands/outliers.rb
119
118
  - lib/spout/commands/project_generator.rb
120
- - lib/spout/commands/test_runner.rb
121
119
  - lib/spout/helpers/array_statistics.rb
122
120
  - lib/spout/helpers/chart_types.rb
121
+ - lib/spout/helpers/iterators.rb
123
122
  - lib/spout/helpers/json_loader.rb
124
123
  - lib/spout/helpers/number_helper.rb
125
124
  - lib/spout/helpers/subject_loader.rb
126
125
  - lib/spout/helpers/table_formatting.rb
127
126
  - lib/spout/models/coverage_result.rb
127
+ - lib/spout/models/dictionary.rb
128
+ - lib/spout/models/domain.rb
129
+ - lib/spout/models/form.rb
130
+ - lib/spout/models/option.rb
128
131
  - lib/spout/models/outlier_result.rb
129
132
  - lib/spout/models/subject.rb
133
+ - lib/spout/models/variable.rb
130
134
  - lib/spout/support/javascripts/data.js
131
135
  - lib/spout/support/javascripts/highcharts-convert.js
132
136
  - lib/spout/support/javascripts/highcharts-more.js
@@ -1,13 +0,0 @@
1
- module Spout
2
- class Application
3
- attr_accessor :version
4
-
5
- def initialize
6
- @version = '1.0.0'
7
- end
8
-
9
- def load_tasks
10
- require "spout/tasks"
11
- end
12
- end
13
- end
@@ -1,35 +0,0 @@
1
- # module Spout
2
- # module Commands
3
- # class TestRunner
4
- # def initialize(argv)
5
- # verbose = (argv.delete('--verbose') != nil)
6
-
7
- # puts "Loaded Suite test"
8
-
9
- # files_loaded = []
10
-
11
-
12
- # Dir.chdir("test") do
13
- # $:.unshift(Dir.pwd)
14
- # Dir.glob(File.join("**", "*_test.rb")).each do |test_file|
15
- # files_loaded << test_file
16
- # require 'spout/tests'
17
- # Spout::Tests.class_eval File.read(test_file)
18
- # # load test_file #.gsub(/\.rb$/, '')
19
- # end
20
- # end
21
-
22
- # puts files_loaded.inspect
23
- # puts Spout::Tests.constants
24
-
25
- # Spout::Tests.constants.select{|c| Spout::Tests.const_get(c).is_a? Class}.each do |klass|
26
- # puts "KLASS: #{klass}"
27
- # my_instance = Spout::Tests.const_get(klass).new
28
- # puts my_instance.methods.select{|m| m.to_s =~ /^test\_/}.inspect
29
- # end
30
- # # puts Spout::Tests::JsonValidation.methods
31
-
32
- # end
33
- # end
34
- # end
35
- # end