Як поширити тести django на декілька файлів?


126
  • У мене є програма python-django
  • Я використовую блок тестування рамки
  • Тести розташовані у файлі "testing.py" у каталозі модулів
  • Я запускаю тести через ./manage.py test app

Тепер ..

  • tests.pyФайл стає досить великий / комплекс / брудний
  • Я хотів би розбити tests.pyна менші колекції тестів ...

Як?

Відповіді:


47

Поведінка змінилася в Django 1.6, тому більше не потрібно створювати пакет. Просто назвіть свої файли test*.py.

З документації Django 1.7

Під час запуску тестів поведінка тестової утиліти за замовчуванням полягає у пошуку всіх тестових випадків (тобто підкласів unittest.TestCase) у будь-якому файлі, ім'я якого починається з тесту, автоматично будувати тестовий набір із цих тестових випадків, і запустіть цей пакет.

З документації Django 1.6 ,

Тестове виявлення засноване на вбудованому тестовому виявленні модуля unittest. За замовчуванням це відкриє тести у будь-якому файлі під назвою "test * .py" у поточній робочій директорії.

Попередня поведінка з документації Django 1.5 :

Під час запуску тестів поведінка тестової утиліти за замовчуванням полягає у пошуку всіх тестових випадків (тобто підкласів unittest.TestCase) у models.py та testing.py, автоматично будує тестовий набір із цих тестових випадків, і запустіть цей пакет.

Існує другий спосіб визначення тестового набору для модуля: якщо ви визначите функцію, що називається suite (), або в models.py, або test.py, тестовий бігун Django використовуватиме цю функцію для побудови тестового набору для цього модуля. Це випливає із запропонованої організації для одиничних тестів. Дивіться документацію на Python для отримання більш детальної інформації про те, як побудувати складний тестовий набір.


4
У django 2.6 він насправді нічого не відкриває…
LtWorf

2
В даний час, використовуючи Django 1.10, я хотів помістити всі мої test*.pyфайли в папку, яку називають, testsщоб зберегти чисту папку - це можливо, але потрібно запустити ./manage.py test app.testsі весь відносний імпорт повинен піднятися на рівень ( from .modelsстає from ..models).
Скотт Стівенс

123

Зауважте, що цей підхід більше не діє від Django 1.6, дивіться цю публікацію .

Ви можете створити testsпапку ___init___.pyзсередини (щоб вона стала пакетом). Потім ви додаєте туди свої розділені тестові файли .py та імпортуєте їх усі ___init___.py.

Тобто: Замініть test.py файл модулем, який виглядає і діє як файл:

Створіть testsкаталог під відповідним додатком

додаток
app \ models.py
app \ views.py
додаток \ тести
додаток \ тести \ __ init__.py
додаток \ тести \ bananas.py
додаток \ тести \ apples.py

Імпорт підмодулів у app\tests\__init__.py:

from bananas import *
from apples import *

Тепер ви можете використовувати ./manage.py так, ніби всі вони були в одному файлі:

./manage.py test app.some_test_in_bananas

1
До. Ви мали на увазі створити модуль "тести" під програмою, яку я тестую; не нова програма під назвою тести. Я зараз це розумію. Дивовижно. Дякую!
Джон Мей

@John: Я більше не можу розпізнати свою відповідь! :-) Але ви абсолютно праві, що це було занадто розпливчастим, навіть якщо правильним - ваші приклади це ясно, всупереч моїй первісної формулюванні.
Томаш Зеліньскі

2
@Tomasz .. Ваші слова все ще є - цілком недоторканими. Я просто трохи це розробив, оскільки ти поставив мене на правильний шлях.
Джон Мей

@John: Я зовсім не розсердився, якщо це ти маєш на увазі :) Було просто смішно бачити власну відповідь дещо іншою формою
Tomasz Zieliński

4
@jMyles, якщо ви маєте на увазі під «звичайним бігуном на тест на джанго», python manage.py test myappто насправді ця відповідь спрацює чудово. (тільки що спробував)
Кірк Волл

