Куда идут юнит-тесты Python? - PullRequest
       41

Куда идут юнит-тесты Python?

443 голосов
/ 14 сентября 2008

Если вы пишете библиотеку или приложение, куда попадают файлы модульного теста?

Приятно отделить тестовые файлы от основного кода приложения, но неудобно помещать их в подкаталог «tests» внутри корневого каталога приложения, потому что это затрудняет импорт модулей, которые вы будете тестировать ,

Есть ли здесь лучшая практика?

Ответы [ 18 ]

184 голосов
/ 15 сентября 2008

Для файла module.py модульный тест обычно следует называть test_module.py, следуя соглашениям Python по присвоению имен.

Есть несколько общепринятых мест для размещения test_module.py:

  1. В том же каталоге, что и module.py.
  2. В ../tests/test_module.py (на том же уровне, что и каталог кодов).
  3. В tests/test_module.py (один уровень под каталогом кодов).

Я предпочитаю № 1 за простоту поиска тестов и их импорта. Какую бы систему сборки вы не использовали, ее можно легко настроить для запуска файлов, начиная с test_. На самом деле шаблон по умолчанию unittest, используемый для обнаружения теста, равен test*.py.

50 голосов
/ 14 сентября 2008

Обычной практикой является размещение каталога tests в том же родительском каталоге, что и ваш модуль / пакет. Так что если ваш модуль называется foo.py, ваш макет каталога будет выглядеть так:

parent_dir/
  foo.py
  tests/

Конечно, нет единого способа сделать это. Вы также можете создать подкаталог test и импортировать модуль, используя absolute import .

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

50 голосов
/ 30 апреля 2014

только 1 тестовый файл

Если тестовых файлов не так много, поместить их в каталог верхнего уровня неплохо (я думаю, что это питонский (рекомендуемый) способ):

module/
  lib/
    __init__.py
    module.py
  test.py

Множество тестовых файлов

Если имеется много тестовых файлов, поместите его в папку tests:

module/
  lib/
    __init__.py
    module.py
  tests/
    test_module.py
    test_module2.py

но если вы поместите тесты в папку tests, то тест не сможет import ..lib в CLI, поскольку __main__ не может импортировать относительные модули, поэтому вместо этого мы можем использовать nose , или мы можем добавить родительский каталог в путь импорта python, и для этого я создам

env.py

import sys
import os

# append module root directory to sys.path
sys.path.append(
    os.path.dirname(
        os.path.dirname(
            os.path.abspath(__file__)
        )
    )
)

в

module/
  tests/
    test_module.py
    env.py

и import env перед тестовым модулем импорта

test_module.py

import unittest
# append parent directory to import path
import env
# now we can import the lib module
from lib import module

if __name__ == '__main__':
    unittest.main()
32 голосов
/ 02 мая 2009

У нас был тот же вопрос при написании Pythoscope (https://pypi.org/project/pythoscope/),, который генерирует модульные тесты для программ на Python. Мы опрашивали людей при тестировании в списке Python, прежде чем мы выбрали каталог, было много разных мнений. В конце мы решили поместить каталог «tests» в тот же каталог, что и исходный код. В этом каталоге мы генерируем тестовый файл для каждого модуля в родительском каталоге.

27 голосов
/ 19 сентября 2008

Я также склонен помещать свои модульные тесты в сам файл, как замечает Джереми Кантрелл, хотя я склонен не помещать тестовую функцию в основной корпус, а скорее помещать все в

if __name__ == '__main__':
   do tests...

блок. Это завершает добавление документации к файлу в качестве «примера кода» для использования тестируемого файла Python.

Я должен добавить, я склонен писать очень узкие модули / классы. Если ваши модули требуют очень большого количества тестов, вы можете поместить их в другой, но даже тогда я бы добавил:

if __name__ == '__main__':
   import tests.thisModule
   tests.thisModule.runtests

Это позволяет любому, кто читает ваш исходный код, знать, где искать тестовый код.

16 голосов
/ 28 сентября 2016

Время от времени я проверяю тему размещения тестов, и каждый раз большинство рекомендует отдельную структуру папок рядом с кодом библиотеки, но я обнаруживаю, что каждый раз аргументы совпадают и не настолько убедительны , Я заканчиваю тем, что помещаю свои тестовые модули где-то рядом с основными модулями.

Основная причина для этого: рефакторинг .

Когда я перемещаю вещи, я хочу, чтобы тестовые модули перемещались вместе с кодом; легко потерять тесты, если они находятся в отдельном дереве. Давайте будем честными, рано или поздно вы получите совершенно иную структуру папок, например django , flask и многие другие. Что хорошо, если тебе все равно.

Главный вопрос, который вы должны себе задать, это:

Я пишу:

  • а) многоразовая библиотека или
  • б) создание проекта, в котором собраны вместе несколько разделенных модулей?

Если a:

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

Но также легко исключить распространение тестов, когда они смешаны с основными папками; поместите это в setup.py :

find_packages("src", exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) 

Если b:

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

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

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

14 голосов
/ 14 сентября 2008

Я использую каталог tests/, а затем импортирую основные модули приложения, используя относительный импорт. Так что в MyApp / tests / foo.py может быть:

from .. import foo

для импорта модуля MyApp.foo.

12 голосов
/ 14 сентября 2008

Я не верю, что существует признанная "лучшая практика".

Я поместил свои тесты в другой каталог за пределами кода приложения. Затем я добавляю основной каталог приложения в sys.path (позволяя вам импортировать модули из любого места) в моем скрипте бегуна тестов (который также выполняет некоторые другие вещи) перед запуском всех тестов. Таким образом, мне никогда не придется удалять каталог tests из основного кода, когда я его выпускаю, что экономит мое время и усилия, если даже очень мало.

10 голосов
/ 28 марта 2014

Исходя из моего опыта разработки сред тестирования на Python, я бы предложил поместить модульные тесты Python в отдельный каталог. Поддерживать симметричную структуру каталогов. Это было бы полезно для упаковки только основных библиотек, а не для пакетных тестов. Ниже реализована принципиальная схема.

                              <Main Package>
                               /          \
                              /            \
                            lib           tests
                            /                \
             [module1.py, module2.py,  [ut_module1.py, ut_module2.py,
              module3.py  module4.py,   ut_module3.py, ut_module.py]
              __init__.py]

Таким образом, когда вы упаковываете эти библиотеки, используя rpm, вы можете просто упаковать основные библиотечные модули (только). Это помогает ремонтопригодности, особенно в гибкой среде.

9 голосов
/ 09 мая 2016

Я рекомендую вам проверить некоторые основные проекты Python на GitHub и получить некоторые идеи.

Когда ваш код становится больше и вы добавляете больше библиотек, лучше создать тестовую папку в том же каталоге, где у вас есть файл setup.py, и отразить структуру каталогов вашего проекта для каждого типа теста (unittest, интеграция, ...)

Например, если у вас есть структура каталогов, например:

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
setup.py

После добавления тестовой папки у вас будет такая структура каталогов, как:

myPackage/
    myapp/
       moduleA/
          __init__.py
          module_A.py
       moduleB/
          __init__.py
          module_B.py
test/
   unit/
      myapp/
         moduleA/
            module_A_test.py
         moduleB/
            module_B_test.py
   integration/
          myapp/
             moduleA/
                module_A_test.py
             moduleB/
                module_B_test.py
setup.py

Многие правильно написанные пакеты Python используют одну и ту же структуру. Очень хороший пример - пакет Boto. Чек https://github.com/boto/boto

...