Pytest execute specific functions but not main()

  pytest, pytest-mock, python-3.x

I am completing a python coding course from udemy, and have a project with a directory structure like:

├── LICENSE
├── README.md
├── __init__.py
├── requirements.txt
├── src
│   ├── __init__.py
│   └── milage_converter.py
└── tests
    ├── __init__.py
    └── milage_converter_test.py

Within milage_converter_test.py I am running some simple tests like:

from py_exercises.src import milage_converter


def test_base_milage_string_to_float(monkeypatch):
    # monkeypatch the "input" function, so that it returns "10".
    monkeypatch.setattr('builtins.input', lambda _: "10")
    assert milage_converter.get_base_milage(1) == 10.0

But these seem to be invoking the main() function in milage_converter.py.

def get_conversion_direction():
    """Gets the conversion direction input from a user, converts to a float and returns."""
    user_input = input(
        "Would you like to convert from (1) Miles to Kilometers or (2) Kilometers to Miles: ")
    try:
        user_input = float(user_input)
    except ValueError:
        print(
            "Invalid input, options are 1 for Miles to Kilometer or 2 for Kilometers to Miles.")
        get_conversion_direction()
    while user_input in (1, 2):
        user_input = input(
            "You chose an invalid value, please enter a value of 1 or 2: ")
    return user_input


def get_base_milage(unit):
    """Gets the milage input from a user, converts to a float and returns."""
    in_milage = input(f"Please input a value in {unit} to convert: ")
    try:
        in_milage = float(in_milage)
    except ValueError:
        print(
            "Invalid input, please input a valid numerical value to convert.")
        # Adding return avoids the exception being returned:
        # https://stackoverflow.com/a/39059651/2816893
        return get_base_milage(unit)
    return in_milage


def main():
    direction = get_conversion_direction()
    if direction == 1:
        print(
            f"You have selected {direction}, converting from Miles to Kilometers.")
        miles = int(get_base_milage("Miles"))
        print(f"{miles} Miles is equal to {round(miles * 1.609344, 2)}")
    else:
        print(
            f"You have selected {direction}, converting from Kilometers to Miles.")
        kilometers = get_base_milage("Kilometers")
        print(f"{kilometers} Kilometers is equal to {round(kilometers / 1.609344, 2)}")


main()

When I run pytest from the project directory, I get prompted for input as though I had ran the milage_converter.py module like python3.9 milage_converter.py. This is throwing an error that pytest cannot capture stdin.

------------------------------------------------------------------------------------------ Captured stdout -------------------------------------------------------------------------------------------
Would you like to convert from (1) Miles to Kilometers or (2) Kilometers to Miles: 
====================================================================================== short test summary info =======================================================================================
ERROR tests/milage_converter_test.py - OSError: pytest: reading from stdin while output is captured!  Consider using `-s`.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================================================================== 1 error in 0.10s ==========================================================================================

What I expected is that pytest would simply invoke the function specified, get_base_milage() and mock out the input. If I comment out main() on line 51 of milage_converter.py pytest does run as I expect, so I feel like I’m missing something here with pytest/mocking in python.

Source: Python-3x Questions

LEAVE A COMMENT