Первая строка ввода — имя файла, содержащего программу на Python; в каждой паре последующих — имя файла с входными даннми и имя файла с эталонными выходными данными. Запустить введённую программу, передав ей на стандартный ввод входные данные, получить от неё вывод (стандартный вывод ошибок игнорировать) и сравнить его с эталоном. Вывести общее количество запусков и количество «успешных» запусков, вывод которых совпал с эталоном. Любую другую информацию можно выводить на стандартный вывод ошибок (sys.stderr).
DummyTest.py 001.dat 001.ans 002.dat 002.ans 003.dat 003.ans
Для простоты можно предположить, что все файлы лежат в одном каталоге и не возиться с преобразованием путей UNIX-Windows.
2/3
Стандартный вывод ошибок можон не выбрасывать, а показать пользователю, либо же, наоборот, замешать со стандартным выводом.
Неплохо (хотя и необязательно) задуматься над тем, чтобы убивать «зависшую» задачу (ели, допустим, в течение 15 секунд она не завершилась сама), и считать это ошибкой эффективности.
Спойлер
Туповатый DummyTest.py (работает 6 секунд):
Файл ввода in:
"qwe" 234
Файл шаблона pattern:
234 qwe
Программа запускает подпроцесс с перенаправлением ввода и вывода в файлы, проверяет совпадение вывода шаблону и убивает зависший процесс:
1 #!/usr/bin/python
2 # coding: utf
3
4 import sys
5 import subprocess
6 import difflib
7 import time
8
9 Prog = "DummyTest.py"
10 fIn, fOut, fPatt = "in", "out", "pattern"
11 toWait = 10
12 Stdin = open(fIn)
13 Stdout = open(fOut,"w")
14 Dummy = subprocess.Popen((sys.executable,Prog),stdin=Stdin,stdout=Stdout)
15 for i in xrange(toWait):
16 res = Dummy.poll()
17 if res == None:
18 time.sleep(1)
19 continue
20 elif res != 0:
21 print >> sys.stderr, "Error status:", res
22 sys.exit()
23 else:
24 break
25 else:
26 print "Kill"
27 Dummy.terminate()
28 sys.exit()
29
30 diff = difflib.ndiff(open(fOut).readlines(), open(fPatt).readlines())
31 for l in diff:
32 if not l.startswith(" "):
33 print l.strip()