spout 0.8.0.beta14 → 0.8.0.beta15

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: 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