Câu hỏi làm thế nào để viết thử nghiệm django có nghĩa là để thất bại?


Tôi có một mô hình gọi là Thing với một thuộc tính được gọi là namevà tôi muốn đặt tên là một trường char chỉ có Dài 3 ký tự.

Làm thế nào để viết một bài kiểm tra cho điều đó?

class TestCase1(TestCase):
    def test1(self):
        thing = Thing(name='1234')

thử nghiệm đó sẽ thất bại. Làm thế nào để viết đúng bài kiểm tra để kiểm tra vượt qua khi đối tượng đó thất bại?


36
2017-11-18 18:22


gốc




Các câu trả lời:


Nếu bạn đang mong muốn Thing (name = '1234') đưa ra một ngoại lệ, có hai cách để giải quyết vấn đề này.

Một là sử dụng assertRaises của Django (thực sự từ unittest / unittest2):

def mytest(self):
    self.assertRaises(FooException, Thing, name='1234')

Điều này không thành công trừ khi Thing (name = '1234') làm tăng lỗi FooException. Một cách khác là bắt ngoại lệ mong đợi và tăng một ngoại lệ nếu nó không xảy ra, như thế này:

def mytest(self):
    try:
        thing = Thing(name='1234')
        self.fail("your message here")
    except FooException:
        pass

Rõ ràng, thay thế FooException bằng cái mà bạn mong muốn nhận được từ việc tạo đối tượng với một chuỗi quá dài. Lỗi xác nhận?

Tùy chọn thứ ba (như Python 2.7) là sử dụng assertRaises như một trình quản lý ngữ cảnh, làm cho mã sạch hơn, dễ đọc hơn:

def mytest(self):
    with self.assertRaises(FooException):
        thing = Thing(name='1234')

Đáng buồn thay, điều này không cho phép các thông báo lỗi kiểm tra tùy chỉnh, vì vậy hãy ghi lại các bài kiểm tra của bạn tốt. Xem https://hg.python.org/cpython/file/2.7/Lib/unittest/case.py#l97 để biết thêm chi tiết.


70
2017-11-18 20:32



Tôi sử dụng assertRaises khá thường xuyên. - Matthew Schinckel
Tôi làm như vậy, nhưng cú pháp có một số nhận được sử dụng để. - GDorn
trong phiên bản python 2.6.5, chữ ký chức năng là khác nhau. Sao chép từ mã python: def failUnlessRaises(self, excClass, callableObj, *args, **kwargs) và sau đó callableObj(*args, **kwargs). Vì vậy, trong ví dụ của bài đăng này, nó sẽ là self.assertRaises(FooException, Thing, name='1234'). Tôi không chắc tại sao chữ ký chức năng của tôi lại khác, nhưng đó là những gì hiệu quả. - Alexander Bird
Trên thực tế, tôi nghĩ rằng nó đã được như vậy một thời gian. Tôi chỉ nhận được sig ngược. Tôi sẽ cập nhật câu trả lời của mình. - GDorn
assertRaises cũng có thể được sử dụng trong câu lệnh có dạng như sau: with self.assertRaises(FooException): thing = Thing(name='1234') - antonagestam


Tôi hiện đang sử dụng expectedFailure trang trí từ unittest. Điều đó hoạt động như được quảng cáo: Không khi không có lỗi, chuyển khi có lỗi.

tôi sử dụng expectedFailure để xác minh rằng tùy chỉnh của tôi khẳng định-thói quen thực sự làm việc và không chỉ rubberstamp tất cả mọi thứ OK.

import unittest
from django.test import TestCase

class EmojiTestCase(TestCase):

    @unittest.expectedFailure
    def testCustomAssert(self):
        self.assertHappyFace(':(') # must fail.

Nhưng in một thông báo cảnh báo trong khi thử nghiệm. Tôi sử dụng nó với Django và Nose. Cái nào khác cũng đã thấy.

/usr/lib64/python3.4/unittest/case.py/25: RuntimeWarning: TestResult không có phương thức addExpectedFailure, báo cáo là pass     RuntimeWarning)

Tôi đến đây để tìm một giải pháp tốt hơn, nhưng không tìm thấy. Vì vậy, ít nhất tôi cũng muốn nói với những người khác rằng tôi đã làm việc với tôi.


2
2018-02-28 09:47





Một cái gì đó như thế này sẽ làm việc:

thing = Thing.objects.create(name='1234')  
# not sure if you need here .get() or if. create() truncates the field on its own
self.assertEqual(thing.name, '123') # or: self.assertEqual(len(thing.name), 3)

- nhưng thử nghiệm như vậy có vẻ lạ :-)

Ngoài ra, lưu ý rằng MySQLdb backend sẽ tăng cảnh báo exception để thông báo cho bạn về việc cắt xén chuỗi, vì vậy bạn có thể muốn kiểm tra nó bằng assertRaises.


0
2017-11-18 18:29