Django birim testleri birden fazla dosyaya nasıl yayılır?


126
  • Bir python-django uygulamam var
  • Ben kullanıyorum birim test çerçevesi
  • Testler, modül dizinindeki "tests.py" dosyasında düzenlenir
  • Testleri şu yolla çalıştırıyorum ./manage.py test app

Şimdi ..

  • tests.pyDosya oldukça büyük / karmaşık oluyor / dağınık
  • Daha tests.pyküçük test koleksiyonlarına ayrılmak istiyorum ...

Nasıl?

Yanıtlar:


47

Davranış Django 1.6'da değişti, bu nedenle artık bir paket oluşturmaya gerek yok. Sadece dosyalarınızı adlandırın test*.py.

Django 1.7 belgelerinden

Testlerinizi çalıştırdığınızda, test uygulamasının varsayılan davranışı, adı test ile başlayan herhangi bir dosyadaki tüm test senaryolarını (yani, unittest.TestCase alt sınıflarını) bulmak, bu test senaryolarından otomatik olarak bir test paketi oluşturmaktır. ve o süiti işlet.

Gönderen Django 1.6 belgelerinde ,

Test keşfi, birim test modülünün yerleşik test keşfine dayanır. Varsayılan olarak bu, geçerli çalışma dizini altındaki "test * .py" adlı herhangi bir dosyadaki testleri keşfedecektir.

Django 1.5 belgelerinden önceki davranış :

Testlerinizi çalıştırdığınızda, test yardımcı programının varsayılan davranışı, models.py ve tests.py içindeki tüm test senaryolarını (yani, unittest.TestCase alt sınıflarını) bulmaktır, bu test senaryolarından otomatik olarak bir test paketi oluşturur, ve o süiti işlet.

Bir modül için test paketini tanımlamanın ikinci bir yolu vardır: model.py veya tests.py'de suite () adında bir işlev tanımlarsanız, Django test çalıştırıcısı o modül için test takımını oluşturmak için bu işlevi kullanır. Bu, birim testleri için önerilen organizasyonu izler. Karmaşık bir test paketinin nasıl oluşturulacağı hakkında daha fazla ayrıntı için Python belgelerine bakın.


4
Django 2.6'da gerçekten hiçbir şey keşfetmiyor…
LtWorf

2
Şu anda Django 1.10 kullanarak, tüm test*.pydosyalarımı tests, klasörü temiz tutmak için çağrılan bir klasöre koymak istedim - bu mümkündür, ancak çalıştırmanız gerekir ./manage.py test app.testsve tüm göreli içe aktarmaların bir seviyeye çıkması gerekir ( from .modelsolur from ..models).
Scott Stevens

123

Bu yaklaşım artık geçerli Django 1.6 ila Not olduğunu, bunu görmek yazıyı .

İçinde testsile klasör oluşturabilirsiniz ___init___.py(böylece bir paket haline gelir). Ardından bölünmüş test .py dosyalarınızı buraya eklersiniz ve hepsini içine aktarırsınız ___init___.py.

Yani: test.pyDosyayı, dosya gibi görünen ve çalışan bir modülle değiştirin:

testsSöz konusu uygulamanın altında bir Dizin oluşturun

Uygulamanın
Uygulamanın \ models.py
Uygulamanın \ views.py
Uygulamanın \ testler
Uygulamanın \ \ __ init__.py testleri
Uygulamanın \ testler \ bananas.py
Uygulamanın \ testler \ apples.py

Alt modülleri şuraya aktarın app\tests\__init__.py:

from bananas import *
from apples import *

Artık ./manage.py dosyasını hepsi tek bir dosyadaymış gibi kullanabilirsiniz:

./manage.py test app.some_test_in_bananas

1
Hamuru. Test ettiğim uygulama altında bir 'test' modülü oluşturmayı kastettiniz; test adı verilen yeni bir uygulama değil. Şimdi anladım. Muhteşem. Teşekkürler!
John Mee

@John: Cevabımı artık tanıyamıyorum! :-) Ama doğru olsa bile çok belirsiz olduğu konusunda tamamen haklısınız - örnekleriniz bunu açıklığa kavuşturuyor, benim orijinal sözlerimin aksine.
Tomasz Zieliński

2
@Tomasz .. Sözleriniz hala orada - tamamen sağlam. Beni doğru yola soktuğundan beri biraz ayrıntılarıyla anlattım.
John Mee

