Pytest - чем заменить input или в чём отличие значения из input?

Изучаю тестирование функций (через pytest).

Есть словарь с которым работает функция.

Ниже сама функция которую пытаюсь протестировать.

def get_doc_owner_name(numbers):
    user_doc_number = numbers # input('Введите номер документа - ') 
    print()
    doc_exist = check_document_existance(user_doc_number)
    if doc_exist:
        for current_document in documents:
            doc_number = current_document['number']
            if doc_number == user_doc_number:
                # return current_document['name']
                return "Code: 200"

Ниже тестирование

numbers = [
  '2207 876234', # Истинное значение. Всё остальное варианты тестирования.
  '22O7 876234',
  ...
  '220787623',
  ''
]

@pytest.mark.parametrize("number", numbers)
def test_get_doc_owner_name(number):
  assert get_doc_owner_name(number) == 'Code: 200'

Если миновать тест и в функцию get_doc_owner_name() значение numbers[0] ввести через input, return срабатывает. Так же return срабатывает если значение задать как аргумент get_doc_owner_name('2207 876234')

При попытке тестирования через @pytest.mark.parametrize("number", numbers) ни одно значение из numbers не проходит

testing.py:19 (test_get_doc_owner_name[22O7 876234])
None != Code: 200

Expected :Code: 200
Actual   :None

В чём отличие значения из input от строки заданной как значение аргумента?


Ответы (1 шт):

Автор решения: insolor

В чём отличие значения из input от строки заданной как значение аргумента?

Примерно во всем.

  • input() - это запрос ввода от пользователя через консоль.

  • Аргумент функции сам по себе ничего не запрашивает, но его наличие подразумевает, что при вызове функции в нее должен быть передан параметр.

    Фактически значение параметра может быть получено откуда угодно - не только с консоли, но и например из файла, из базы, из другой функции.

    Если вы в функцию вшиваете input(), а не используете параметр, то вы ограничиваете возможность получения значения только с консоли. В том числе и при тестировании функции вам придется подменять функцию input(), чтобы она не ждала ввода пользователя, а возвращала тестовые данные. При передаче значений в функцию через параметр тестирование становится более простым.

Чтобы функция у вас работала так же как и раньше, то нужно при ее вызове передать ей результат input-а:

user_doc_number = input('Введите номер документа - ')
print(get_doc_owner_name(user_doc_number))

Дальше, при тестировании если у вас "истинное" значение только одно, то со всеми остальными значениями тест будет валиться, т.к. не будет выполняться условие get_doc_owner_name(number) == 'Code: 200'. Чтобы тест работал, нужно в него еще передать ожидаемый результат (значение, которое должна вернуть тестируемая функция при заданном входном значении):

@pytest.mark.parametrize("number, result", [
  ('2207 876234', 'Code: 200'), # Истинное значение. Всё остальное варианты тестирования.
  ('22O7 876234', None),  # На некорректных значениях функция get_doc_owner_name возвращает None (т.к. нет return после выхода из цикла)
  ...
  ('220787623', None),
  ('', None)
])
def test_get_doc_owner_name(number, result):
  assert get_doc_owner_name(number) == result

- так тест будет проверять, что при значении '2207 876234' функция возвращает 'Code: 200', а при других значениях возвращает None.

→ Ссылка