Каков хороший способ вызова протестированной функции, предоставляемой библиотекой/пакетом?

Каков хороший способ вызова протестированной функции, предоставляемой библиотекой/пакетом?
Каков хороший способ вызова протестированной функции, предоставляемой библиотекой/пакетом? - davidclode @ Unsplash

Рассмотрим функцию foo, предоставляемую пакетом X в Python. Я хочу протестировать различные функциональные возможности X.foo, а затем использовать X.foo в своем коде. Чтобы убедиться, что я использую X.foo так, как он был протестирован, я думаю инкапсулировать его в функцию, а затем вызвать эту функцию вместо него. Однако я не уверен, что это излишество, и что мне следует просто вызывать X.foo напрямую.

Например, для тестирования X.foo он помещается внутрь функции main, которая, в свою очередь, находится в файле example.py:

# example.py
import X

def main(arg1,arg2,arg3):
    X.foo(arg1,arg2,arg3,...) # X.foo may have other arguments other than arg1,arg2, and arg3

Далее, для юнит-тестирования X.foo в том же каталоге, что и test_example.py, создается новый файл example.py, содержащий различные функции, которые тестируют различные функциональные возможности X.foo:

# test_example.py
from example import main

def test_foo1():
    main(...)
    # some assertions here

def test_foo2():
    main(...)
    # some assertions here

def test_foo3():
    main(...)
    # some assertions here

Затем я запустил бы каждый из test_foo1,test_foo2, и test_foo3, чтобы убедиться, что X.foo работает так, как ожидалось. Однако, чтобы использовать X.foo в моем коде, я не уверен, вызывать ли X.foo напрямую, или вызывать main, как я делал в тестах выше. То есть, в другом файле я могу написать либо

import X
X.foo(...)

или

from example import main
main(...)

Мне кажется, что последний вариант "безопаснее", потому что я ограничиваю использование X.foo тем, как он был протестирован, и не более того.

Инкапсуляция библиотечных функций имеет смысл, когда ваш «собственный» интерфейс main предлагает упрощенный доступ к библиотеке или, по крайней мере, предоставляет более точное или более читаемое имя (при условии, что в реальном коде функции вызываются не просто main и X.foo). Это может быть особенно полезно в ситуациях, когда

  • документация библиотеки имеет низкое качество, или

  • некоторые способы использования библиотеки работают, а другие обнаруживают ошибки (но вы можете жить с этими ошибками, потому что вы нашли некоторые обходные пути), или

  • функции, которые вы собираетесь вызывать, значительно сложнее, чем то, что вам нужно

Об этом нельзя судить только по бессмысленным именам, таким как main или foo. Итак, давайте приведем лучший пример: скажем, это библиотека графического рисования, а X.foo — универсальная функция рисования (ее настоящее имя может быть gfx.Draw) с множеством перегрузок и параметров для рисования точек, линий, кривых, прямоугольников и других фигур. Теперь все, что вам нужно, это функция рисования линий. Итак, вы решили написать функцию DrawLine, которая вызывает gfx.Draw с параметрами для рисования линии между двумя конечными точками.

Чтобы убедиться, что ваша инкапсуляция работает правильно, вы решили написать несколько простых тестов для DrawLine, которые показывают, что она работает, как описано в документации. Теперь должно быть ясно, что ваш реальный код также должен вызывать DrawLine, что будет менее подвержено ошибкам и более выразительно, чем просто вызов gfx.Draw.

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

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


LetsCodeIt, 27 декабря 2022 г., 14:07