2014-09-12 3 views
0

В python 3.4, я хочу иметь возможность сделать очень простую таблицу отправки для целей тестирования. Идея состоит в том, чтобы иметь словарь с ключом, являющимся строкой имени проверяемой функции, и элементом данных, являющимся именем тестовой функции. Например:Python: Вычисление имени функции из другого имени функции

myTestList = (
    "myDrawFromTo", 
    "myDrawLineDir" 
) 

myTestDict = { 
    "myDrawFromTo": test_myDrawFromTo, 
    "myDrawLineDir": test_myDrawLineDir 
} 

for myTest in myTestList: 
    result = myTestDict[myTest]() 

Идея состоит в том, что у меня есть список имен функций где-то. В этом примере я вручную создаю словарь, который сопоставляет эти имена именам тестовых функций. Имена тестовых функций - это простое расширение имени функции. Я хотел бы вычислить весь словарь из списка имен функций (здесь это «myTestList»).

Альтернативно, если я могу сделать то же самое без словаря, это тоже будет хорошо. Я попытался просто создать новую строку из записей в myTestList, а затем с помощью local() настроить этот вызов, но не повезло. Идея словаря взята из docs.python.org/3/

+1

бы делать класс из функций работать для вас? –

+0

@crclayton: Это хорошая идея ... но это не помогает решить проблему. – abarnert

ответ

2

В этой проблеме есть две части.

Легкая часть просто предварив 'text_' на каждую строку:

tests = {test: 'test_'+test for test in myTestDict} 

Чем тверже часть на самом деле смотрит на себя функцию по имени. Такую вещь обычно плохая идея, но вы попали в один из случаев (генерации тестов), где это часто имеет смысл. Вы можете сделать это, глядя им в your module's global dictionary, как это:

tests = {test: globals()['test_'+test] for test in myTestList} 

Есть вариации на ту же идею, если тесты жить где-то кроме глобальной области видимости модуля. Например, это может быть хорошей идеей, чтобы сделать их все методы класса, в этом случае вы могли бы сделать:

tester = TestClass() 
tests = {test: getattr(tester, 'test_'+test) for test in myTestList} 

(Хотя более вероятно, что код будет внутри TestClass, так что было бы с помощью self ., а не tester)


Если вы на самом деле не нужен Dict, конечно, вы можете изменить понимание в явном for заявление:

for test in myTestList: 
    globals()['test_'+test]() 

Еще одна вещь: Прежде чем изобретать колесо, рассмотрели ли вы испытательные рамки built into the stdlib или available on PyPI?

+0

@abamert: спасибо, я думаю, что могу сделать эту работу. Я на самом деле преподаю курс базовых курсов CS для студентов, не участвующих в CS (но, безусловно, студенты, у которых нет опыта программирования), и было высказано предположение, что мы используем модуль черепахи. Я хотел бы, чтобы ученики создали простые, но содержательные функции, и я хотел бы подчеркнуть письменные тесты в одно и то же время.Это был бы очень простой способ введения очень простых тестовых идей без необходимости погружаться в кучу других тем. Только около 30% студентов обычно входят в программу CS. –

+1

@PDXMark: Я думаю, что использование рамки модульного тестирования еще более привлекательно, потому что тогда им не нужно узнавать о таких вещах, как 'globals' или' getattr' (или, что еще хуже, 'eval'). Они просто определяют тесты, и они волшебным образом управляются. Хорошая структура также упростит запись тестов, которые они могли бы не знать, как писать (или просто не хотят тратить время на запись), например, проверка того, что функция вызывает исключение, или распечатывает, как фактические результаты отличается от ожидаемых результатов. – abarnert

1

ответ Abarnert, кажется, быть полезным, но ответить на исходный вопрос о том, как назвать все тестовые функции для списка имен функций:

def test_f(): 
    print("testing f...") 

def test_g(): 
    print("testing g...") 

myTestList = ['f', 'g'] 

for funcname in myTestList: 
    eval('test_' + funcname + '()') 
+0

5gon12eder: работает отлично. Это, вероятно, будет проще для моей аудитории. –

+1

Если вам не нужен диктофон для чего-либо, имеет смысл перестраивать петлю над функциями, явно подобными этому ... но использование 'eval' вместо' globals' - плохая идея. – abarnert

Смежные вопросы