27

Відповідь, сказана Томашем, правильна. Однак це може стати стомлюючим для того, щоб імпорт __init__.pyвідповідав вашій файловій структурі.

Щоб автоматично виявити всі тести в папці, ви можете додати це в __init__.py:

import unittest

def suite():   
    return unittest.TestLoader().discover("appname.tests", pattern="*.py")

Це дозволить вам запустити, ./manage.py test appnameале не обробляти конкретні тести. Для цього ви можете використовувати цей код (також у __init__.py):

import pkgutil
import unittest

for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(module_name).load_module(module_name)
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
            exec ('%s = obj' % obj.__name__)

Тепер ви можете запустити всі свої тести через manage.py test appабо конкретні тестування черезmanage.py test app.TestApples


Де ви розміщуєте другий твір?
rh0dium

Обидва шматки заходять у__init__.py
Брайс Дренан

Зауважте, що якщо будь-яке ім'я тестового пакету збігається з іменами модулів верхнього рівня, які імпортуються під час пробного запуску, фрагмент pkgutil призведе до збою імпорту, оскільки тести додаються як sys.modules[packagename]. Швидке вирішення - це delбудь-яке, що спричиняє проблеми після сказаного. (Або ви могли перейменувати свої папки;))
Пол Фенні

Це чудово, але я зіткнувся з помилкою, коли під час запуску тесту рівня програми ( python manage.py test appName) другий біт коду видав би помилку, вказавши, що __path__вона недоступна. Я уникнув цього, загорнувши другий фрагмент у if '__path__' in locals():чек, який зробив трюк. Дякую за відповідь!
alukach

1
+1 це також гарантує, що файл init дотримується загальних стандартів кодування, тобто не має * або невикористаного імпорту
Мартін Б.

13

Просто зробіть структуру каталогу таким чином:

myapp/
    __init__.py
    tests/
        __init__.py
        test_one.py
        test_two.py
        ...
    ...

І python manage.py test myappпрацюватиме, як очікувалося.



2

Не потрібно нічого кодувати в init. Просто створіть у своєму додатку підкаталог. Єдина вимога - не називати це тестами * Для зразка

app/
app/__init_.py
app/serializers.py
app/testing/
app/testing/__init__.py
app/testing/tests_serializers.py

1
Чому ви не можете назвати це чимось, що починається з "тестів"?
Serp C

Я використовую цю відповідь з Django 1.11.4. Причини його використання: (1) Файл "app / testing / __ init__.py" залишається порожнім і (2) Команда залишається основною "testt app python management.py"
rprasad

2

З Django 2.2 простим і досить хорошим рішенням може стати створення testпапки всередині програми, і ви можете помістити пов'язані test_...pyфайли в них, просто додати __init__.pyїх до testпапки.


1

Якщо у вас є більш складна установка або ви не хочете використовувати- from ... import *type оператори, ви можете визначити функцію, яку називають suiteу вашому testing.py (або тести / __ init__.py), яка повертає екземпляр unittest.TestSuite.


0

Я думаю, що ./manage.py testпросто виконувати всі трюкові трюки (у django> = 1.7).

Якщо у ваших організаційних тестах йдеться про групування та вишні, ви любите noseвикористовувати нос джанго :

python manage.py test another.test:TestCase.test_method

Якщо ви знаєте ніс, то ви знаєте, як «підкреслити» набагато приємніше всі ваші файли.

PS

Це просто краща практика. Сподіваюся, що це допомагає. Відповідь була запозичена звідси: Запуск конкретного тестового випадку в Django, коли у вашому додатку є каталог тестів


0

У мене два файли. Одне є, tests.pyа інше - test_api.py. Я можу запускати їх окремо, як нижче.

   manage.py test companies.tests
   manage.py test companies.test_api

Зверніться до відповіді @ osa щодо правила іменування файлів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.