trail_marker 0.1.1

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.
@@ -0,0 +1,350 @@
1
+ require_relative "response"
2
+
3
+ # TODO: CLEAN UP or DRY testruns and testplans methods since can be combined.
4
+ # Implement other API calls
5
+ #
6
+ class ApiTestRail
7
+ attr_accessor :project_id
8
+ attr_accessor :suite_id
9
+ attr_accessor :run_id
10
+ attr_accessor :test_case_id
11
+ attr_accessor :section_id
12
+
13
+
14
+ def initialize(client)
15
+ @client = client
16
+ @projects = get_projects()
17
+ @project = nil
18
+ @suites = nil
19
+ @suite = nil
20
+ @plans = nil
21
+ @plan = nil
22
+ @runs = nil
23
+ @run = nil
24
+ @test_cases = nil
25
+ @test_case = nil
26
+ @milestones = nil
27
+ @milestone = nil
28
+ @statuses = get_statuses()
29
+
30
+ end
31
+
32
+ # Returns the project ID of the project name passed.
33
+ #
34
+ def get_project_id(project_name)
35
+ if @projects.nil?
36
+ get_projects()
37
+ end
38
+ @project_id = search_array_kv(@projects, 'name', project_name, 'id')
39
+ if @project_id.nil?
40
+ puts "\nProject '#{project_name}' WAS NOT FOUND, select from available projects."
41
+ resp_projects = Response.new(@projects)
42
+ project_name = resp_projects.picker("name")
43
+ @project_id = search_array_kv(@projects, 'name', project_name, 'id')
44
+ end
45
+ return @project_id
46
+ end
47
+
48
+ def get_milestone_id(milestone_name)
49
+ ms_id = nil
50
+ if ! milestone_exists?(milestone_name)
51
+ puts "\nMilestone '#{milestone_name}' WAS NOT FOUND, select from available milestones."
52
+ resp_ms = Response.new(@milestones)
53
+ milestone_name = resp_ms.picker("name")
54
+ #ms_id = search_array_kv(@milestones, 'name', milestone_name, 'id')
55
+ end
56
+ ms_id = search_array_kv(@milestones, 'name', milestone_name, 'id')
57
+ return ms_id
58
+ end
59
+
60
+ def get_test_runplan_id(runplan_name)
61
+ if @runs.nil?
62
+ get_runs(@project_id)
63
+ end
64
+ run_id = search_array_kv(@runs, 'name', runplan_name, 'id')
65
+ if run_id.nil?
66
+ puts "\nTest Run WAS NOT FOUND, select from available."
67
+ resp_runs = Response.new(@runs)
68
+ runplan_name = resp_runs.picker("name")
69
+ run_id = search_array_kv(@runs, 'name', runplan_name, 'id')
70
+ end
71
+ return run_id
72
+ end
73
+
74
+ def get_testplan_id(testplan_name)
75
+ if @plans.nil?
76
+ get_plans(@project_id)
77
+ end
78
+ plan_id = search_array_kv(@plans, 'name', testplan_name, 'id')
79
+ if plan_id.nil?
80
+ puts "\nTestPlan #{testplan_name} WAS NOT FOUND, select from available."
81
+ resp_plans = Response.new(@plans)
82
+ plan_name = resp_plans.picker("name")
83
+ plan_id = search_array_kv(@plans, 'name', plan_name, 'id')
84
+ end
85
+ return plan_id
86
+ end
87
+
88
+ def get_suite_id(proj_id, suite_name)
89
+ suite_id = nil
90
+ if suite_exists?(proj_id, suite_name)
91
+ suite_id = search_array_kv(@suites, 'name', suite_name, 'id')
92
+ end
93
+ return suite_id
94
+ end
95
+
96
+ def get_projects()
97
+ @projects = request_get('get_projects')
98
+ return @projects
99
+ end
100
+
101
+ def get_milestones(proj_id)
102
+ ms_req = "get_milestones/" + proj_id.to_s
103
+ @milestones = request_get(ms_req)
104
+ end
105
+
106
+ def get_runs(proj_id)
107
+ runs_req = "get_runs/" + proj_id.to_s
108
+ @runs = request_get(runs_req)
109
+ end
110
+
111
+ def get_plans(proj_id)
112
+ plans_req = "get_plans/" + proj_id.to_s
113
+ @plans = request_get(plans_req)
114
+ end
115
+
116
+ def get_plan(plan_id)
117
+ plan_req = "get_plan/" + plan_id.to_s
118
+ @plan = request_get(plan_req)
119
+ end
120
+
121
+ def get_suites(proj_id)
122
+ suite_req = "get_suites/" + proj_id.to_s
123
+ @suites = request_get(suite_req)
124
+ end
125
+
126
+ ######################## VERIFY
127
+
128
+ def milestone_exists?(milestone_name)
129
+ it_exists = false
130
+ if @milestones.nil?
131
+ get_milestones(@project_id)
132
+ end
133
+ puts "ALL MILES: #{@milestones}"
134
+ ms_id = search_array_kv(@milestones, 'name', milestone_name, 'id')
135
+ if ! ms_id.nil?
136
+ it_exists = true
137
+ end
138
+ return it_exists
139
+ end
140
+
141
+ def run_exists?(proj_id, run_name)
142
+ it_exists = false
143
+ if @runs.nil?
144
+ @runs = get_runs(proj_id)
145
+ end
146
+ run_id = search_array_kv(@runs, 'name', run_name, 'id')
147
+ if ! run_id.nil?
148
+ it_exists = true
149
+ end
150
+ return it_exists
151
+ end
152
+
153
+ def suite_exists?(proj_id, suite_name)
154
+ it_exists = false
155
+ if @suites.nil?
156
+ @suites = get_suites(proj_id)
157
+ end
158
+ suite_id = search_array_kv(@suites, 'name', suite_name, 'id')
159
+ if ! suite_id.nil?
160
+ it_exists = true
161
+ end
162
+ return it_exists
163
+ end
164
+
165
+ #############
166
+
167
+ # Makes an API call to get all possible results status. Currently has 5
168
+ # passed, blocked, untested, retest, failed.
169
+ # Puts the name and status in @statuses array.
170
+ #
171
+ def get_statuses()
172
+ @statuses = []
173
+ status_req = request_get('get_statuses')
174
+ status_req.each do |status|
175
+ status_hash ={}
176
+ status_hash['id'] = status['id']
177
+ status_hash['name'] = status['name']
178
+ @statuses.push(status_hash)
179
+ end
180
+ return @statuses
181
+ end
182
+
183
+
184
+
185
+ ######################## TEST PLANS #########################
186
+
187
+ # Returns an array of testrun IDs that is inside a testplan.
188
+ #
189
+ def get_testplan_testruns(testplan_id)
190
+ run_ids = []
191
+ plan_resp = get_plan(testplan_id)
192
+ tp_entries = plan_resp['entries']
193
+ tp_entries.each do |entry|
194
+ entry_runs = entry['runs']
195
+ entry_runs.each do |erun|
196
+ run_ids.push(erun['id'])
197
+ end
198
+ end
199
+ return run_ids
200
+ end
201
+
202
+ # Returns array of id for testruns inside a testplan
203
+ def get_testplan_run_ids(testplan_name)
204
+ testplan_id = get_testplan_id(testplan_name)
205
+ get_testplan_testruns(testplan_id)
206
+ end
207
+
208
+ # NOTE - NOT USED RIGHT NOW.
209
+ # Marks a test case inside a testplan. Testplans adds extra API calls
210
+ # because testruns are inside the testplans and are not named.
211
+ # See note below MARK_TESTPLAN
212
+ def markoff_testplan(case_id, testplan_id, pass_status)
213
+ status_id = search_array_kv(@statuses, 'name', 'failed', 'id')
214
+ defect_txt = ""
215
+ if pass_status
216
+ status_id = search_array_kv(@statuses, 'name', 'passed', 'id')
217
+ defect_txt = ""
218
+ end
219
+ equiv_json = {:status_id => status_id, :comment => 'Auto marker.', :defects => defect_txt}
220
+ add_result_req = "add_result_for_case/" + run_id.to_s + "/" + case_id.to_s
221
+ request_post(add_result_req, equiv_json)
222
+ end
223
+
224
+ def get_testid(run_id, case_id)
225
+ puts "SEARCH FOR TESTID: #{run_id} :: #{case_id}"
226
+ tests_req = 'get_tests/' + run_id.to_s
227
+ tests_resp = request_get(tests_req)
228
+ puts "GET_TESTS: #{tests_resp}"
229
+ id_equiv = search_array_kv(tests_resp, 'case_id', case_id.to_i, 'id')
230
+ return id_equiv
231
+ end
232
+
233
+
234
+
235
+ # TODO: Parse XML for failed reason and add to comment(?)
236
+ #
237
+ def markoff_test(case_id, run_id, pass_status, comment_txt)
238
+ status_id = search_array_kv(@statuses, 'name', 'failed', 'id')
239
+ defect_txt = ""
240
+ if pass_status
241
+ status_id = search_array_kv(@statuses, 'name', 'passed', 'id')
242
+ defect_txt = ""
243
+ end
244
+ equiv_json = {:status_id => status_id, :comment => comment_txt, :defects => defect_txt}
245
+ add_result_req = "add_result_for_case/" + run_id.to_s + "/" + case_id.to_s
246
+ request_post(add_result_req, equiv_json)
247
+ end
248
+
249
+ # Makes a post call to create a new milestone
250
+ def create_milestone(proj_name, msname)
251
+ proj_id = get_project_id(proj_name)
252
+ if ! milestone_exists?(msname)
253
+ puts "Create Milestones #{msname} in Project #{proj_name} "
254
+ unix_timestamp = Time.now.to_i
255
+ req_field = {:name => msname, :due_on => unix_timestamp}
256
+ create_milestone_req = "add_milestone/" + proj_id.to_s
257
+ request_post(create_milestone_req, req_field)
258
+ sleep(2)
259
+ get_milestones(proj_id)
260
+ end
261
+ end
262
+
263
+ def delete_milestone(proj_name, msname)
264
+ proj_id = get_project_id(proj_name)
265
+ ms_id = get_milestone_id(msname)
266
+ del_ms_req = "delete_milestone/" + ms_id.to_s
267
+ request_post(del_ms_req, nil)
268
+ exit
269
+ end
270
+
271
+ def create_testrun(proj_name, msname, trname, tsname)
272
+ proj_id = get_project_id(proj_name)
273
+ if ! run_exists?(proj_id, trname)
274
+ if suite_exists?(proj_id, tsname)
275
+ ms_id = nil
276
+ if ! msname.nil? && msname != ""
277
+ ms_id = get_milestone_id(msname)
278
+ end
279
+ puts "MSID: #{msname} #{ms_id}"
280
+ ts_id = get_suite_id(proj_id, tsname)
281
+ req_field = {:name => trname, :suite_id => ts_id, :description => "AutoCreated"}
282
+ if ! ms_id.nil? && ms_id != ""
283
+ req_field[:milestone_id] = ms_id
284
+ end
285
+ add_run_req = "add_run/" + proj_id.to_s
286
+ request_post(add_run_req, req_field)
287
+ puts "CREATING RUN under #{proj_name} #{req_field}"
288
+ sleep(2)
289
+ get_runs(proj_id)
290
+ else
291
+ puts "CANNOT Create New TestRun, (-s) test suite name needed."
292
+ end
293
+ else
294
+ puts "CANNOT Create RUN #{trname}, already exists."
295
+ end
296
+ end
297
+
298
+ private
299
+
300
+ def request_get(api_cmd)
301
+ req = Request.new(@client)
302
+ resp = req.exec_get(api_cmd)
303
+ return resp
304
+ end
305
+
306
+ def request_post(api_cmd, data)
307
+ req = Request.new(@client)
308
+ resp = req.exec_post(api_cmd, data)
309
+ return resp
310
+ end
311
+
312
+ # Searched an array of hashes for a key and value to match
313
+ # and returns a field of that hash.
314
+ # * *Args* :
315
+ # - +rdata+ -> Array of hash data (e.g)
316
+ # - +k+ -> key (e.g. "name")
317
+ # - +v+ -> value to find (e.g. "Test Project")
318
+ # - +key_return+ -> name of another field to return (e.g. "id")
319
+ # * *Returns* :
320
+ # - Value of a field in the hash
321
+ # - nil if none found
322
+ #
323
+ # Example: rdata: [{'id' => 12, 'name' => 'Project-Files, 'owner' => 'Serban', 'run_name' => 'Sprint 2'},
324
+ # {'id' => 22, 'name' => 'Faspex, 'owner' => 'Ajanta', 'run_name' => 'Marathon 10'}]
325
+ #
326
+ # search_array_kv(rdata, "name", "Faspex", "owner")
327
+ # => Calling this find the hash that has 'Faspex' for name,
328
+ # then return the value of 'owner' in that hash 'Ajanta'
329
+ #
330
+ def search_array_kv(rdata, k, v, key_return)
331
+ retval = nil
332
+ fnd = rdata.detect {|unhash| unhash[k] == v}
333
+ if ! fnd.nil?
334
+ retval = fnd[key_return]
335
+ end
336
+ return retval
337
+ end
338
+
339
+
340
+ # NOTE: MARK_TEST_PLAN
341
+ # User Input: Project Name, TestRun Name
342
+ # Project Name > Get project_id
343
+ # Call API get_plans/project_id to get all test plans for the project
344
+ # Get testplan_id of testplan with the given name
345
+ # Call API get_plan/testplan_id to get testruns inside this testplan
346
+ #
347
+
348
+
349
+
350
+ end
@@ -0,0 +1,229 @@
1
+
2
+ # Parses command line argument.
3
+ # Avoids requiring a dependent gem, easy to add any parameters and tags
4
+ # To Add New Parameter:
5
+ # => Add new tag in @valid_parameters
6
+ # => Change HELP message to describe new parameter added
7
+ #
8
+ class Argument
9
+
10
+ USAGE = "Usage: \n testrail_marker -r run_plan_name -p project_name -x /home/path_to/results_xml/dir \n"
11
+ HELP = " -h, Show HELP
12
+ -p *, name of project (e.g. TestRail API Gem) (required parameter)
13
+ -r or -t *, name of test run (-r) or test plan (-t) (required parameter)
14
+ -m, milestone name (can be used when creating a test run)
15
+ -s, test suite name (* required when creating a test run)
16
+ -u, user (e.g. ibarra@apitestrail.com)
17
+ -pw, password or token (recommended)
18
+ -url, URL of TestRail (e.g. https://yourcompany.testrail.io)
19
+ -cf, create a configuration file
20
+ -d, debug mode (set to false to suppresses most messages)
21
+ -x or -f *, path (-x, Directory) or specific file (-f) for results to parse
22
+ -com, comment to put on each test
23
+
24
+
25
+ NOTES: Results must have TestRail test case numbers to match. See README file for
26
+ more details.
27
+ Create options are available by adding \'c\' to some arguments, ex. -cr would create a new test run."
28
+
29
+ REQUIRED = "\nMissing required parameter/s (until config file implemented):
30
+ Ex: testrail_marker -p TestRail API Gem -r Regression Suite -x ./results/path
31
+ -p, name of project (e.g. -p TestRail API Gem)
32
+ -r or -t, name of test run or test plan (e.g. -r Regression Suite)
33
+ -x or -f, path (Directory) or a specific file of results to parse (e.g. -f /home/path/results/rspec_results.xml)\n"
34
+
35
+ # Constructor. Requires passing the parameters from the command line argument.
36
+ #
37
+ def initialize(passed_arguments)
38
+ @arg_passed = passed_arguments
39
+ @valid_parameters = ['-p', '-m', '-r', '-h', '-u', '-pw', '-url', '-d', '-x', '-t', '-s', '-com', '-f']
40
+ @create_parameters = ['-cm', '-cr', '-ct']
41
+ @delete_parameters = ['-dm', '-dr', '-dt']
42
+ @runner_parameters = ['-cf']
43
+ @valid_parameters += @create_parameters
44
+ @valid_parameters += @delete_parameters
45
+ @valid_parameters += @runner_parameters
46
+ @required_parameters = ['-p']
47
+ @requires_atleast_one = ['-r', '-t', '-cr', '-ct']
48
+ @requires_only_one = ['-x', '-f']
49
+
50
+ check_help(passed_arguments)
51
+ initialize_holder()
52
+ parse_args(passed_arguments)
53
+ check_required_parameters(passed_arguments)
54
+ print_arguments
55
+ end
56
+
57
+ def print_arguments()
58
+ puts "\nPassed Arguments:"
59
+ @holder.each do |hold|
60
+ if hold[:value] != ""
61
+ puts " #{hold[:tag]} #{hold[:value]}"
62
+ end
63
+ end
64
+ end
65
+
66
+ def parse_args(arguments)
67
+ par_index = []
68
+ puts "ARG: #{arguments}"
69
+ @valid_parameters.each do |tag|
70
+ arg_index = arguments.index(tag).nil? ? -1 : arguments.index(tag)
71
+ par_index.push(arg_index)
72
+ end
73
+ @valid_parameters.each_with_index do |tag, x|
74
+ tag_index = par_index[x]
75
+ end_index = get_next_highest(tag_index, par_index)
76
+ save_arg_to_holder(arguments, tag_index, end_index)
77
+ end
78
+ end
79
+
80
+ # Returns the argument parameter passed with the specified tag
81
+ #
82
+ def get_arg_value(tag)
83
+ tag_value = nil
84
+ if @valid_parameters.include?(tag)
85
+ tag_hash = @holder.detect{|tag_data| tag_data[:tag] == tag}
86
+ tag_value = tag_hash[:value]
87
+ else
88
+ puts "ERROR: Parameter #{tag} not recognized."
89
+ end
90
+ return tag_value
91
+ end
92
+
93
+ def get_optional_arg(tag_arr)
94
+ tag_value = nil
95
+ tag_arr.each do |tag|
96
+ if @valid_parameters.include?(tag)
97
+ tag_hash = @holder.detect{|tag_data| tag_data[:tag] == tag}
98
+ tag_value = tag_hash[:value]
99
+ else
100
+ puts "ERROR: Parameter #{tag} not recognized."
101
+ end
102
+ if tag_value == ""
103
+ tag_value = nil
104
+ end
105
+ if ! tag_value.nil?
106
+ break
107
+ end
108
+ end
109
+ return tag_value
110
+ end
111
+
112
+ def arg_exists?(tag)
113
+ it_exists = false
114
+ tagv = get_arg_value(tag)
115
+ if ! tagv.nil? && tagv != ""
116
+ it_exists = true
117
+ end
118
+ return it_exists
119
+ end
120
+
121
+ def has_argument?(tag)
122
+ if @arg_passed.include?(tag)
123
+ return true
124
+ end
125
+ return false
126
+ end
127
+
128
+ private
129
+
130
+ # Creates an array to hold values of possible parameter tags.
131
+ #
132
+ def initialize_holder()
133
+ @holder = []
134
+ @valid_parameters.each do |tag|
135
+ param_hash = {:tag => tag, :value => ""}
136
+ @holder.push(param_hash)
137
+ end
138
+ end
139
+
140
+ # Returns the next highest value in the array
141
+ # If num is the highest, then returns 100
142
+ def get_next_highest(num, array_num)
143
+ retval = nil
144
+ if ! num.nil? && num != -1
145
+ arr_size = array_num.size
146
+ sorted_nums = array_num.sort
147
+ num_index = sorted_nums.index(num)
148
+ if num_index == arr_size - 1
149
+ retval = 100
150
+ else
151
+ retval = sorted_nums[num_index + 1]
152
+ end
153
+ end
154
+ return retval
155
+ end
156
+
157
+ def save_arg_to_holder(arguments, startx, endx)
158
+ if startx >= 0
159
+ which_tag = arguments[startx]
160
+ tag_hash = @holder.detect{|tag_data| tag_data[:tag] == which_tag}
161
+ tag_hash[:value] = arguments[startx+1..endx-1].join(" ")
162
+ end
163
+ end
164
+
165
+ def check_help(arguments)
166
+ if arguments.include?('-h')
167
+ puts "#{USAGE}"
168
+ puts "#{HELP} \n\n"
169
+ exit(0)
170
+ end
171
+ end
172
+
173
+ private
174
+
175
+ # Verifies that all required parameters are passed in the argument.
176
+ # Two types of required. First, parameters that are absolutely needed.
177
+ # Second, parameters that are not all required but at least one must
178
+ # be passed.
179
+ # Exits the script if parameter requirements are not satisfied.
180
+ #
181
+ def check_required_parameters(arguments)
182
+ params_good = true
183
+
184
+ @runner_parameters.each do |run_par|
185
+ if arguments.include?(run_par)
186
+ return true
187
+ end
188
+ end
189
+ @required_parameters.each do |req_par|
190
+ passed_reqpar = get_arg_value(req_par)
191
+ if passed_reqpar.nil? || passed_reqpar == ''
192
+ params_good = false
193
+ end
194
+ end
195
+
196
+ has_atleast_one = true
197
+ if @requires_atleast_one.size > 0
198
+ has_atleast_one = false
199
+ @requires_atleast_one.each do |least_one|
200
+ luno = get_arg_value(least_one)
201
+ if ! luno.nil? && luno != ""
202
+ has_atleast_one = true
203
+ end
204
+ end
205
+ end
206
+
207
+ has_only_one = true
208
+ if @requires_only_one.size > 0
209
+ has_only_one = false
210
+ num_detected = 0
211
+ @requires_only_one.each do |only_one|
212
+ if arg_exists?(only_one)
213
+ num_detected += 1
214
+ end
215
+ end
216
+ if num_detected == 1
217
+ has_only_one = true
218
+ end
219
+ end
220
+
221
+ if !params_good || ! has_atleast_one || ! has_only_one
222
+ puts "#{REQUIRED}"
223
+ exit(1)
224
+ end
225
+
226
+ end
227
+
228
+
229
+ end
@@ -0,0 +1,107 @@
1
+ require 'yaml'
2
+
3
+ # History:
4
+ # 2/19/2018 Created ibarra.alfonso@gmail.com
5
+ #
6
+ #
7
+ class ConfigFile
8
+
9
+ attr_accessor :username, :token, :testrail_url, :filename, :default_comment
10
+
11
+ def initialize(cfile)
12
+ @filename = cfile
13
+ read_config_file
14
+ end
15
+
16
+ def prompt_user(user_msg, default_val)
17
+ retval = default_val
18
+ newval = ''
19
+ atmps = 0
20
+ while newval.strip == '' && atmps < 3
21
+ atmps += 1
22
+ print "#{user_msg}"
23
+ newval = STDIN.gets
24
+ retval = newval.strip == '' ? default_val : newval.strip
25
+ newval = retval
26
+ end
27
+ if atmps >= 3
28
+ puts "\nERROR: Value cannot be empty... exiting."
29
+ exit(1)
30
+ end
31
+ return retval
32
+ end
33
+
34
+ def user_continue?(user_msg, default_val=false)
35
+ retval = default_val
36
+ reply = prompt_user(user_msg, 'N')
37
+ if reply.upcase == "Y"
38
+ retval = true
39
+ end
40
+ return retval
41
+ end
42
+
43
+ def read_config_file
44
+ if File.exist?(@filename)
45
+ @trail_info = YAML.load_file(@filename)
46
+ @username = @trail_info["username"]
47
+ @token = @trail_info["token"]
48
+ @testrail_url = @trail_info["testrail_url"]
49
+ @default_comment = @trail_info['default_comment']
50
+ else
51
+ @trail_info = Hash.new
52
+ @username = ''
53
+ @token = ''
54
+ @testrail_url = ''
55
+ @default_comment = 'Marked by Automation'
56
+ end
57
+ end
58
+
59
+ def check_create_configfile
60
+ if ! File.exist?(@filename)
61
+ puts "\nWARNING: Configuration File does not exist."
62
+ if user_continue?("Create a new config file (Y/N)? : ", 'N')
63
+ create_configfile
64
+ end
65
+ end
66
+ end
67
+
68
+ def create_configfile
69
+ @username = prompt_user("Enter testrail email (#{@username}): ", @username)
70
+ @token = prompt_user("Enter testrail token (#{@token}): ", @token)
71
+ @testrail_url = prompt_user("TestRail URL (#{@testrail_url}): ", @testrail_url)
72
+ @default_comment = prompt_user("Test comment (Default - Marked by Automation): ", "Marked by Automation")
73
+ @trail_info = Hash.new
74
+ @trail_info["username"] = @username
75
+ @trail_info["token"] = @token
76
+ @trail_info["testrail_url"] = @testrail_url
77
+ @trail_info["default_comment"] = @default_comment
78
+ save
79
+ # Comment out until overwrite is finished.
80
+ #if user_continue?("Do you want to save the testrail project info (Y/N)?")
81
+ # config_project
82
+ # thash["project_name"] = @project_name
83
+ # thash["testrun"] = @testrun
84
+ # thash["testplan"] = @testplan
85
+ #end
86
+ end
87
+
88
+ def config_project
89
+ @project_name = prompt_user("Enter testrail project name: ")
90
+ @testrun = prompt_user("Enter name of test run: ", "NA")
91
+ @testplan = prompt_user("Enter name of test plan: ", "NA")
92
+ end
93
+
94
+ def update(varname, varvalue)
95
+ if defined? @trail_info
96
+ @trail_info[varname] = varvalue
97
+ end
98
+ end
99
+
100
+ def save
101
+ File.open(@filename, 'w') { |f|
102
+ f.write @trail_info.to_yaml
103
+ puts "Successfully saved config file: #{@filename}"
104
+ }
105
+ end
106
+
107
+ end