@John: Kastettiğin buysa hiç kızmadım :) Kendi cevabımı biraz farklı bir şekilde görmek çok komikti
Tomasz Zieliński

4
@jMyles, eğer "normal django test koşucusu" derken, python manage.py test myappaslında bu cevabın iyi çalıştığını kastediyorsunuz . (yeni denedim)
Kirk Woll

27

Tomasz'ın belirttiği gibi cevap doğrudur. Ancak, içe aktarımların __init__.pydosya yapınıza uymasını sağlamak yorucu olabilir .

İçin otomatik olarak klasördeki tüm testleri tespit Eğer bu ekleyebilirsiniz __init__.py:

import unittest

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

Bu, çalıştırmanıza izin verir ./manage.py test appnameancak belirli testleri çalıştırmanızı sağlamaz. Bunu yapmak için bu kodu kullanabilirsiniz (ayrıca içinde __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__)

Artık tüm testlerinizi manage.py test appveya belirli testlerinizi şu yolla çalıştırabilirsiniz:manage.py test app.TestApples


İkinci parçayı nereye koyuyorsunuz?
rh0dium

Her iki parça da giriyor__init__.py
Bryce Drennan

Test paketi adlarınızdan herhangi biri, test çalıştırması sırasında içe aktarılan üst düzey modül adlarıyla çakışırsa, pkgutil parçacığı, testler olarak eklendiğinden içe aktarmanın başarısız olmasına neden olacağını unutmayın sys.modules[packagename]. Hızlı bir çözüm, delyukarıdakilerden sonra sorunlara neden olanlardır. (Veya klasörlerinizi yeniden adlandırabilirsiniz;))
Paul Fenney

Bu harika ama bir uygulama seviyesinde test ( python manage.py test appName) çalıştırırken ikinci kod bitinin __path__mevcut olmadığını belirten bir hata attığı bir hatayla karşılaştım . İkinci pasajı bir if '__path__' in locals():çeke sararak bundan kaçındım , bu hile yaptı. Cevap için teşekkürler!
alukach

1
+1 bu ayrıca init dosyasının ortak kodlama standartlarına uymasını sağlar , yani * veya kullanılmamış içe
Martin B.

13

Dizin yapınızı şu şekilde yapın:

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

Ve python manage.py test myappbeklendiği gibi çalışacak.



2

Init'te hiçbir şeyi kodlamaya gerek yok. Uygulamanızda bir alt dizin oluşturmanız yeterlidir. Tek şart, test olarak adlandırılmamasıdır * Örneğin

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

1
Neden buna "testler" ile başlayan bir şey diyemiyorsun?
Serp C

Bu yanıtı Django 1.11.4 ile kullanıyorum. Kullanmanın nedenleri: (1) "app / testing / __ init__.py" dosyası boş kalır ve (2) Komut temel "python manage.py test uygulaması" olarak kalır
rprasad

2

Django 2.2 ile basit ve oldukça iyi bir çözüm bir oluşturmak olabilir test, uygulamanın içinde klasör ve size ilgili koyabilirsiniz test_...py, dosyaları sadece eklemek __init__.pyiçin testklasöre.


1

Daha karmaşık bir kurulumunuz varsa veya from ... import *-type deyimlerini kullanmak istemiyorsanız suite, tests.py (veya testler / __ init__.py) içinde çağrılan ve bir örneğini döndüren bir işlev tanımlayabilirsiniz unittest.TestSuite.


0

Sanırım ./manage.py testbasitçe tüm testleri çalıştırıyor (django> = 1.7'de).

Senin Eğer organize testler hakkında gruplama ve cherrypicking ve hayranı olan nosekullanım burun django :

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

Eğer burnu biliyorsanız, o zaman tüm dosyalarınızda nasıl daha güzel "joker karakter" yapacağınızı bilirsiniz.

PS

Bu sadece daha iyi bir uygulamadır. Umarım yardımcı olur. Cevap buradan ödünç alındı: Uygulamanızın bir test dizini varken Django'da belirli bir test durumu çalıştırmak


0

İki dosyam var. Biri tests.pyve diğeri test_api.py. Bunları aşağıdaki gibi ayrı ayrı çalıştırabilirim.

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

@ Osa'nın dosya adlandırma kuralı hakkındaki yanıtına bakın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.