Tắt di chuyển khi chạy kiểm tra đơn vị trong Django 1.7


110

Django 1.7 đã giới thiệu việc di chuyển cơ sở dữ liệu .

Khi chạy các bài kiểm tra đơn vị trong Django 1.7, nó buộc phải di chuyển , mất nhiều thời gian. Vì vậy, tôi muốn bỏ qua việc di chuyển django và tạo cơ sở dữ liệu ở trạng thái cuối cùng.

Tôi biết rằng việc bỏ qua các di chuyển có thể là một phương pháp không tốt, vì phần đó của mã sẽ không được kiểm tra. Nhưng không phải vậy: Tôi đang chạy quá trình di chuyển đầy đủ trong máy chủ kiểm tra CI (jenkins). Tôi chỉ muốn bỏ qua quá trình di chuyển trong các bài kiểm tra cục bộ của mình, nơi tốc độ quan trọng.


Một số bối cảnh:

Cho đến Django 1.6 , khi sử dụng South, tôi đã sử dụng cài đặt SOUTH_TESTS_MIGRATE :

Theo mặc định, lệnh syncdb của South cũng sẽ áp dụng di chuyển nếu nó chạy ở chế độ không tương tác, bao gồm cả khi bạn đang chạy thử nghiệm - nó sẽ chạy mọi di chuyển mỗi khi bạn chạy thử nghiệm của mình.

Nếu bạn muốn trình chạy thử nghiệm sử dụng syncdb thay vì di chuyển - ví dụ: nếu quá trình di chuyển của bạn mất quá nhiều thời gian để áp dụng - chỉ cần đặt SOUTH_TESTS_MIGRATE = False trong settings.py.

Tuy nhiên, syncdb không tồn tại nữa, bây giờ nó sẽ di chuyển .

Và từ Django 1.8, tôi sẽ sử dụng tham số --keepdb :

Tùy chọn --keepdb có thể được sử dụng để duy trì cơ sở dữ liệu thử nghiệm giữa các lần chạy thử nghiệm. Điều này có lợi thế là bỏ qua cả hành động tạo và hủy, giúp giảm đáng kể thời gian chạy thử nghiệm, đặc biệt là những hành động trong một bộ thử nghiệm lớn. Nếu cơ sở dữ liệu thử nghiệm không tồn tại, nó sẽ được tạo trong lần chạy đầu tiên và sau đó được giữ nguyên cho mỗi lần chạy tiếp theo. Mọi di chuyển chưa được áp dụng cũng sẽ được áp dụng cho cơ sở dữ liệu thử nghiệm trước khi chạy bộ thử nghiệm.

Vì vậy, câu hỏi này được giới hạn trong Django 1.7.


Tôi tranh luận rằng trong UT, bạn thực sự không chạy quá trình di chuyển theo cách kiểm tra chúng vì chúng DB mà bạn bắt đầu là không tồn tại. Thử nghiệm di chuyển chỉ thực sự xảy ra khi bạn đang di chuyển một DB hiện có. Doanh nghiệp di cư 1.7 này là khó khăn thực sự đầu tiên mà tôi có với Django, nhưng nó thực sự gây khó chịu. Nam ít nhất đã có kịch bản thử nghiệm phù hợp cho việc di cư.
boatcoder

Các django-test-without-migrationsgói đã thực sự có ích đối với tôi, bạn có thể muốn thay đổi câu trả lời được chấp nhận để stackoverflow.com/a/28993456/200224
Andy

Tôi muốn tránh thêm các phụ thuộc mới, nếu có thể.
David Arcos

Câu trả lời:


79

Hãy xem cách giải quyết này , được Bernie Sumption đăng lên danh sách gửi thư của nhà phát triển Django:

Nếu makemigrations vẫn chưa được chạy, lệnh "migrate" sẽ coi một ứng dụng là chưa được di chuyển và tạo các bảng trực tiếp từ các mô hình giống như syncdb đã làm trong 1.6. Tôi đã xác định mô-đun cài đặt mới chỉ dành cho các bài kiểm tra đơn vị có tên "settings_test.py", mô-đun này nhập * từ mô-đun cài đặt chính và thêm dòng này:

MIGRATION_MODULES = {"myapp": "myapp.migrations_not_used_in_tests"}

Sau đó, tôi chạy các bài kiểm tra như thế này:

DJANGO_SETTINGS_MODULE = "myapp.settings_test" thử nghiệm python management.py

Điều này ngu ngốc chuyển sang nghĩ rằng ứng dụng chưa được di chuyển và vì vậy mỗi khi cơ sở dữ liệu thử nghiệm được tạo, nó sẽ phản ánh cấu trúc hiện tại của models.py.

Trong Django 1.9, tình trạng này được cải thiện phần nào và bạn có thể đặt giá trị thành None:

MIGRATION_MODULES = {"myapp": Không có}


9
Lưu ý rằng myapp.migrations_not_used_in_testsmô-đun không được tồn tại.
bmihelac

4
Ngoài nhận xét @bmihelac đưa ra về mô-đun không tồn tại, chuỗi mô-đun phải chứa chuỗi con 'chuyển đổi', Để biết lý do tại sao, hãy xem: github.com/django/django/blob/stable/1.7.x/django/db/migrations /…
nealtodd

