Menjalankan test case khusus di Django ketika aplikasi Anda memiliki direktori tes

165

Dokumentasi Django ( http://docs.djangoproject.com/en/1.3/topics/testing/#running-tests ) mengatakan bahwa Anda dapat menjalankan masing-masing kotak uji dengan menetapkannya:

$ ./manage.py test animals.AnimalTestCase

Ini mengasumsikan bahwa Anda memiliki tes Anda dalam file tests.py di aplikasi Django Anda. Jika ini benar, maka perintah ini berfungsi seperti yang diharapkan.

Saya memiliki tes untuk aplikasi Django di direktori tes:

my_project/apps/my_app/
├── __init__.py
├── tests
   ├── __init__.py
   ├── field_tests.py
   ├── storage_tests.py
├── urls.py
├── utils.py
└── views.py

The tests/__init__.pyfile memiliki suite () fungsi:

import unittest

from my_project.apps.my_app.tests import field_tests, storage_tests

def suite():
    tests_loader = unittest.TestLoader().loadTestsFromModule
    test_suites = []
    test_suites.append(tests_loader(field_tests))
    test_suites.append(tests_loader(storage_tests))
    return unittest.TestSuite(test_suites)

Untuk menjalankan tes yang saya lakukan:

$ ./manage.py test my_app

Mencoba menentukan kasus uji individual menimbulkan pengecualian:

$ ./manage.py test my_app.tests.storage_tests.StorageTestCase
...
ValueError: Test label 'my_app.tests.storage_tests.StorageTestCase' should be of the form app.TestCase or app.TestCase.test_method

Saya mencoba melakukan apa yang dikatakan pesan pengecualian:

$ ./manage.py test my_app.StorageTestCase
...
ValueError: Test label 'my_app.StorageTestCase' does not refer to a test

Bagaimana cara menentukan kasus uji individual ketika tes saya di beberapa file?

hekevintran
sumber

Jawaban:

156

Periksa django-nose . Ini memungkinkan Anda menentukan tes untuk dijalankan seperti:

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

atau seperti yang tercantum dalam komentar, gunakan sintaks:

python manage.py test another.test.TestCase.test_method
Sam Dolan
sumber
Terima kasih @ddolan. Mengalami masalah yang sama dengan hekevintran. Beralih ke Django-nose dan memperbaiki masalah itu, juga bekerja jauh lebih baik daripada test runner Django default.
LeeMobile
Ini menjalankan tes, tetapi bagaimana menjalankan seluruh TestCase?
jMyles
5
@jMyles:another.test:TestCase
Sam Dolan
4
Perhatian orang-orang seperti saya yang menyisipkan secara membabi buta dari Stackoverflow: Ini akan kesalahan tanpa plugin yang disebutkan, gunakan sintaks yang dijelaskan dalam jawaban lain (. Bukannya :) yang bekerja di Django 1.6+.
Andy Smith
1
Saya menurunkan jawaban ini karena sebenarnya tidak menjawab pertanyaan OP, yang bagaimana melakukan ini di Django. Sebaliknya, itu hanya menyarankan untuk beralih ke Nosetest
Josh Brown
175

Karena Django 1.6 Anda dapat menjalankan test case lengkap, atau single test, menggunakan notasi titik lengkap untuk elemen yang ingin Anda jalankan.

Penemuan tes otomatis sekarang akan menemukan tes dalam file apa pun yang dimulai dengan tes di bawah direktori kerja, jadi menjawab pertanyaan Anda harus mengganti nama file Anda, tetapi sekarang Anda dapat menyimpannya di dalam direktori yang Anda inginkan. Jika Anda ingin menggunakan nama file khusus, Anda dapat menentukan pola (default Django test runner) dengan flag opsi --pattern="my_pattern_*.py".

Jadi jika Anda berada di manage.pydirektori Anda dan ingin menjalankan tes test_adi dalam TestCasesubkelas Adi dalam file di tests.pybawah aplikasi / modul exampleyang akan Anda lakukan:

python manage.py test example.tests.A.test_a

Jika Anda tidak ingin menyertakan dependensi dan berada di Django 1.6 atau yang lebih baru, itulah cara Anda melakukannya.

Lihat dokumentasi Django untuk informasi lebih lanjut

cristiano2lopes
sumber
Senang melihat fitur ini dibangun ke Django sekarang.
hekevintran
Saya tidak bisa membuat ini bekerja sama sekali: error: option --pattern not recognizeddaninvalid command name
geoidesic
Ini bekerja sangat baik di Django v3!
Kirk
11

Saya sendiri mengalami masalah ini dan menemukan pertanyaan ini, kalau-kalau ada yang datang, inilah yang saya gali. DjangoTestSuiteRuner menggunakan metode yang disebut build_test (label) yang mencari tahu kasus uji apa yang harus dijalankan berdasarkan label. Melihat ke metode ini ternyata mereka melakukan getattr () pada modul "model" atau "test". Ini berarti jika Anda mengembalikan suite pelari tes tidak mencari kasus pengujian Anda di suite itu, itu hanya terlihat di salah satu modul tersebut.

Solusi cepat adalah menggunakan __init__.pyuntuk mengimpor tes Anda secara langsung alih-alih mendefinisikan suite. Jadikan mereka bagian dari modul "test" dan build_test (label) dapat menemukannya.

Untuk contoh Anda di atas, tests/__init__.pycukup berisi:

from field_tests import *
from storage_tests import *

Ini tidak terlalu elegan dan tentu saja jika Anda mencoba melakukan sesuatu yang lebih rumit dengan suite Anda maka ini tidak akan berhasil, tetapi itu akan berlaku untuk kasus ini.

Chris T
sumber
11

Ini harus bekerja-

python manage.py test my_app.tests.storage_tests
Swapnil Patel
sumber
3

Letakkan kode ini di __init__.py Anda dan itu akan mengimpor semua kelas uji dalam paket dan sub-paket. Ini akan memungkinkan Anda untuk menjalankan tes tertentu tanpa mengimpor setiap file secara manual.

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__)

Demikian pula, untuk suite pengujian Anda, Anda dapat menggunakan:

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

Sekarang yang harus Anda lakukan untuk tes baru adalah menulisnya dan pastikan semuanya ada di folder tes. Tidak ada lagi perawatan impor yang membosankan!

Bryce Drennan
sumber