2

Lets say I have a simple class object that looks like some sort of Counter (of course it has other functions but it's out of scope for this question):

from collections import Counter

class Vocabulary:
    def __init__(self, words):
        self.vocab = Counter(words)

And adding the Vocabulary class to a unittest, I could have use the setUpClass classmethod as such:

import unittest

class VocabularyTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.vocab = Vocabulary(["z", "a", "b", "c", "f", "d", "e", "g", "a", "d", "b", "e", "w"])


    def test_counts_set_correctly(self):
        self.assertEqual(cls.vocab["a"], 2)

Or I could have just use self:

class VocabularyTests(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super(VocabularyTests, self).__init__(*args, **kwargs)
        self.vocab = Vocabulary(["z", "a", "b", "c", "f", "d", "e", "g", "a", "d", "b", "e", "w"])

    def test_counts_set_correctly(self):
        self.assertEqual(self.vocab["a"], 2)

And both of the above would work fine. But what if I've a sort of unpythonic pattern:

import unittest

class VocabularyTests(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        self.vocab = Vocabulary(["z", "a", "b", "c", "f", "d", "e", "g", "a", "d", "b", "e", "w"])


    def test_counts_set_correctly(self):
        self.assertEqual(self.vocab["a"], 2)

According to What is the 'cls' variable used for in Python classes?, it's just a coding convention but is there any difference between the 3rd version of the unittest with @classmethod with the usage of self.vocab and the first two more idiomatic tests?

alvas
  • 115,346
  • 109
  • 446
  • 738

1 Answers1

4

For unittest.TestCase subclasses, don't do any test setup in __init__. That's not what it's for. If you want the setup to be executed once-per test method, put it here:

def setUp(self):
    ...

If you want setup to be executed once per test class, put it here:

@classmethod
def setUpClass(cls):
    ...

Finally let's address a misconception. There is technically no difference between this:

@classmethod
def setUpClass(cls):
    ...

And this:

@classmethod
def setUpClass(self):
    ...

The second one is just a more confusing/bad way of writing the first.

wim
  • 338,267
  • 99
  • 616
  • 750