Подтвердить что ты не робот

Куда идут тестовые тесты Python?

Если вы пишете библиотеку или приложение, куда идут файлы unit test?

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Запустите тестирование в CLI

python test.py

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

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

module/
    lib/
        __init__.py
        module.py
    tests/
        test_module.py
        test_module_function.py
# test_module.py

import unittest
from lib import module

class TestModule(unittest.TestCase):
    def test_module(self):
        pass

if __name__ == '__main__':
    unittest.main()

Запустите тестирование в CLI

# In top-level /module/ folder
python -m tests.test_module
python -m tests.test_module_function

Используйте unittest discovery

unittest discovery найдет все тесты в папке пакета.

Создайте __init__.py в папке tests/

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

Запустите тестирование в CLI

# In top-level /module/ folder

# -s, --start-directory (default current directory)
# -p, --pattern (default test*.py)

python -m unittest discover

Reference

Структура модульного теста

Ответ 3

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

parent_dir/
  foo.py
  tests/

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

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

Ответ 4

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

Ответ 5

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

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

блок. Это приводит к добавлению документации к файлу как "пример кода" для использования файла python, который вы тестируете.

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

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

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

Ответ 6

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

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

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

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

Я пишу:

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

Если:

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

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

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

Если б:

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

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

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

Ответ 7

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

from .. import foo

чтобы импортировать модуль MyApp.foo.

Ответ 8

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

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

Ответ 9

Из моего опыта разработки тестовых фреймворков в 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, вы можете просто упаковать основные библиотечные модули (только). Это помогает ремонтопригодности, особенно в гибкой среде.

Ответ 10

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

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

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

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

Ответ 11

Как я это делаю...

Структура папки:

project/
    src/
        code.py
    tests/
    setup.py

Setup.py указывает на src/как местоположение, содержащее мои модули проектов, затем я запускаю:

setup.py develop

Что добавляет мой проект в пакеты сайта, указывая на мою рабочую копию. Для запуска моих тестов я использую:

setup.py tests

Использование любого тестового бегуна, который я настроил.

Ответ 12

Я предпочитаю каталог тестов. Это означает, что импорт становится немного сложнее. Для этого у меня есть два решения:

  • Используйте setuptools. Затем вы можете передать test_suite='tests.runalltests.suite' в setup() и просто запустить тесты: python setup.py test
  • Установите PYTHONPATH при выполнении тестов: PYTHONPATH=. python tests/runalltests.py

Вот как этот материал поддерживается кодом в M2Crypto:

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

Ответ 13

Мы используем

app/src/code.py
app/testing/code_test.py 
app/docs/..

В каждый тестовый файл мы вставляем ../src/ в sys.path. Это не самое лучшее решение, но оно работает. Я думаю, было бы здорово, если бы кто-то подошел с чем-то вроде maven в java, который дает вам стандартные соглашения, которые просто работают, независимо от того, над каким проектом вы работаете.

Ответ 14

В С# я обычно отделял тесты от отдельной сборки.

В Python - до сих пор - я имел тенденцию либо писать доктрины, где тест находится в docstring функции, либо помещать их в блок if __name__ == "__main__" в нижней части модуля.

Ответ 15

Если тесты просты, просто поместите их в docstring - большинство тестовых фреймворков для Python смогут использовать это:

>>> import module
>>> module.method('test')
'testresult'

Для других более сложных тестов я поставил их либо в ../tests/test_module.py, либо в tests/test_module.py.

Ответ 16

Когда вы пишете пакет под названием "foo", я буду вводить модульные тесты в отдельный пакет "foo_test". Модули и подпакеты будут иметь то же имя, что и модуль пакета SUT. Например. тесты для модуля foo.x.y находятся в файле foo_test.x.y. Файлы __init__.py каждого тестового пакета затем содержат пакет AllTests, который включает все тестовые пакеты пакета. setuptools обеспечивает удобный способ указания основного тестового пакета, так что после создания "python setup.py" вы можете просто использовать "тест python setup.py" или "тест python setup.py -s foo_test.x.SomeTestSuite" на просто конкретный пакет.

Ответ 17

Я помещаю свои тесты в ту же директорию, что и тестируемый код (CUT); для foo.py тесты будут в foo_ut.py или аналогичном. (Я настраиваю тестовый процесс обнаружения, чтобы найти их.)

Это помещает тесты рядом с кодом в список каталогов, делая очевидным наличие тестов, и делает открытие тестов настолько простым, насколько это возможно, когда они находятся в отдельном файле. (Для редакторов командной строки vim foo* и при использовании графического браузера файловой системы просто щелкните файл CUT, а затем непосредственно прилегающий тестовый файл.)

Как уже отмечали другие, это также облегчает рефакторинг и извлечение кода для использования в других местах, если это когда-либо понадобится.

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

Ответ 18

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

Итак, у меня есть:

app/
 appfile.py
test/
 appfileTest.py

Мне нужно посмотреть, как это происходит, когда я перехожу к более крупным проектам.