typingpool 0.8.11 → 0.8.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/bin/tp-assign +5 -4
  3. data/bin/tp-collect +16 -6
  4. data/bin/tp-finish +5 -4
  5. data/bin/tp-make +5 -4
  6. data/bin/tp-review +52 -26
  7. data/lib/typingpool/test.rb +4 -126
  8. data/lib/typingpool/test/fixtures/tp_collect_id.txt +1 -1
  9. data/lib/typingpool/test/fixtures/tp_collect_sandbox-assignment.csv +7 -8
  10. data/lib/typingpool/test/fixtures/tp_review2a_id.txt +1 -0
  11. data/lib/typingpool/test/fixtures/tp_review2a_sandbox-assignment.csv +7 -0
  12. data/lib/typingpool/test/fixtures/tp_review2b_id.txt +1 -0
  13. data/lib/typingpool/test/fixtures/tp_review2b_sandbox-assignment.csv +7 -0
  14. data/lib/typingpool/test/fixtures/tp_review3_id.txt +1 -0
  15. data/lib/typingpool/test/fixtures/tp_review3_sandbox-assignment.csv +7 -0
  16. data/lib/typingpool/test/fixtures/tp_review_id.txt +1 -1
  17. data/lib/typingpool/test/fixtures/tp_review_sandbox-assignment.csv +7 -8
  18. data/lib/typingpool/test/fixtures/vcr/tp-collect-1.yml +3176 -1814
  19. data/lib/typingpool/test/fixtures/vcr/tp-collect-2.yml +116 -2641
  20. data/lib/typingpool/test/fixtures/vcr/tp-collect-3.yml +119 -2693
  21. data/lib/typingpool/test/fixtures/vcr/tp-review-1.yml +353 -355
  22. data/lib/typingpool/test/fixtures/vcr/tp-review-2.yml +161 -242
  23. data/lib/typingpool/test/fixtures/vcr/tp-review-3.yml +4716 -0
  24. data/lib/typingpool/test/fixtures/vcr/tp-review-4.yml +741 -0
  25. data/lib/typingpool/test/fixtures/vcr/tp-review-5.yml +248 -0
  26. data/lib/typingpool/test/fixtures/vcr/tp-review-6.yml +233 -0
  27. data/lib/typingpool/test/fixtures/vcr/tp-review-7.yml +4479 -0
  28. data/lib/typingpool/test/fixtures/vcr/tp-review-8.yml +188 -0
  29. data/lib/typingpool/test/fixtures/vcr/tp-review-9.yml +187 -0
  30. data/lib/typingpool/test/script.rb +13 -320
  31. data/lib/typingpool/utility/test.rb +175 -0
  32. data/lib/typingpool/utility/test/script.rb +342 -0
  33. data/lib/typingpool/version.rb +1 -1
  34. data/test/make_amazon_question_fixture.rb +1 -1
  35. data/test/make_tp_collect_fixture_1.rb +18 -19
  36. data/test/make_tp_collect_fixture_2.rb +16 -10
  37. data/test/make_tp_collect_fixture_3.rb +15 -9
  38. data/test/make_tp_collect_fixture_4.rb +19 -11
  39. data/test/make_tp_collect_fixture_5.rb +25 -0
  40. data/test/make_tp_collect_fixture_6.rb +22 -0
  41. data/test/make_tp_collect_fixture_7.rb +22 -0
  42. data/test/make_tp_collect_fixture_8.rb +26 -0
  43. data/test/make_tp_review_fixture_1.rb +18 -19
  44. data/test/make_tp_review_fixture_2.rb +43 -24
  45. data/test/make_tp_review_fixture_3.rb +35 -0
  46. data/test/make_tp_review_fixture_4.rb +56 -0
  47. data/test/test_integration_script_1_tp_config.rb +7 -7
  48. data/test/test_integration_script_2_tp_make.rb +12 -12
  49. data/test/test_integration_script_3_tp_assign.rb +23 -21
  50. data/test/test_integration_script_4_tp_review.rb +156 -23
  51. data/test/test_integration_script_5_tp_collect.rb +33 -24
  52. data/test/test_integration_script_6_tp_finish.rb +23 -20
  53. data/test/test_unit_amazon.rb +4 -2
  54. data/test/test_unit_filer.rb +6 -6
  55. data/test/test_unit_project.rb +2 -2
  56. data/test/test_unit_project_local.rb +2 -2
  57. data/test/test_unit_project_remote.rb +3 -1
  58. data/test/test_unit_template.rb +6 -6
  59. data/test/test_unit_test.rb +3 -3
  60. metadata +23 -3
  61. data/lib/typingpool/app/test.rb +0 -69
