28

When I create a unittest.TestCase, I can define a setUp() function that will run before every test in that test case. Is it possible to skip the setUp() for a single specific test?

It's possible that wanting to skip setUp() for a given test is not a good practice. I'm fairly new to unit testing and any suggestion regarding the subject is welcome.

Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
7hi4g0
  • 3,729
  • 4
  • 22
  • 32
  • 1
    An example use-case: I am functional testing an application which uses an external API. Nearly every method requires `setUp()` to authenticate with the server, except if I were testing the `login()` function itself. – Stevoisiak Feb 05 '18 at 20:21
  • Related on [softwareengineering.se]: [*Is it possible to have setup and tear down methods run only for specific unittests?*](https://softwareengineering.stackexchange.com/q/232243/168744) – Stevoisiak Feb 05 '18 at 20:31
  • Related to: [Python unittest, do something only if test fails](https://stackoverflow.com/questions/30647772/python-unittest-do-something-only-if-test-fails/) – Evandro Coan May 01 '19 at 19:31
  • A `@unittest.skip_setup` decorator would be nice to have, similar to [@unittest.skip](https://docs.python.org/3/library/unittest.html#unittest.skip). I guess [victortv's answer](https://stackoverflow.com/a/56710965) is the closest thing. – djvg Jun 09 '21 at 15:53

4 Answers4

17

You can use Django's @tag decorator as a criteria to be used in the setUp method to skip if necessary.

# import tag decorator
from django.test.utils import tag

# The test which you want to skip setUp
@tag('skip_setup')
def test_mytest(self):
    assert True

def setUp(self):
    method = getattr(self,self._testMethodName)
    tags = getattr(method,'tags', {})
    if 'skip_setup' in tags:
        return #setUp skipped
    #do_stuff if not skipped

Besides skipping you can also use tags to do different setups.

P.S. If you are not using Django, the source code for that decorator is really simple:

def tag(*tags):
    """
    Decorator to add tags to a test class or method.
    """
    def decorator(obj):
        setattr(obj, 'tags', set(tags))
        return obj
    return decorator
Ixio
  • 517
  • 6
  • 21
victortv
  • 7,874
  • 2
  • 23
  • 27
14

From the docs (italics mine):

unittest.TestCase.setUp()

Method called to prepare the test fixture. This is called immediately before calling the test method; any exception raised by this method will be considered an error rather than a test failure. The default implementation does nothing.

So if you don't need any set up then don't override unittest.TestCase.setUp.

However, if one of your test_* methods doesn't need the set up and the others do, I would recommend putting that in a separate class.

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
  • 3
    i believe @7hi4g0 has like 5 tests, and out of those 5 tests, he doesnt want the setup to run on one of them. INSTEAD of writing two seperate tests, one with setup one without – TehTris Jun 07 '13 at 20:03
  • 1
    @TehTris: In that case, it should be a separate test case and not mixed in with the others. – Steven Rumbalski Jun 07 '13 at 20:05
  • 3
    i agree 100%, but im sure there is at least one legit reason out there for this to be be able. – TehTris Jun 07 '13 at 20:08
  • My problem is like @TehTris described. Probably it's better to have them in different classes. As I said, I'm fairly new to unit testing. Thanks for the help ;) – 7hi4g0 Jun 07 '13 at 20:39
  • I just decided to not have a setup and embed each variant of the setup in the test. I'm not sure if that is the best way or not, but the setup was only 2 lines. – Cephlin Jun 09 '16 at 14:30
  • While rare, there are some legitimate use cases for skipping setup. I have 20 unittests for an application which authenticates with an external API. However, I have a single test which tests the authentication process itself. – Stevoisiak Feb 05 '18 at 20:28
9

In setUp(), self._testMethodName contains the name of the test that will be executed. It's likely better to put the test into a different class or something, of course, but it's in there.

djvg
  • 11,722
  • 5
  • 72
  • 103
user3757614
  • 1,776
  • 12
  • 10
2

It's feasible for user to skip some test methods based on its docstring, take an example as below:

import unittest

class simpleTest2(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      if name == "add":
         self.a = 10
         self.b = 20
         print name, self.a, self.b
      if name == "sub":
         self.a = 50
         self.b = 60
         print name, self.a, self.b
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def testadd(self):
      """add"""
      result = self.a+self.b
      self.assertTrue(result == 30)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)

if __name__ == '__main__':
   unittest.main()

If the setup() method is used for most test methods except one exception, you can return directly if that method is met based on the comparison of docstring.

Eugene
  • 10,627
  • 5
  • 49
  • 67