Làm thế nào để truyền bá bài kiểm tra đơn vị django trên nhiều tập tin?


126
  • Tôi có một ứng dụng python-django
  • Tôi đang sử dụng khung kiểm tra đơn vị
  • Các bài kiểm tra được sắp xếp trong tệp "tests.py" trong thư mục mô-đun
  • Tôi đang chạy thử nghiệm qua ./manage.py test app

Hiện nay..

  • Các tests.pytập tin đang trở nên khá lớn / phức tạp / lộn xộn
  • Tôi muốn chia tests.pythành các bộ sưu tập thử nghiệm nhỏ hơn ...

Làm sao?

Câu trả lời:


47

Hành vi đã thay đổi trong Django 1.6, do đó không còn cần phải tạo gói. Chỉ cần đặt tên cho các tập tin của bạn test*.py.

Từ tài liệu Django 1.7

Khi bạn chạy thử nghiệm, hành vi mặc định của tiện ích thử nghiệm là tìm tất cả các trường hợp thử nghiệm (nghĩa là các lớp con của unittest.TestCase) trong bất kỳ tệp nào có tên bắt đầu bằng thử nghiệm, tự động xây dựng bộ thử nghiệm từ các trường hợp thử nghiệm đó, và chạy bộ đó.

Từ tài liệu Django 1.6 ,

Khám phá thử nghiệm dựa trên khám phá thử nghiệm tích hợp sẵn của mô-đun nhỏ nhất. Theo mặc định, điều này sẽ khám phá các thử nghiệm trong bất kỳ tệp nào có tên là test test * .py tựa trong thư mục làm việc hiện tại.

Hành vi trước đó, từ tài liệu Django 1.5 :

Khi bạn chạy thử nghiệm, hành vi mặc định của tiện ích thử nghiệm là tìm tất cả các trường hợp thử nghiệm (nghĩa là các lớp con của unittest.TestCase) trong model.py và tests.py, tự động xây dựng một bộ thử nghiệm trong số các trường hợp thử nghiệm đó, và chạy bộ đó.

Có một cách thứ hai để xác định bộ kiểm thử cho một mô-đun: nếu bạn xác định một hàm được gọi là bộ () trong mô hình mô hình hoặc tests.txt, trình chạy thử Django sẽ sử dụng chức năng đó để xây dựng bộ thử nghiệm cho mô-đun đó. Điều này theo tổ chức đề xuất cho các bài kiểm tra đơn vị. Xem tài liệu Python để biết thêm chi tiết về cách xây dựng bộ kiểm tra phức tạp.


4
Trong django 2,6 nó không thực sự khám phá bất cứ điều gì ...
LtWorf

2
Hiện đang sử dụng Django 1.10, tôi muốn đặt tất cả test*.pycác tệp của mình vào một thư mục được gọi testsđể giữ cho thư mục sạch sẽ - điều này là có thể, nhưng bạn phải chạy ./manage.py test app.testsvà tất cả các lần nhập tương đối cần phải tăng lên ( from .modelstrở thành from ..models).
Scott Stevens

123

Lưu ý rằng phương pháp này không còn hiệu lực từ Django 1.6, xem bài đăng này .

Bạn có thể tạo teststhư mục với ___init___.pybên trong (để nó trở thành một gói). Sau đó, bạn thêm các tệp .py thử nghiệm phân tách của bạn ở đó và nhập tất cả chúng vào ___init___.py.

Tức là: Thay thế test.pytệp bằng một mô-đun trông và hoạt động giống như tệp:

Tạo một thư testsmục trong ứng dụng được đề cập

ứng dụng
ứng dụng \ model.py
ứng dụng \ lượt xem
ứng dụng \ kiểm tra
ứng dụng \ tests \ __ init__.py
ứng dụng \ tests \ bananas.py
ứng dụng \ tests \ apples.py

Nhập các mô hình con vào app\tests\__init__.py:

from bananas import *
from apples import *

Bây giờ bạn có thể sử dụng ./manage.py như thể tất cả chúng đều nằm trong một tệp:

./manage.py test app.some_test_in_bananas

1
Doh. Bạn có nghĩa là tạo một mô-đun 'thử nghiệm' trong ứng dụng tôi đang thử nghiệm; không phải là một ứng dụng mới gọi là kiểm tra. Bây giờ tôi hiểu rồi. Tuyệt vời. Cảm ơn!
John Mee

@ John: Tôi không thể nhận ra câu trả lời của mình nữa! :-) Nhưng bạn hoàn toàn đúng khi nói rằng nó quá mơ hồ, ngay cả khi chính xác - ví dụ của bạn làm cho nó rõ ràng, trái với từ ngữ ban đầu của tôi.
Tomasz Zieliński

2
@Tomasz .. Lời nói của bạn vẫn còn đó - hoàn toàn nguyên vẹn. Tôi chỉ tập trung vào nó một chút kể từ khi bạn đưa tôi đi đúng hướng.
John Mee