@@ -0,0 +1,175 @@
1
+ module Typingpool
2
+ module Utility
3
+ module Test
4
+ require 'vcr'
5
+ require 'uri'
6
+
7
+ def fixtures_dir
8
+ File.join(Utility.lib_dir, 'test', 'fixtures')
9
+ end
10
+
11
+ def audio_dir
12
+ File.join(fixtures_dir, 'audio')
13
+ end
14
+
15
+ def vcr_dir
16
+ File.join(fixtures_dir, 'vcr')
17
+ end
18
+
19
+ def delete_vcr_fixture(fixture_name)
20
+ fixture_path = File.join(vcr_dir, [fixture_name, '.yml'].join)
21
+ File.delete(fixture_path) if File.exist? fixture_path
22
+ end
23
+
24
+ def cleared_vcr_fixture_path_for(fixture_name)
25
+ if Typingpool::Test.record
26
+ delete_vcr_fixture(fixture_name)
27
+ end
28
+ if (Typingpool::Test.record || not(Typingpool::Test.live))
29
+ File.join(vcr_dir, fixture_name)
30
+ end
31
+ end
32
+
33
+ def with_vcr(fixture_name, config, opts={})
34
+ if fixture = cleared_vcr_fixture_path_for(fixture_name)
35
+ read_only = not(Typingpool::Test.record)
36
+ vcr_load(fixture, config, read_only, opts)
37
+ end
38
+ begin
39
+ yield
40
+ ensure
41
+ vcr_stop
42
+ end
43
+ end
44
+
45
+ #Loads an HTTP mock fixture for playback (default) or
46
+ #recording. Used in automated tests. Uses the great VCR gem.
47
+ #
48
+ #Automatically filters your Config#amazon#key and
49
+ #Config#amazon#secret from the recorded fixture, and
50
+ #automatically determines the "cassette" name and "cassette
51
+ #library" dir from the supplied path.
52
+ # ==== Params
53
+ # [fixture_path] Path to where you want the HTTP fixture
54
+ # recorded, including filename.
55
+ # [config] A Config instance, used to extract the
56
+ # Config#amazon#secret and Config#amazon#key that
57
+ # will be filtered from the fixture.
58
+ # [read_only] Default is true. Set to false to enable recording.
59
+ # [vcr_params] Default is nil. A hash of params to pass to
60
+ # VCR.insert_cassette (same set of params that
61
+ # can be passed to VCR.use_cassette), like
62
+ # :preserve_exact_body_bytes or
63
+ # :match_requests_on => [:url, :matcher]. If nil,
64
+ # no extra params will be passed.
65
+ # ==== Returns
66
+ # Result of calling VCR.insert_cassette.
67
+ def vcr_load(fixture_path, config, read_only=true, vcr_params=nil)
68
+ VCR.configure do |c|
69
+ c.cassette_library_dir = File.dirname(fixture_path)
70
+ c.hook_into :webmock
71
+ c.filter_sensitive_data('<AWS_KEY>'){ config.amazon.key }
72
+ c.filter_sensitive_data('<AWS_SECRET>'){ config.amazon.secret }
73
+ c.before_record do |interaction|
74
+ if interaction.request.body.size > 10000
75
+ interaction.request.body = '<BIG_UPLOAD>'
76
+ end
77
+ end #c.before_record do...
78
+ end
79
+ WebMock.allow_net_connect!
80
+ opts = {:record => (read_only ? :none : :once)}
81
+ opts.merge!(vcr_params) if vcr_params
82
+ VCR.turn_on!
83
+ VCR.insert_cassette(File.basename(fixture_path, '.*'),
84
+ opts
85
+ )
86
+
87
+ end
88
+
89
+ #Stops playing/recording from the last call to vcr_load. Returns the
90
+ #result of VCR.eject_cassette.
91
+ def vcr_stop
92
+ VCR.eject_cassette
93
+ VCR.turn_off!
94
+ end
95
+
96
+ #great for s3 because we don't have to worry about changing
97
+ #bucket names, only matches as far as s3.amazonaws.com
98
+ def vcr_core_host_matcher
99
+ lambda do |request1, request2|
100
+ core_host = lambda{|host| host.split(/\./).reverse.slice(0, 3).reverse.join('.')}
101
+ core_host.call(URI(request1.uri).host) == core_host.call(URI(request2.uri).host)
102
+ end #lambda do...
103
+ end
104
+
105
+ def config
106
+ if File.exist?(File.expand_path(Config.default_file))
107
+ Config.file
108
+ else
109
+ Config.from_bundled_template
110
+ end
111
+ end
112
+
113
+ def amazon_credentials?(config=self.config)
114
+ config.amazon && config.amazon.key && config.amazon.secret
115
+ end
116
+
117
+ def s3_credentials?(config)
118
+ amazon_credentials?(config) && config.amazon.bucket
119
+ end
120
+
121
+ def sftp_credentials?(config)
122
+ config.sftp && config.sftp.user && config.sftp.host && config.sftp.url
123
+ end
124
+
125
+ def add_goodbye_message(msg)
126
+ at_exit do
127
+ STDERR.puts msg
128
+ end
129
+ end
130
+
131
+ def dummy_config(number=1)
132
+ Typingpool::Config.file(File.join(fixtures_dir, "config-#{number}"))
133
+ end
134
+
135
+
136
+ def project_default
137
+ Hash[
138
+ :config_filename => '.config',
139
+ :subtitle => "Typingpool's test interview transcription",
140
+ :title => "Typingpool's Test & Interview",
141
+ :chunks => '0:22',
142
+ :unusual => ['Hack Day', 'Sunnyvale', 'Chad D'],
143
+ :voice => ['Ryan', 'Havi, hacker'],
144
+ ]
145
+ end
146
+
147
+ def works_eventually?(max_seconds=10, min_tries=2)
148
+ start = Time.now.to_i
149
+ tries = 0
150
+ wait = 0
151
+ until ((tries >= min_tries) && ((Time.now.to_i + wait - start) >= max_seconds)) do
152
+ sleep wait
153
+ return true if yield
154
+ wait = wait > 0 ? wait * 2 : 1
155
+ tries += 1
156
+ end
157
+ false
158
+ end
159
+
160
+ def working_url_eventually?(url, max_seconds=10, min_tries=2, max_redirects=6)
161
+ works_eventually?(max_seconds, min_tries) do
162
+ Utility.working_url?(url, max_redirects)
163
+ end
164
+ end
165
+
166
+ def broken_url_eventually?(url, max_seconds=10, min_tries=2, max_redirects=6)
167
+ works_eventually?(max_seconds, min_tries) do
168
+ not(Utility.working_url?(url, max_redirects))
169
+ end
170
+ end
171
+
172
+
173
+ end #Test
174
+ end #Utility
175
+ end #Typingpool
@@ -0,0 +1,342 @@
1
+ module Typingpool
2
+ module Utility
3
+ module Test
4
+ module Script
5
+ require 'yaml'
6
+ require 'fileutils'
7
+ require 'open3'
8
+ require 'tmpdir'
9
+ require 'typingpool/utility/test'
10
+
11
+ include Typingpool::Utility::Test
12
+
13
+
14
+ @@readymade_project_path = nil
15
+
16
+ def with_temp_readymade_project
17
+ Dir.mktmpdir('typingpool_') do |transcripts_dir|
18
+ FileUtils.cp_r(File.join(readymade_project_path, '.'), transcripts_dir)
19
+ config = reconfigure_for_transcripts_dir(
20
+ Config.file(config_path(transcripts_dir)),
21
+ transcripts_dir)
22
+ write_config(transcripts_dir, config)
23
+ reconfigure_project(Project.new(project_default[:title], config))
24
+ yield(transcripts_dir)
25
+ end
26
+ end
27
+
28
+ def with_temp_transcripts_dir
29
+ Dir.mktmpdir('typingpool_') do |transcripts_dir|
30
+ write_testing_config_for_transcripts_dir(transcripts_dir, self.config)
31
+ yield(transcripts_dir)
32
+ end
33
+ end
34
+
35
+ def reconfigure_for_s3(config)
36
+ unless s3_credentials?(config)
37
+ raise Error::Test, "No S3 credentials available"
38
+ end
39
+ config.to_hash.delete('sftp')
40
+ config
41
+ end
42
+
43
+ def reconfigure_for_transcripts_dir(config, transcripts_dir)
44
+ config.transcripts = transcripts_dir
45
+ config.cache = File.join(transcripts_dir, '.cache')
46
+ config
47
+ end
48
+
49
+ def reconfigure_for_testing(config)
50
+ config['assign']['reward'] = '0.02'
51
+ config.assign.to_hash.delete('qualify')
52
+ config
53
+ end
54
+
55
+ def write_config(dir, config, filename=project_default[:config_filename])
56
+ path = File.join(dir, filename)
57
+ File.write(path, YAML.dump(config.to_hash))
58
+ path
59
+ end
60
+
61
+ def write_testing_config_for_transcripts_dir(transcripts_dir, config=self.config)
62
+ write_config(
63
+ transcripts_dir,
64
+ reconfigure_for_transcripts_dir(reconfigure_for_testing(config), transcripts_dir),
65
+ project_default[:config_filename])
66
+ end
67
+
68
+
69
+ def readymade_project_path
70
+ unless @@readymade_project_path
71
+ transcripts_dir = @@readymade_project_path = Dir.mktmpdir('typingpool_')
72
+ do_later{ FileUtils.remove_entry_secure(transcripts_dir) }
73
+ write_testing_config_for_transcripts_dir(transcripts_dir, reconfigure_for_s3(self.config))
74
+ tp_make(transcripts_dir, config_path(transcripts_dir), 'mp3', true)
75
+ end
76
+ @@readymade_project_path
77
+ end
78
+
79
+ def config_path(dir)
80
+ File.join(dir, project_default[:config_filename])
81
+ end
82
+
83
+ #Intended to be overriden by some classes that mixin this
84
+ #module
85
+ def do_later
86
+ at_exit{ yield }
87
+ end
88
+
89
+ def reconfigure_project(project)
90
+ #rewrite URLs in assignment.csv according to config at config_path
91
+ File.delete(project.local.file('data', 'id.txt'))
92
+ project.local.create_id
93
+ reconfigure_project_csv(project)
94
+ project
95
+ end
96
+
97
+ def reconfigure_project_csv(project)
98
+ assignments = project.local.file('data', 'assignment.csv').as(:csv)
99
+ urls = project.create_remote_names(assignments.map{|assignment| Project.local_basename_from_url(assignment['audio_url']) }).map{|file| project.remote.file_to_url(file) }
100
+ assignments.each! do |assignment|
101
+ assignment['audio_url'] = urls.shift
102
+ assignment['project_id'] = project.local.id
103
+ end
104
+ assignments
105
+ end
106
+
107
+ def path_to_script(script_name)
108
+ File.join(Utility.app_dir, 'bin', script_name)
109
+ end
110
+
111
+
112
+ def call_script(script_name, *args)
113
+ out, err, status = Open3.capture3(path_to_script(script_name), *args)
114
+ if status.success?
115
+ return [out.to_s.chomp, err.to_s.chomp]
116
+ else
117
+ if err
118
+ raise Error::Shell, err.chomp
119
+ else
120
+ raise Error::Shell
121
+ end
122
+ end
123
+ end
124
+
125
+ def tp_make(in_dir, config=config_path(in_dir), audio_subdir='mp3', devtest_mode_skipping_upload=false, *args)
126
+ commands = [
127
+ '--config', config,
128
+ '--chunks', project_default[:chunks],
129
+ *[:title, :subtitle].map{|param| ["--#{param}", project_default[param]] }.flatten,
130
+ *[:voice, :unusual].map{|param| project_default[param].map{|value| ["--#{param}", value] } }.flatten,
131
+ *audio_files(audio_subdir).map{|path| ['--file', path]}.flatten,
132
+ *args
133
+ ]
134
+ commands.push('--testnoupload', '--testkeepmergefile') if devtest_mode_skipping_upload
135
+ call_script('tp-make', *commands)
136
+ end
137
+
138
+ def tp_make_with_vcr(dir, fixture_name, config_path=config_path(dir))
139
+ tp_make(dir, config_path, 'mp3', false, *vcr_args(fixture_name))
140
+ end
141
+
142
+ def vcr_args(fixture_name)
143
+ args = []
144
+ if fixture = cleared_vcr_fixture_path_for(fixture_name)
145
+ args.push('--testfixture', fixture)
146
+ if Typingpool::Test.record
147
+ args.push('--testfixturerecord')
148
+ end
149
+ end #if fixture = ...
150
+ args
151
+ end
152
+
153
+ def tp_finish(dir, config_path=config_path(dir), project_title=project_default[:title], *args)
154
+ tp_finish_inside_sandbox(dir, config_path, project_title, *args)
155
+ tp_finish_outside_sandbox(dir, config_path, project_title, *args)
156
+ end
157
+
158
+
159
+ def tp_finish_inside_sandbox(dir, config_path=config_path(dir), project_title=project_default[:title], *args)
160
+ tp_finish_outside_sandbox(dir, config_path, project_title, '--sandbox', *args)
161
+ end
162
+
163
+ def tp_finish_outside_sandbox(dir, config_path=config_path(dir), project_title=project_default[:title], *args)
164
+ call_script('tp-finish', project_title, '--config', config_path, *args)
165
+ end
166
+
167
+ def audio_files(subdir='mp3')
168
+ dir = File.join(audio_dir, subdir)
169
+ Dir.entries(dir).reject{|entry| entry.match(/^\./) }.map{|entry| File.join(dir, entry)}.select{|path| File.file?(path) }
170
+ end
171
+
172
+ def assign_default
173
+ Hash[
174
+ :template => 'interview/phone',
175
+ :deadline => '5h',
176
+ :lifetime => '10h',
177
+ :approval => '10h',
178
+ :qualify => ['approval_rate >= 90', 'hits_approved > 10'],
179
+ :keyword => ['test', 'mp3', 'typingpooltest']
180
+ ]
181
+ end
182
+
183
+ def tp_assign(dir, config_path=config_path(dir), project_title=project_default[:title], *args)
184
+ call_script(
185
+ 'tp-assign',
186
+ '--sandbox',
187
+ project_title,
188
+ assign_default[:template],
189
+ '--config', config_path,
190
+ *[:deadline, :lifetime, :approval].map{|param| ["--#{param}", assign_default[param]] }.flatten,
191
+ *[:qualify, :keyword].map{|param| assign_default[param].map{|value| ["--#{param}", value] } }.flatten,
192
+ *args)
193
+
194
+ end
195
+
196
+ def tp_assign_with_vcr(dir, fixture_name, config_path=config_path(dir), project_title=project_default[:title])
197
+ project = Project.new(project_default[:title], Typingpool::Config.file(config_path))
198
+ args = [dir, config_path, project_title, *vcr_args(fixture_name)]
199
+ unless (Typingpool::Test.live || Typingpool::Test.record)
200
+ args.push('--testtime', project_time(project).to_i.to_s)
201
+ end
202
+ tp_assign(*args)
203
+ end
204
+
205
+ def copy_tp_assign_fixtures(dir, fixture_prefix, config_path=config_path(dir), project_title=project_default[:title])
206
+ project = Project.new(project_title, Config.file(config_path))
207
+ if Typingpool::Test.record
208
+ project_time(project, Time.now)
209
+ with_fixtures_in_transcripts_dir(dir, "#{fixture_prefix}_", project_title) do |fixture_path, project_path|
210
+ FileUtils.cp(project_path, fixture_path)
211
+ end
212
+ elsif not(Typingpool::Test.live)
213
+ copy_fixtures_to_project_dir("#{fixture_prefix}_", File.join(dir, project_title))
214
+ reconfigure_project_csv(project)
215
+ end
216
+ end
217
+
218
+ def tp_collect_with_fixture(dir, fixture_name, are_recording=false)
219
+ fixture_handle = File.join(vcr_dir, fixture_name)
220
+ args = ['tp-collect', '--sandbox', '--testfixture', fixture_handle, '--config', config_path(dir)]
221
+ if are_recording
222
+ delete_vcr_fixture(fixture_name)
223
+ args.push('--testfixturerecord')
224
+ end
225
+ call_script(*args)
226
+ end
227
+
228
+ def tp_review_with_fixture(transcripts_dir, fixture_name, choices, are_recording=false, project_name=nil)
229
+ fixture_handle = File.join(vcr_dir, fixture_name)
230
+ output = {}
231
+ args = [
232
+ File.join(Utility.app_dir, 'bin', 'tp-review'),
233
+ '--sandbox',
234
+ '--config', config_path(transcripts_dir),
235
+ '--testfixture', fixture_handle
236
+ ]
237
+ args.push(project_name) if project_name
238
+ if are_recording
239
+ delete_vcr_fixture(fixture_name)
240
+ args.push('--testfixturerecord')
241
+ end
242
+
243
+ Open3.popen3(*args) do |stdin, stdout, stderr, wait_thr|
244
+ choices.each do |choice|
245
+ stdin.puts(choice)
246
+ if choice.strip.match(/^r/i)
247
+ stdin.puts("No reason - this is a test")
248
+ end
249
+ end
250
+ output[:out] = stdout.gets(nil)
251
+ output[:err] = stderr.gets(nil)
252
+ [stdin, stdout, stderr].each{|stream| stream.close }
253
+ output[:status] = wait_thr.value
254
+ end
255
+ output
256
+ end
257
+
258
+ def tp_config_with_input(args, input)
259
+ output = {}
260
+ Open3.popen3(path_to_script('tp-config'), *args) do |stdin, stdout, stderr, wait_thr|
261
+ input.each do |sending|
262
+ stdin.puts(sending)
263
+ end
264
+ output[:out] = stdout.gets(nil)
265
+ output[:err] = stderr.gets(nil)
266
+ [stdin, stdout, stderr].each{|stream| stream.close }
267
+ output[:status] = wait_thr.value
268
+ end #Open3.popen3...
269
+ output
270
+ end
271
+
272
+ def project_time(project, time=nil)
273
+ file = project.local.file('data', 'time.txt')
274
+ if time
275
+ file.write(time.to_i)
276
+ else
277
+ time = Time.at(file.read.to_i)
278
+ end
279
+ time
280
+ end
281
+
282
+ def simulate_failed_audio_upload_in(dir, config_path=config_path(dir))
283
+ project = Typingpool::Project.new(project_default[:title], Config.file(config_path))
284
+ csv = project.local.file('data', 'assignment.csv').as(:csv)
285
+ csv.each!{|a| a['audio_uploaded'] = 'maybe'}
286
+ end
287
+
288
+ def make_fixture_transcripts_dir(name)
289
+ dir = File.join(fixtures_dir, name)
290
+ if File.exist? dir
291
+ raise Error::Test, "Fixture transcript dir already exists for #{name} at #{dir}"
292
+ end
293
+ Dir.mkdir(dir)
294
+ dir
295
+ end
296
+
297
+ def with_fixtures_in_project_dir(fixture_prefix, project_path)
298
+ fixtures = Dir.entries(fixtures_dir).select{|entry| entry.include?(fixture_prefix) && entry.index(fixture_prefix) == 0 }.select{|entry| File.file?(File.join(fixtures_dir, entry)) }
299
+ fixtures.map!{|fixture| fixture[fixture_prefix.size .. -1] }
300
+ fixtures.each do |fixture|
301
+ project_fixture_path = File.join(project_path, 'data', fixture)
302
+ source_fixture_path = File.join(fixtures_dir, [fixture_prefix, fixture].join )
303
+ yield(source_fixture_path, project_fixture_path)
304
+ end
305
+ end
306
+
307
+ def copy_fixtures_to_project_dir(fixture_prefix, project_path)
308
+ copies = 0
309
+ with_fixtures_in_project_dir(fixture_prefix, project_path) do |source_fixture_path, project_fixture_path|
310
+ if File.exist? project_fixture_path
311
+ FileUtils.mv(project_fixture_path, File.join(File.dirname(project_fixture_path), "orig_#{File.basename(project_fixture_path)}"))
312
+ end
313
+ FileUtils.cp(source_fixture_path, project_fixture_path)
314
+ copies += 1
315
+ end
316
+ copies > 0 or raise Error, "No fixtures to copy with prefix #{fixture_prefix}"
317
+ copies
318
+ end
319
+
320
+ def restore_project_dir_from_fixtures(fixture_prefix, project_path)
321
+ with_fixtures_in_project_dir(fixture_prefix, project_path) do |source_fixture_path, project_fixture_path|
322
+ FileUtils.rm(project_fixture_path)
323
+ path_to_orig = File.join(File.dirname(project_fixture_path), "orig_#{File.basename(project_fixture_path)}")
324
+ if File.exist?(path_to_orig)
325
+ FileUtils.mv(path_to_orig, project_fixture_path)
326
+ end
327
+ end #with_fixtures_in_transctips_dir
328
+ end
329
+
330
+ def project_transcript_count(project, which_csv)
331
+ project.local.file('data', which_csv).as(:csv).reject{|assignment| assignment['transcript'].to_s.empty?}.size
332
+ end
333
+
334
+ def split_reviews(output)
335
+ output.split(/Transcript for\b/)
336
+ end
337
+
338
+
339
+ end #Script
340
+ end #Test
341
+ end #Utility
342
+ end #Typingpool