Как правильно тестировать код внутри функции Python - PullRequest
1 голос
/ 10 ноября 2019

Как я могу тестировать переменные / значения, которые находятся внутри функции?

Это довольно простой вопрос о модульном тестировании (я использую pytest), то есть я хочу убедиться, что весь мой код ведет себя какожидается.

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

Здесь я могу только проверить, работает ли возвращаемое значение interp_function, как ожидалось, но никоим образом не протестировать остальную часть кода.

def multidim_interp_function(grid = None, max_error_in_mm=1,
                         max_error_in_deg=1):

    def interp_function(array_of_pts):
        fct_list = create_interp(grid)
        max_error = [max_error_in_mm]*3
        if len(grid) == 6:
            max_error.extend([max_error_in_deg]*3)
    return np.column_stack([error*fct_list[i](array_of_pts) for i,error in enumerate(max_error)])

return interp_function

Ответы [ 2 ]

0 голосов
/ 11 ноября 2019

Вам не нужно тестировать реализацию вашей функции. Если вы написали foo = 'bar' внутри своей функции, то вам не нужно проверять, правильно ли foo было присвоено значение 'bar';Вы можете просто ожидать, что это сработает. С юнит-тестами вы хотите быть на один шаг более абстрактным . Вы хотите проверить, верна ли ваша функция multidim_interp_function правильные результаты при некотором известном вводе. Относитесь к функции так же, как к другим функциям в Python: вы не написали бы модульный тест, чтобы выяснить, как работает max(), вместо этого вы бы написали тест, утверждающий, что max(3, 4) возвращает значение 4.

Мало того, что нецелесообразно проверять "внутренние" функции, это то, что внутренние функции могут изменить . Если вы пишете свои модульные тесты и обнаруживаете, что в вашем коде есть какая-то ошибка, то вы собираетесь изменить свой код. Или вы можете позже вернуться и реорганизовать внутренние компоненты, чтобы сделать их более эффективными, или дедуплицировать некоторый код в вашем модуле, или что-то еще. Вы не хотели бы переписывать свои юнит-тесты каждый раз. Так что не стоит писать свои юнит-тесты, чтобы быть слишком конкретными. Ваши модульные тесты должны протестировать открытый интерфейс функции (аргументы и возвращаемые значения), чтобы вы могли убедиться, что этот интерфейс не изменится (т. Е. Функция продолжает вести себя одинаково), даже если вы переместили некоторыекод вокруг. Если с помощью вашего модульного теста или иным образом вы обнаружите, что внутри функции есть какое-то неправильное поведение, то вы можете вмешаться с помощью отладчика и подтвердить каждое отдельное утверждение один за другим, чтобы найти причину проблемы.

Чтобы прийти к правильному мышлению, попробуйте Разработка на основе тестов , в которой вы сначала пишете свои тесты, по существу решая, как должна вести себя функция , а затемвы реализуете внутреннюю часть функции, все время имея возможность проверить, соответствует ли ваша реализация ожидаемому.

0 голосов
/ 10 ноября 2019

По сути, вы хотите, чтобы ваша функция работала одинаково, поэтому результаты должны быть предсказаны. Вы не хотите проверять внутреннее состояние своей функции, а скорее вывод.


def my_calculus(divise, multiply):
    def inner(value):
        return value * multiply / divide
    return inner

calculus = my_calculus(2, 4)

@pytest.mark.parameterize("function,value,expected", [
    (calculus, 2, 4),
    (calculus, 5, 10)
])
def test_my_calculus(function, value, expected):
     assert function(value) == excepted
...