Chạy setUp chỉ một lần cho một tập hợp các bài kiểm tra tự động


81

Phiên bản Python của tôi là 2.6.

Tôi chỉ muốn thực thi phương thức setUp thử nghiệm một lần vì tôi thực hiện những thứ cần thiết cho tất cả các thử nghiệm.

Ý tưởng của tôi là tạo một biến boolean sẽ được đặt thành 'true' sau lần thực thi đầu tiên và sau đó vô hiệu hóa nhiều lệnh gọi đến phương thức thiết lập.

class mySelTest(unittest.TestCase):
    setup_done = False

    def setUp(self):
        print str(self.setup_done)
            
        if self.setup_done:
            return
        self.setup_done = True
        print str(self.setup_done)

Đầu ra:

False

True

--- Test 1 ---

False

True

--- Test 2 ---

Tại sao cái này không hoạt động? Tôi có bỏ lỡ điều gì không?


6
Unittest tạo ra các trường hợp riêng biệt cho mỗi bài kiểm tra
David Robinson

2
Đừng làm điều này. Thực hiện một số cơ chế khác. Nhưng đừng cố gắng thay đổi ý nghĩa của setUp.
David Heffernan

Câu trả lời:


113

Bạn có thể sử dụng setUpClassđể xác định các phương thức chỉ chạy một lần trên mỗi testsuite.


Cảm ơn vì đã trả lời. Vì tôi đang sử dụng Python 2.6.6 nên không có sẵn setUpClass.
Kesandal

2
@JohnM .: Bạn có thể tải xuống gói backport unittest2 và tải tất cả nội dung mới trên python-dist cũ hơn của mình.
Macke

Câu hỏi liên quan đến Python 2, nhưng vì câu trả lời cũng hợp lệ cho Python 3 nên tôi đã thay đổi URL vì Python 2 không được dùng nữa.
CharlesB

64

Câu trả lời của Daniel là đúng, nhưng đây là một ví dụ để tránh một số sai lầm thường gặp tôi tìm thấy, chẳng hạn như không gọi super()trong setUpClass()khi TestCaselà một lớp con của unittest.TestCase(như trong django.testhoặc falcon.testing).

Tài liệu cho setUpClass()không đề cập rằng bạn cần phải gọi super()trong những trường hợp như vậy. Bạn sẽ gặp lỗi nếu không, như đã thấy trong câu hỏi liên quan này .

class SomeTest(TestCase):
    def setUp(self):
        self.user1 = UserProfile.objects.create_user(resource=SomeTest.the_resource)

    @classmethod
    def setUpClass(cls):
        """ get_some_resource() is slow, to avoid calling it for each test use setUpClass()
            and store the result as class variable
        """
        super(SomeTest, cls).setUpClass()
        cls.the_resource = get_some_resource()

1
Lưu ý rằng điều này chỉ có liên quan khi TestCaselà một lớp con của unittest.TestCase.
EliadL

3

Nếu bạn đã kết thúc ở đây vì cần tải một số dữ liệu để thử nghiệm ... thì theo điều kiện bạn đang sử dụng Django 1.9+, vui lòng truy cập setUpTestData :

class MyTests(TestCase):

    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.foo = Foo.objects.create(bar="Test")

    def test1(self):
        self.assertEqual(self.foo.bar, 'Test') 

2

Đừng cố gắng loại bỏ các cuộc gọi đến setUp, chỉ cần gọi nó một lần.

Ví dụ:

class MyClass(object):
    ...

def _set_up():
    code to do one-time setup

_set_up()

Điều này sẽ gọi _set_up () khi mô-đun được tải lần đầu tiên. Tôi đã định nghĩa nó là một hàm cấp mô-đun, nhưng bạn cũng có thể biến nó thành một phương thức lớp của MyClass.


2

Đặt tất cả mã bạn muốn thiết lập một lần bên ngoài mySelTest.

setup_done = False

class mySelTest(unittest.TestCase):

    def setUp(self):
        print str(setup_done)

        if setup_done:
            return

        setup_done = True
        print str(setup_done)

Một khả năng khác là có một lớp Singleton mà bạn khởi tạo setUp(), lớp này sẽ chỉ chạy __new__mã một lần và trả về cá thể đối tượng cho phần còn lại của các lệnh gọi. Hãy xem: Có cách nào đơn giản, thanh lịch để định nghĩa singleton không?

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(
                            cls, *args, **kwargs)
            # PUT YOUR SETUP ONCE CODE HERE!
            cls.setUpBool = True

        return cls._instance

class mySelTest(unittest.TestCase):

    def setUp(self):
        # The first call initializes singleton, ever additional call returns the instantiated reference.
        print(Singleton().setUpBool)

Tuy nhiên, cách của bạn cũng hoạt động.


2

setup_done là một biến lớp, không phải là một biến cá thể.

Bạn đang tham chiếu nó như một biến phiên bản:

self.setup_done

Nhưng bạn cần tham chiếu nó như một biến lớp:

mySelTest.setup_done

Đây là mã đã sửa:

class mySelTest(unittest.TestCase):
    setup_done = False

    def setUp(self):
        print str(mySelTest.setup_done)

        if mySelTest.setup_done:
            return
        mySelTest.setup_done = True
        print str(mySelTest.setup_done)

1

Tôi đang sử dụng Python 3 và nhận thấy rằng clstham chiếu cũng có sẵn trong setupphương thức và do đó, các hoạt động sau đây:

class TestThing(unittest.TestCase):

  @classmethod
  def setUpClass(cls):
    cls.thing = Thing() # the `thing` is only instantiated once

  def setup(self):
    self.thing = cls.thing # ...but set on each test case instance

  def test_the_thing(self):
    self.assertTrue(self.thing is not None)
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.