@ John: Tôi đã không tức giận chút nào nếu đó là những gì bạn có ý nghĩa :) Đó chỉ là hài hước để xem câu trả lời của riêng tôi trong một hình dạng khác nhau chút
Tomasz Zieliński

4
@jMyles, nếu theo "người chạy thử django thông thường" python manage.py test myappthì ý bạn là trên thực tế câu trả lời này không hoạt động tốt. (chỉ cần thử nó)
Kirk Woll

27

Câu trả lời như đã nêu của Tomasz là chính xác. Tuy nhiên, nó có thể trở nên tẻ nhạt để đảm bảo rằng việc nhập __init__.pyphù hợp với cấu trúc tệp của bạn.

Để tự động phát hiện tất cả các bài kiểm tra trong thư mục, bạn có thể thêm phần này vào __init__.py:

import unittest

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

Điều này sẽ cho phép bạn chạy ./manage.py test appnamenhưng sẽ không xử lý các bài kiểm tra cụ thể. Để làm điều đó, bạn có thể sử dụng mã này (cũng trong __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__)

Bây giờ bạn có thể chạy tất cả các bài kiểm tra của mình thông qua manage.py test apphoặc kiểm tra cụ thể thông quamanage.py test app.TestApples


Nơi nào bạn đặt mảnh thứ hai?
rh0dium

Cả hai mảnh đi vào__init__.py
Bryce Drennan

Lưu ý rằng nếu bất kỳ tên gói thử nghiệm nào của bạn trùng với tên mô-đun cấp cao nhất được nhập trong quá trình chạy thử, đoạn mã pkgutil sẽ khiến quá trình nhập thất bại vì các thử nghiệm được thêm dưới dạng sys.modules[packagename]. Một cách giải quyết nhanh là delbất kỳ vấn đề nào gây ra vấn đề sau. (Hoặc bạn có thể đổi tên các thư mục của mình;))
Paul Fenney

Điều này thật tuyệt nhưng tôi đã gặp phải một lỗi trong đó, khi chạy thử nghiệm cấp độ ứng dụng ( python manage.py test appName), đoạn mã thứ hai sẽ đưa ra một lỗi cho biết __path__không có sẵn. Tôi tránh nó bằng cách gói đoạn mã thứ hai vào một if '__path__' in locals():tấm séc, điều này đã tạo ra mánh khóe. Cảm ơn câu trả lời!
alukach

1
+1 điều này cũng đảm bảo rằng tệp init tuân thủ các tiêu chuẩn mã hóa phổ biến, tức là không có nhập khẩu * hoặc không được sử dụng
Martin B.

13

Chỉ cần làm cho cấu trúc thư mục của bạn như thế này:

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

python manage.py test myappsẽ làm việc như mong đợi.



2

Không cần mã bất cứ điều gì trong init. Chỉ cần tạo một thư mục con trong ứng dụng của bạn. Chỉ yêu cầu là không gọi nó là kiểm tra * Ví dụ

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

1
Tại sao bạn không thể gọi nó là một cái gì đó bắt đầu bằng "bài kiểm tra"?
Serp C

Tôi đang sử dụng câu trả lời này với Django 1.11.4. Lý do nên sử dụng: (1) Tệp "app / tests / __ init__.py" vẫn trống và (2) Lệnh vẫn là "ứng dụng kiểm tra python
Manage.py

2

Với Django 2.2, một giải pháp đơn giản và khá tốt có thể là tạo một testthư mục bên trong một ứng dụng và bạn có thể đặt các test_...pytệp liên quan của mình vào, chỉ cần thêm __init__.pyvào testthư mục.


1

Nếu bạn có một thiết lập phức tạp hơn hoặc không muốn sử dụng các from ... import *câu lệnh -type, bạn có thể xác định một hàm được gọi suitetrong tests.txt (hoặc tests / __ init__.py), trả về một thể hiện của unittest.TestSuite.


0

Tôi nghĩ ./manage.py testđơn giản là chạy tất cả các thủ thuật thử nghiệm (trong django> = 1.7).

Nếu các bài kiểm tra tổ chức của bạn là về nhómcherrypicking và bạn là người hâm mộ nosesử dụng mũi django :

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

Nếu bạn biết mũi, thì bạn biết cách "ký tự đại diện" đẹp hơn nhiều so với tất cả các tệp của bạn.

PS

Nó chỉ là một thực hành tốt hơn. Mong rằng sẽ giúp. Câu trả lời đã được mượn từ đây: Chạy một trường hợp thử nghiệm cụ thể trong Django khi ứng dụng của bạn có thư mục thử nghiệm


0

Tôi có hai tập tin. Một là tests.pyvà một là test_api.py. Tôi có thể chạy các cá nhân như dưới đây.

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

Tham khảo phản hồi của @ osa về quy ước đặt tên tệp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.