#python #automated-tests
Вопрос:
Фон
У меня есть задача запустить множество методов python против наборов тестов в пакетном режиме. Я написал программу для динамического определения методов и соответствующих тестовых примеров (с использованием exec(str)
) и автоматического запуска тестовых примеров.
Проблема
Правильный код не должен содержать input()
инструкцию, которая требует ввода пользователем. Однако существует неправильный код, который может содержать input()
инструкции, которые блокируют выполнение и ожидание ввода пользователем. Как я могу определить, вызывается ли an input()
и моя программа зависает там? Существуют ли подходы для сбоя такого вызова метода и продолжения программы?
Краткие сведения
- Как я могу определить, вызывается ли an
input()
и моя программа зависает там? - Существуют ли подходы для сбоя такого вызова метода и продолжения программы?
Ответ №1:
Как я могу определить, вызывается ли an input()
и моя программа зависает там?
Предположим, у вас есть два метода — один правильный и один неправильный:
class Foo:
def correct(self, x):
return x
def incorrect(self):
# You shouldn't use input!
a = int(input())
return 42 a
Вы можете использовать unittest.mock
библиотеку. Создайте функцию, которая определяет, использовался ли какой-либо вызов input
:
import unittest.mock
def check(f, *args, **kwargs):
# Store the real `input` function in a variable
real_input = __builtins__.input
# Use `unittest.mock` to catch any calls to this variable
__builtins__.input = unittest.mock.MagicMock()
# Call the desired function with the provided arguments
f(*args, **kwargs)
# Check if the fake `input` function was called
result = __builtins__.input.called
# Restore the value of the `input` function
__builtins__.input = real_input
# Return if the fake `input` function was called
return result
Вы можете использовать его следующим образом:
foo = Foo()
print(check(foo.correct, 42)) # Outputs False
print(check(foo.incorrect)) # Outputs True
Существуют ли подходы для сбоя такого вызова метода и продолжения программы?
Замените check
функцию на
def check(f, *args, **kwargs):
# Use a custom error so that, if the original function throws an
# error, it wouldn't be catch mistakenly inside the `check` function
class _MyCustomError(BaseException):
pass
real_input = __builtins__.input
__builtins__.input = unittest.mock.Mock(side_effect=_MyCustomError())
try:
f(*args, **kwargs)
except _MyCustomError:
return True
else:
return False
finally:
__builtins__.input = real_input
С этой модификацией использование будет:
foo = Foo()
print(check(foo.correct, 42)) # Outputs False
print(check(foo.incorrect)) # Outputs True and fail the function with _MyCustomError