7
Ý chính của một hàm để tạo MIGRATION_MODULES động trong settings_test.py: gist.github.com/nealtodd/2869341f38f5b1eeb86d
nealtodd

1
TY. Tôi đã có thể giảm các bài kiểm tra đơn vị của mình từ 13 giây xuống 4 giây vì điều này. Ngoài ra, có thể tìm thấy nhiều mức tăng tốc độ hơn bằng cách sử dụng sqlite để thử nghiệm. Đối với tôi, sử dụng postgres cho các bài kiểm tra mất 5,5 giây nhưng sqlite mất 4 giây.
Gattster

21
Từ các nhận xét về ý chính của @ nealtodd, đây là một liên kết đến một giải pháp tránh một số cạm bẫy và cực kỳ đơn giản: gist.github.com/NotSqrt/5f3c76cd15e40ef62d09
djsutho

72

Đây là phần cuối của tệp cài đặt của tôi:

class DisableMigrations(object):

    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None


TESTS_IN_PROGRESS = False
if 'test' in sys.argv[1:] or 'jenkins' in sys.argv[1:]:
    logging.disable(logging.CRITICAL)
    PASSWORD_HASHERS = (
        'django.contrib.auth.hashers.MD5PasswordHasher',
    )
    DEBUG = False
    TEMPLATE_DEBUG = False
    TESTS_IN_PROGRESS = True
    MIGRATION_MODULES = DisableMigrations()

dựa trên đoạn mã này

Tôi chỉ tắt tính năng di chuyển khi các thử nghiệm đang chạy


1
Đẹp! Tôi sẽ thêm __setitem__(self, *_)phương pháp cũng vì chúng tôi đã có vấn đề với các ứng dụng thiết lập di cư của mình như settings.MIGRATION_MODULES['chroniker'] = 'db_migrations'
Zhe Li

1
Cảm ơn bạn rất nhiều vì điều này, đó là điều duy nhất tôi thấy rằng nó thực sự hoạt động.
fluffels

Điều này không còn hoạt động trong Django 1.9 khi chạy thử nghiệm ở chế độ song song. Sử dụng thử nghiệm không song song bình thường, nó tiếp tục hoạt động tốt, nhưng chuyển sang chế độ song song dẫn đến lỗi không tìm thấy bảng.
LS55321

@LeeSemel ở chế độ song song, bạn có thể muốn sử dụng giải pháp từ rlmv
Guillaume Vincent

@guillaumevincent tôi có cùng một vấn đề khi sử dụng django-test-không-di cư trong chế độ song song
LS55321


3

Cập nhật : Đừng bận tâm, thay đổi này đã được hoàn nguyên trước khi bản cuối 1.10 được phát hành. Hy vọng rằng nó sẽ trở lại trong một phiên bản trong tương lai.


Lưu ý rằng kể từ Django 1.10, điều này có thể được kiểm soát bởi cài đặt cơ sở dữ liệu thử nghiệm.

DI CƯ

Mặc định: True

Nếu được đặt thành False, Django sẽ không sử dụng di chuyển để tạo cơ sở dữ liệu thử nghiệm.



1

Đối với django 1.9 trở lên, câu trả lời của Guillaume Vincent không hoạt động nữa, vì vậy đây là một giải pháp mới:

Tôi đang sử dụng đoạn mã này trong tệp cài đặt của mình, sau định nghĩa của INSTALLED_APPS

if os.environ.get('TESTS_WITHOUT_MIGRATIONS', False):
    MIGRATION_MODULES = {
        app.split('.')[-1]: None for app in INSTALLED_APPS
    }

Nó lặp lại trên tất cả các ứng dụng đã cài đặt và đánh dấu mỗi ứng dụng là không có mô-đun di chuyển. Xem tài liệu django để biết thêm thông tin .

Sử dụng đoạn mã này, bạn có thể chạy các thử nghiệm của mình, thiết lập biến môi trường TESTS_WITHOUT_MIGRATIONS, ví dụ:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test

1

Tôi chỉ tìm ra cách vô hiệu hóa di chuyển sau django 1.10, có thể nó có thể giúp ích cho ai đó. Đây là liên kết tại git

class DisableMigrations(dict):
    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

Migrations cho django 1.10 có hai phần, vui lòng xem load_diskghi

Phần load_diskdành cho mô hình di chuyển của ứng dụng được thêm tại INSTALL_APP Và phần recorderdành cho kết nối cơ sở dữ liệu Đối với phiên bản trước 1.9, chúng tôi cần đặt MIGRATION_MODULES={'do.not.migrate':'notmigrations'}khi bạn đang chạy thử nghiệm Bây giờ chúng tôi cần đặt nó Không giống như MIGRATION_MODULES={'do.not.migrate':None} vậy Nếu chúng tôi không muốn thực hiện di chuyển cho bất kỳ ứng dụng nào , chỉ cần mở rộng một dict và trả về Nonecho getitemhàm, và thực hiện tương tự DATABASES, đó là điều đúng bạn cần làm

PS: Đối với lệnh, bạn cần chỉ định --setting=module.path.settings_test_snippetsau test PPS Nếu bạn đang làm việc với pycharm, không đặt --settings tùy chọn tại Run/Debug configurations, chỉ cần thêm đường dẫn củasettings_test_snippet.py tại Cài đặt tùy chỉnh. Tốt thôi !!

thưởng thức

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.