2014-02-28 01:58:51 -07:00
|
|
|
#!/usr/bin/env python
|
2017-02-22 11:03:19 +01:00
|
|
|
from __future__ import print_function
|
|
|
|
|
|
2014-02-28 01:58:51 -07:00
|
|
|
import os
|
|
|
|
|
import ast
|
|
|
|
|
import imp
|
|
|
|
|
import glob
|
|
|
|
|
import shutil
|
|
|
|
|
import subprocess
|
2015-01-14 18:17:57 +01:00
|
|
|
import sys
|
2014-02-28 01:58:51 -07:00
|
|
|
import tempfile
|
2017-02-22 11:03:19 +01:00
|
|
|
import json
|
2014-02-28 01:58:51 -07:00
|
|
|
|
|
|
|
|
|
2017-03-19 23:28:00 +01:00
|
|
|
def python_executable_name():
|
|
|
|
|
return 'python{}.{}'.format(sys.version_info.major, sys.version_info.minor)
|
|
|
|
|
|
|
|
|
|
|
2017-02-22 11:03:19 +01:00
|
|
|
def check_assignment(name, test_file):
|
2014-02-28 01:58:51 -07:00
|
|
|
# Returns the exit code of the tests
|
|
|
|
|
workdir = tempfile.mkdtemp(name)
|
2017-02-22 11:03:19 +01:00
|
|
|
example_name = modname_heuristic(test_file)
|
2014-02-28 01:58:51 -07:00
|
|
|
try:
|
|
|
|
|
test_file_out = os.path.join(workdir, os.path.basename(test_file))
|
|
|
|
|
shutil.copyfile(test_file, test_file_out)
|
|
|
|
|
shutil.copyfile(os.path.join(os.path.dirname(test_file), 'example.py'),
|
|
|
|
|
os.path.join(workdir, '{}.py'.format(example_name)))
|
2017-03-19 23:28:00 +01:00
|
|
|
return subprocess.call([python_executable_name(), test_file_out])
|
2014-02-28 01:58:51 -07:00
|
|
|
finally:
|
|
|
|
|
shutil.rmtree(workdir)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def modname_heuristic(test_file):
|
|
|
|
|
with open(test_file) as f:
|
|
|
|
|
tree = ast.parse(f.read(), filename=test_file)
|
|
|
|
|
# return the first nonexistent module that the tests import
|
|
|
|
|
for node in ast.walk(tree):
|
|
|
|
|
for modname in possible_module_names(node):
|
|
|
|
|
if is_module_missing(modname):
|
|
|
|
|
return modname
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def possible_module_names(node):
|
|
|
|
|
if isinstance(node, ast.Import):
|
|
|
|
|
for alias in node.names:
|
|
|
|
|
yield alias.name
|
|
|
|
|
elif isinstance(node, ast.ImportFrom):
|
|
|
|
|
yield node.module
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_module_missing(modname):
|
|
|
|
|
try:
|
|
|
|
|
imp.find_module(modname)
|
|
|
|
|
except ImportError:
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2017-02-22 11:03:19 +01:00
|
|
|
def load_config():
|
|
|
|
|
try:
|
|
|
|
|
with open('./config.json') as json_file:
|
|
|
|
|
data = json.load(json_file)
|
|
|
|
|
except IOError:
|
|
|
|
|
print('FAIL: config.json file not found')
|
|
|
|
|
raise SystemExit(1)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
problems = [entry['slug'] for entry in data['exercises']]
|
|
|
|
|
deprecated_problems = data['deprecated']
|
|
|
|
|
except KeyError:
|
|
|
|
|
print('FAIL: config.json has an incorrect format')
|
|
|
|
|
raise SystemExit(1)
|
|
|
|
|
|
|
|
|
|
return problems, deprecated_problems
|
2014-02-28 01:58:51 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
2017-02-22 11:03:19 +01:00
|
|
|
if len(sys.argv) >= 2:
|
|
|
|
|
# test specific exercises
|
|
|
|
|
exercises = [exercise.strip('/') for exercise in sys.argv[1:]]
|
2014-02-28 01:58:51 -07:00
|
|
|
else:
|
2017-02-22 11:03:19 +01:00
|
|
|
# load exercises from config-file
|
|
|
|
|
exercises, _ = load_config()
|
|
|
|
|
|
|
|
|
|
failures = []
|
|
|
|
|
for exercise in exercises:
|
|
|
|
|
test_file = glob.glob('./exercises/{}/*_test.py'.format(exercise))
|
|
|
|
|
print('# ', exercise)
|
|
|
|
|
if not test_file:
|
|
|
|
|
print('FAIL: File with test cases not found')
|
|
|
|
|
failures.append('{} (FileNotFound)'.format(exercise))
|
2015-01-14 18:17:57 +01:00
|
|
|
else:
|
2017-02-22 11:03:19 +01:00
|
|
|
if check_assignment(exercise, test_file[0]):
|
|
|
|
|
failures.append('{} (TestFailed)'.format(exercise))
|
|
|
|
|
print('')
|
|
|
|
|
|
2017-03-23 13:48:14 +01:00
|
|
|
print('TestEnvironment:', python_executable_name().capitalize(), '\n\n')
|
2017-03-19 23:28:00 +01:00
|
|
|
|
2017-02-22 11:03:19 +01:00
|
|
|
if failures:
|
|
|
|
|
print('FAILURES: ', ', '.join(failures))
|
|
|
|
|
raise SystemExit(1)
|
|
|
|
|
else:
|
|
|
|
|
print('SUCCESS!')
|
|
|
|
|
|
2014-02-28 01:58:51 -07:00
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|