| 141 |
Kevin |
1 |
#!/usr/bin/python
|
|
|
2 |
#
|
|
|
3 |
#Script: stdriver.py
|
|
|
4 |
#Author: Patrick Boyd
|
|
|
5 |
#
|
|
|
6 |
#Purpose: Run point-valued python test scripts and generate a grade sheet
|
|
|
7 |
#
|
|
|
8 |
#Description:
|
|
|
9 |
#Runs a set of python tests as determined by the contents of the input file.
|
|
|
10 |
#The contents of the .txt file should appear as follows:
|
|
|
11 |
# = test group 1
|
|
|
12 |
# 5 test_worth_5.py
|
|
|
13 |
# 10 test_worth 10.py
|
|
|
14 |
# 15 test_worth_15.py
|
|
|
15 |
# = test group 2
|
|
|
16 |
# 20 test_worth 20.py
|
|
|
17 |
# 25 test_worth 25.py
|
|
|
18 |
# ...
|
|
|
19 |
#
|
|
|
20 |
#These tests will then be spawned into their own subprocesses and ran,
|
|
|
21 |
#and their results will be recorded. If the verbose option is enabled,
|
|
|
22 |
#error information will be displayed.
|
|
|
23 |
#
|
|
|
24 |
#
|
|
|
25 |
#
|
|
|
26 |
|
|
|
27 |
import getopt, os, sys, subprocess, re
|
|
|
28 |
|
|
|
29 |
# add directory in which script is located to python path
|
|
|
30 |
script_dir = "/".join(__file__.split("/")[:-1])
|
|
|
31 |
if script_dir == "":
|
|
|
32 |
script_dir = "."
|
|
|
33 |
if script_dir not in sys.path:
|
|
|
34 |
sys.path.append(script_dir)
|
|
|
35 |
|
|
|
36 |
verbose = False
|
|
|
37 |
output_spec_file = "./eshoutput.py"
|
|
|
38 |
plugin_directory = ""
|
|
|
39 |
test_base = "./eshtests/"
|
|
|
40 |
milestone_test_file = "milestone.tst"
|
|
|
41 |
basic_test_file = "basic.tst"
|
|
|
42 |
reduced_test_file = "reduced.tst"
|
|
|
43 |
advanced_test_file = "advanced.tst"
|
|
|
44 |
testfilter = None
|
|
|
45 |
|
|
|
46 |
def usage():
|
|
|
47 |
print """
|
|
|
48 |
Usage: python stdriver.py [options] [tests1.tst tests2.tst] ...
|
|
|
49 |
-m Run milestone tests
|
|
|
50 |
-p plugin_dir Run plugins from the supplied directory
|
|
|
51 |
-b Run basic tests
|
|
|
52 |
-v Verbose
|
|
|
53 |
-h Show help
|
|
|
54 |
-o outputspec Run using this output spec file
|
|
|
55 |
-t testname Run only tests whose names contains 'testname'
|
|
|
56 |
-l List available tests (not implemented)
|
|
|
57 |
-a Run advanced tests
|
|
|
58 |
"""
|
|
|
59 |
|
|
|
60 |
try:
|
|
|
61 |
opts, args = getopt.getopt(sys.argv[1:], "ahvmrbo:p:t:", \
|
|
|
62 |
["help", "outputspec=", "test="])
|
|
|
63 |
except getopt.GetoptError, err:
|
|
|
64 |
# print help information and exit:
|
|
|
65 |
print str(err) # will print something like "option -a not recognized"
|
|
|
66 |
usage()
|
|
|
67 |
sys.exit(2)
|
|
|
68 |
|
|
|
69 |
for o, a in opts:
|
|
|
70 |
if o == "-v":
|
|
|
71 |
verbose = True
|
|
|
72 |
elif o in ("-h", "--help"):
|
|
|
73 |
usage()
|
|
|
74 |
sys.exit()
|
|
|
75 |
elif o in ("-t", "--test"):
|
|
|
76 |
testfilter = a
|
|
|
77 |
elif o in ("-m"):
|
|
|
78 |
args = [test_base + milestone_test_file]
|
|
|
79 |
elif o in ("-b"):
|
|
|
80 |
args = [test_base + basic_test_file]
|
|
|
81 |
elif o in ("-a"):
|
|
|
82 |
args = [test_base + advanced_test_file]
|
|
|
83 |
elif o in ("-r"):
|
|
|
84 |
#args = [test_base + reduced_test_file]
|
|
|
85 |
print "-r is no longer allowed"
|
|
|
86 |
usage()
|
|
|
87 |
sys.exit()
|
|
|
88 |
elif o in ("-p"):
|
|
|
89 |
plugin_directory = a
|
|
|
90 |
elif o in ("-o"):
|
|
|
91 |
output_spec_file = a
|
|
|
92 |
else:
|
|
|
93 |
assert False, "unhandled option"
|
|
|
94 |
|
|
|
95 |
if plugin_directory != "" and not os.access(plugin_directory, os.R_OK):
|
|
|
96 |
print "Directory ", plugin_directory, " is not readable"
|
|
|
97 |
print "You must create this plugin directory if you wish to test plugins"
|
|
|
98 |
sys.exit(1)
|
|
|
99 |
else:
|
|
|
100 |
plugin_directory = " -p " + plugin_directory
|
|
|
101 |
|
|
|
102 |
if not os.access(output_spec_file, os.R_OK):
|
|
|
103 |
print "File ", output_spec_file, " is not readable"
|
|
|
104 |
print "You must create this file and adapt it to match the output of your shell"
|
|
|
105 |
sys.exit(1)
|
|
|
106 |
|
|
|
107 |
full_testlist = []
|
|
|
108 |
if len(args) == 0:
|
|
|
109 |
usage()
|
|
|
110 |
sys.exit(1)
|
|
|
111 |
|
|
|
112 |
for testlist_filename in args:
|
|
|
113 |
try:
|
|
|
114 |
testlist_file = open(testlist_filename, 'r')
|
|
|
115 |
test_dir = os.path.dirname(testlist_filename)
|
|
|
116 |
if test_dir == "":
|
|
|
117 |
test_dir = './'
|
|
|
118 |
else:
|
|
|
119 |
test_dir = test_dir + '/'
|
|
|
120 |
except:
|
|
|
121 |
print 'Error: Tests list file: ''%s'' could not be opened.'% testlist_filename
|
|
|
122 |
sys.exit(-1)
|
|
|
123 |
|
|
|
124 |
#File input, read in the test filenames
|
|
|
125 |
#test information is placed into tuples that are placed onto a 2d list
|
|
|
126 |
for line in testlist_file:
|
|
|
127 |
|
|
|
128 |
grps = re.match("^= (.+)", line)
|
|
|
129 |
if grps:
|
|
|
130 |
testset = { 'name' : grps.group(1),
|
|
|
131 |
'tests' : [ ],
|
|
|
132 |
'dir' : test_dir }
|
|
|
133 |
full_testlist.append(testset)
|
|
|
134 |
else:
|
|
|
135 |
grps = re.match("(\d+) (.+)", line)
|
|
|
136 |
if grps:
|
|
|
137 |
points, testname = int(grps.group(1)), grps.group(2)
|
|
|
138 |
if not testfilter or testname.find(testfilter) != -1:
|
|
|
139 |
testset['tests'].append((points, testname))
|
|
|
140 |
|
|
|
141 |
testlist_file.close()
|
|
|
142 |
|
|
|
143 |
# print full_testlist
|
|
|
144 |
|
|
|
145 |
process_list = []
|
|
|
146 |
|
|
|
147 |
#Run through each test set in the list
|
|
|
148 |
for testset in full_testlist:
|
|
|
149 |
print testset['name']
|
|
|
150 |
print '-------------------------'
|
|
|
151 |
|
|
|
152 |
#Run through each test in the set
|
|
|
153 |
testresults = [ ]
|
|
|
154 |
for (points, testname) in testset['tests']:
|
|
|
155 |
|
|
|
156 |
print str(points) + '\t' + testname + ':',
|
|
|
157 |
sys.stdout.flush()
|
|
|
158 |
|
|
|
159 |
# run test
|
|
|
160 |
child_process = subprocess.Popen(["python", testset['dir'] + testname, \
|
|
|
161 |
output_spec_file, plugin_directory],\
|
|
|
162 |
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
|
|
163 |
test_passed = child_process.wait() == 0
|
|
|
164 |
|
|
|
165 |
# build result list
|
|
|
166 |
testresults.append((points, testname, child_process, test_passed))
|
|
|
167 |
|
|
|
168 |
#if: test passed
|
|
|
169 |
if test_passed:
|
|
|
170 |
print ' PASS'
|
|
|
171 |
else:
|
|
|
172 |
print ' FAIL'
|
|
|
173 |
print ""
|
|
|
174 |
testset['tests'] = testresults
|
|
|
175 |
|
|
|
176 |
|
|
|
177 |
#Grade sheet printing. It prints each individual test and the points awarded
|
|
|
178 |
#from that test, the points awarded from each set of tests, and the total
|
|
|
179 |
#points awarded over the entire test.
|
|
|
180 |
|
|
|
181 |
#Run through each set of tests in the list
|
|
|
182 |
testset_points = 0
|
|
|
183 |
testset_points_earned = 0
|
|
|
184 |
|
|
|
185 |
#Run through each test in the set
|
|
|
186 |
for (points, testname, child_process, test_passed) in testset['tests']:
|
|
|
187 |
testset_points += points
|
|
|
188 |
points_earned = points
|
|
|
189 |
if not test_passed:
|
|
|
190 |
points_earned = 0
|
|
|
191 |
|
|
|
192 |
print '\t%s\t%d/%d' % (testname, points_earned, points)
|
|
|
193 |
testset_points_earned += points_earned
|
|
|
194 |
|
|
|
195 |
print '-------------------------'
|
|
|
196 |
|
|
|
197 |
print testset['name'] + '\t' + str(testset_points_earned) + '/' + \
|
|
|
198 |
str(testset_points)
|
|
|
199 |
|
|
|
200 |
|
|
|
201 |
|
|
|
202 |
#Verbose printing. If the verbose option was enabled, print the error
|
|
|
203 |
#information from the tests that failed.
|
|
|
204 |
if verbose:
|
|
|
205 |
print '\nError Output'
|
|
|
206 |
print '-------------------------'
|
|
|
207 |
for testset in full_testlist:
|
|
|
208 |
for (points, testname, child_process, test_passed) in testset['tests']:
|
|
|
209 |
if not test_passed:
|
|
|
210 |
print testname + ':'
|
|
|
211 |
(stdout, stderr) = child_process.communicate()
|
|
|
212 |
print stdout, stderr
|
|
|
213 |
|