-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyrobot.py
More file actions
281 lines (228 loc) · 9.96 KB
/
pyrobot.py
File metadata and controls
281 lines (228 loc) · 9.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# -*- coding: utf-8 -*-
#
# imports
from robot.running import TestSuite
from robot import utils
from robot.conf import settings
import os, glob
import subprocess
import time
from datetime import datetime
import sys
import getopt
import fileinput
import random
import PyrobotConfig as config
import string
import random
import shutil
from BrowserData import *
from SauceRest import *
class Jybot():
""" Helper class to interact with RobotFrameworks pybot script to execute tests / test suites.
"""
name = ""
tests = []
suite = ""
args = []
output = ""
process = -1
running = False
jyLogLoc = ""
def __init__(self, name):
""" Constructor, creates the object and assigns the given 'name'.
"""
self.name = name
def start(self, args=[]):
""" Starts the pybot script from RobotFramework executing the given 'suite'.
'args' (optional) is a list of additional parameters passed to pybot
"""
self.suite = payload
self.output_file = '%s_Output.xml' % self.name
self.log_file = '%s_Log.html' % self.name
self.report_file = '%s_Report.html' % self.name
self.jyLogLoc = os.path.join(workspace_home, ("%s_Stdout.txt" % self.name))
jyLog = open(self.jyLogLoc, "w")
jybotCommand = "pybot --name %s --outputdir %s --output %s --log %s --report %s %s" % (self.name, workspace_home, self.output_file, self.log_file, self.report_file, payload)
print "Executing : %s ..." % jybotCommand
self.running = True
#self.process = subprocess.Popen(["pybot", "-o", "%s" % os.path.join(log_folder, self.output_file), "%s" % self.suite], cwd=client_cwd, stdout=jyLog, stderr=jyLog)
self.process = subprocess.Popen(jybotCommand.split(' '), cwd=client_cwd, stdout=jyLog, stderr=jyLog)
def isRunning(self):
""" Polls the pybot subprocess to check if it's running. Will return true if the process is running.
Returns false if the process hasn't been started or has finished already.
"""
if not self.running:
return False
elif self.process.poll() == 0 or self.process.returncode >= 0:
return False
else:
return True
def stop(self):
""" Kills the pybot subprocess.
"""
os.system("taskkill /T /F /PID %s" % self.process.pid)
self.running = False
# Methods #####################################################################################################
def startJybot(name, args=[]):
""" Creates a pybot object, starts it and returns the object
'name' is the name for the pybot (will be used for log outputs)
'tests' is a list of tests to be executed by the pybot
'suite' is the filename of the test suite containing the 'tests'
'args' (optional) is a list of additional parameters passed to pybot
"""
jybot = Jybot(name)
jybot.start(args)
return jybot
def generateReportAndLog(xmlFiles, reportFile, logFile):
""" Calls RobotFrameworks rebot tool to generate Report and Log files from output.xml files
'xmlFiles' is a list of output.xml files from jybot / pybot
'reportFile' is the path+name of the report.html file to be written
'logFile' is the path+name of the log.html file to be written
the global variable 'payload' will be used a report title
"""
rebotCommand = "rebot --log %s --report %s --reporttitle \"%s\" --name ' ' %s/*.xml" % (logFile, reportFile, suite_name, workspace_home)
print 'rebotCommand: ' + rebotCommand
rc = os.system(rebotCommand)
return rc
# def parseArgs(argv):
# """ Parses command line arguments like the testsuite name and additonal parameters
# Expects the command line args without the python class as parameter argv (sys.argv[1:])
# Fails and aborts script if args don't match the expected format
# """
# global payload, client_cwd, base_dir, log_folder, testsToRun, suiteToRun, testDirectory
def getDynArgs(index):
""" Reads the DYN_ARGS variable from the config file and parses it into a list of argument strings
like --variable name:"value".
This list can be passed to the Pybot start() method as args[] list.
"""
arglist = []
for row in config.DYN_ARGS:
valueIndex = index
if len(row) < 2:
print "Error reading DYN_ARGS: Row is invalid: %s. Row will be skipped!" % row
else:
varName = row[0]
values = []
i = 1
while i < len(row):
values.append(row[i])
i = i+1
if valueIndex >= len(values):
valueIndex = (len(values)-1) % valueIndex
varValue = values[valueIndex]
arglist.append("--variable %s:\"%s\"" % (varName, varValue))
return arglist
def usage():
""" Prints usage information for Parabot """
print ""
print "Usage: python parabot.py [options] <testsuite.tsv>"
print ""
print "<testsuite.tsv> can be absolute or relative path + filename of a testsuite."
print "The containing folder will be used as working directory"
print ""
print "Options:"
print "-h\t--help\t\tThis screen"
print "-i\t--include\tInclude a tag"
print "-e\t--exclude\tExclude a tag"
print "-f\t--forceserial\tForces serial test execution"
print "-b\t--basedir\tSet parabots base dir"
print ""
# helper classes ##############################################################################################
# MAIN SCRIPT #################################################################################################
print "";
print "-- PYROSUITE --";
print "";
# save current time to calculate execution time at the end of the script
startTime = datetime.now()
# global vars
payload = "No suite defined yet" # specified via args
argumentFiles = []
listeners = []
jybots = []
client_cwd = "No cwd defined" # specified via testsuite from args
base_dir = "./"
# reading variables from ParabotConfig
time_between_test_start_up = config.time_between_test_start_up
log_folder = config.LOG_DIR
# Example of multiple browsers (TeamCity)
#os.environ['SAUCE_ONDEMAND_BROWSERS'] = '[{"platform":"LINUX","os":"Linux","browser":"chrome","url":"sauce-ondemand:?os=Linux&browser=chrome&browser-version=32&username=talliskane&access-key=6c3ed64b-e065-4df4-b921-75336e2cb9cf","browser-version":"32"},{"platform":"LINUX","os":"Linux","browser":"android","url":"sauce-ondemand:?os=Linux&browser=android&browser-version=4.0&username=talliskane&access-key=6c3ed64b-e065-4df4-b921-75336e2cb9cf","browser-version":"4.0"}]'
# Example of Single Browser (TeamCity)
#os.environ['SELENIUM_DRIVER'] = "sauce-ondemand:?username=talliskane&access-key=6c3ed64b-e065-4df4-b921-75336e2cb9cf&os=Windows 2012 R2&browser=internet explorer&browser-version=11&max-duration=null&idle-timeout=null"
# if not os.environ.get('SAUCE_ONDEMAND_BROWSERS') and not os.environ.get('SELENIUM_DRIVER'):
# print 'WARNING: Pyrobot was unable to intersect the sauce environment variables'
# print ' -> SAUCE_ONDEMAND_BROWSERS SELENIUM_DRIVER'
# print ' Entering test mode by overriding SELENIUM_DRIVER with a fake value'
# print ''
# os.environ['SELENIUM_DRIVER'] = "sauce-ondemand:?username=talliskane&access-key=6c3ed64b-e065-4df4-b921-75336e2cb9cf&os=Windows 2012 R2&browser=internet explorer&browser-version=11&max-duration=null&idle-timeout=null"
# parsing command line arguments
#parseArgs(sys.argv[1:])
# if len(arglist)<1:
# usage()
# sys.exit(2)
os.environ['DISPLAY'] = config.DEFAULT_BROWSER_DISPLAY
arglist = sys.argv[1:]
if os.environ.get('PAYLOAD'):
payload = os.environ['PAYLOAD']
else:
try:
payload = arglist[len(arglist)-1]
except:
usage()
sys.exit(2)
suite_name = os.path.basename(os.path.normpath(payload))
client_cwd = os.path.realpath(base_dir)
uid = os.environ.get("WORKSPACE_UID", ''.join(random.choice(string.ascii_uppercase) for i in range(12)))
workspace_home = os.path.join("/mnt/wt/pyrobot/workspace/", uid)
os.mkdir(workspace_home, 0755)
payload = os.path.join(os.path.realpath(base_dir), payload)
if not os.path.exists(payload):
print "FATAL - Pyro must be given a payload that exists: %s\n" % payload
sys.exit(2)
#####
#### log_folder = os.path.abspath(log_folder)
log_folder = payload
print "Base dir: %s" % base_dir
print "Client dir: %s" % client_cwd
print "Log dir: %s" % log_folder
print "Payload: %s" % payload
print "Workspace Home: %s" % workspace_home
print "Display: %s" % os.environ['DISPLAY']
print ""
# Browser information
construct = BrowserData(config)
print "Starting suite: \"%s\" ...\n" % suite_name
for x in range(0, construct.getUrlCount()):
test_name = ("%s_%s_%s" % (construct.getBrowser(x), construct.getOS(x), construct.getBrowserVersion(x))).replace(' ', '_')
construct.setPyrobotEnvForTest(x, config, test_name)
print ""
print "Starting browser tests for %s ..." % test_name
jybot = startJybot(test_name, getDynArgs(0))
while jybot.isRunning():
time.sleep(time_between_test_start_up)
jybots.append(jybot)
with open(jybot.jyLogLoc, 'r') as fin:
print fin.read()
print "Serial tests finished"
print ""
# merging outputs to one report and log
print "Generating report and log"
report = os.path.join(workspace_home, "%s_Report.html" % suite_name)
log = os.path.join(workspace_home, "%s_Log.html" % suite_name)
print 'final log and report'
print report
print log
outputXmls = []
for jybot in jybots:
outputXmls.append(os.path.join(log_folder, jybot.output))
reportRC = generateReportAndLog(outputXmls, report, log)
# delete XML output files after generating the report / log (if report generation
# returned zero)
#if reportRC == 0:
# for outXML in outputXmls:
# os.remove(outXML)
# calculating test execution time
endTime = datetime.now()
executionTime = endTime - startTime
print ""
print "Execution time: %s" % executionTime