2009-10-23 34 views
10

Nếu tôi chạy lệnh sau:Định cấu hình Django để tìm tất cả các tài liệu trong tất cả các mô-đun?

>python manage.py test 

Django nhìn tests.py trong ứng dụng của tôi, và chạy bất kỳ doctests hoặc kiểm tra đơn vị trong tập tin đó. Nó cũng nhìn vào __ test __ dictionary để chạy thử nghiệm thêm. Vì vậy, tôi có thể liên kết doctests từ các module khác như vậy:

#tests.py 
from myapp.module1 import _function1, _function2 

__test__ = { 
    "_function1": _function1, 
    "_function2": _function2 
} 

Nếu tôi muốn để bao gồm nhiều doctests, là có một cách dễ dàng hơn liệt kê tất cả chúng trong từ điển này? Lý tưởng nhất, tôi chỉ muốn có Django tìm tất cả các doctests trong tất cả các mô-đun trong ứng dụng myapp.

Có loại hack phản chiếu nào có thể đưa tôi đến nơi tôi muốn không?

Trả lời

1

Nhờ Alex và Paul. Đây là những gì tôi đã đưa ra:

# tests.py 
import sys, settings, re, os, doctest, unittest, imp 

# import your base Django project 
import myapp 

# Django already runs these, don't include them again 
ALREADY_RUN = ['tests.py', 'models.py'] 

def find_untested_modules(package): 
    """ Gets all modules not already included in Django's test suite """ 
    files = [re.sub('\.py$', '', f) 
      for f in os.listdir(os.path.dirname(package.__file__)) 
      if f.endswith(".py") 
      and os.path.basename(f) not in ALREADY_RUN] 
    return [imp.load_module(file, *imp.find_module(file, package.__path__)) 
      for file in files] 

def modules_callables(module): 
    return [m for m in dir(module) if callable(getattr(module, m))] 

def has_doctest(docstring): 
    return ">>>" in docstring 

__test__ = {} 
for module in find_untested_modules(myapp.module1): 
    for method in modules_callables(module): 
     docstring = str(getattr(module, method).__doc__) 
     if has_doctest(docstring): 

      print "Found doctest(s) " + module.__name__ + "." + method 

      # import the method itself, so doctest can find it 
      _temp = __import__(module.__name__, globals(), locals(), [method]) 
      locals()[method] = getattr(_temp, method) 

      # Django looks in __test__ for doctests to run 
      __test__[method] = getattr(module, method) 
+0

Làm cách nào để bạn xử lý các mô-đun sâu hơn cấp 1 ('myapp.views.stats')? –

+0

os.walk() nên được thêm vào đó. –

+0

Vui mừng được hỗ trợ. Có vẻ như một đoạn trích hữu ích. –

1

yếu tố chính Here're của giải pháp:

tests.py:

def find_modules(package): 
    """Return list of imported modules from given package""" 
    files = [re.sub('\.py$', '', f) for f in os.listdir(os.path.dirname(package.__file__)) 
      if f.endswith(".py") and os.path.basename(f) not in ('__init__.py', 'test.py')] 
    return [imp.load_module(file, *imp.find_module(file, package.__path__)) for file in files] 

def suite(package=None): 
    """Assemble test suite for Django default test loader""" 
    if not package: package = myapp.tests # Default argument required for Django test runner 
    return unittest.TestSuite([doctest.DocTestSuite(m) for m in find_modules(package)]) 

Để thêm đệ quy sử dụng os.walk() phải đi qua cây mô-đun và tìm gói python.

+0

Tôi thích phương pháp tìm kiếm các mô-đun của Paul. Bạn đã cung cấp mã để nhận các bài kiểm tra tài liệu. Chăm sóc để đóng vòng lặp và xây dựng __ thử nghiệm __ từ điển? –

2

tôi giải quyết này cho bản thân mình một lúc trước:

 
apps = settings.INSTALLED_APPS 

for app in apps: 
    try: 
     a = app + '.test' 
     __import__(a) 
     m = sys.modules[a] 
    except ImportError: #no test jobs for this module, continue to next one 
     continue 
    #run your test using the imported module m 

này cho phép tôi đặt thử nghiệm cho mỗi mô-đun trong tập tin test.py riêng của họ, vì vậy họ đã không nhận được trộn lẫn với phần còn lại của tôi mã ứng dụng. Nó sẽ dễ dàng để sửa đổi điều này để chỉ cần tìm các bài kiểm tra doc trong mỗi mô-đun của bạn và chạy chúng nếu nó tìm thấy chúng.

+0

Điều này là rất tốt cho các bài kiểm tra đơn vị. Cảm ơn! Nếu bạn thực sự có thể viết mã với một ví dụ làm việc cho các bài kiểm tra tài liệu, tôi sẽ rất vui khi được trao các điểm thưởng. –

2

Sử dụng django-nose vì mũi tự động tìm tất cả các thử nghiệm recursivelly.

+0

Dường như là một ý tưởng hay, nhưng (a) nó không tự động tìm tài liệu, và (b) những nỗ lực của tôi để nói với nó để tìm các tài liệu dường như không có hiệu lực – Auspex

1

Tôi không bắt kịp tốc độ thử nghiệm của Djano, nhưng khi tôi hiểu nó sử dụng khám phá tự động unittest, giống như python -m unittest discover và Mũi.

Nếu có, chỉ cần đặt tệp sau đây vào nơi mà khám phá sẽ tìm thấy tệp đó (thường chỉ là đặt tên nó là test_doctest.py hoặc tương tự).

Thay đổi your_package thành gói để kiểm tra. Tất cả các mô-đun (bao gồm cả các gói phụ) sẽ được doctested.

import doctest 
import pkgutil 

import your_package as root_package 


def load_tests(loader, tests, ignore): 
    modules = pkgutil.walk_packages(root_package.__path__, root_package.__name__ + '.') 
    for _, module_name, _ in modules: 
     try: 
      suite = doctest.DocTestSuite(module_name) 
     except ValueError: 
      # Presumably a "no docstrings" error. That's OK. 
      pass 
     else: 
      tests.addTests(suite) 
    return tests 
Các vấn đề liên quan