How can I decorate a Python unittest method to skip if a property I've previously evaluated isn't True?

You could write your own decorator to which you pass the name of the flag:

def skipIfTrue(flag):
    def deco(f):
        def wrapper(self, *args, **kwargs):
            if getattr(self, flag):
                self.skipTest()
            else:
                f(self, *args, **kwargs)
        return wrapper
    return deco

Then in your class you would define the test method like this:

@skipIfTrue('isOnline')
def test_thing(self):
    print("A test")

Whether this is better than just checking in the method depends on the situation. If you are doing this with many methods, it could be better than writing the check in every one. On the other hand, if you're doing that, you might want to group them together and do one check to skip the entire suite.


If you can move the isOnline test outside of your setUp method, then that's a solution:

IS_ONLINE = i_am_online()

class MyTestCase(unittest.TestCase):
  @unittest.skipUnless(IS_ONLINE, "Not online")
  def test_xyz(self):
    # do a test that relies on being online

Another (more elegant option) would then be:

import unittest

def skipWhenOffline():
    if not i_am_online():
         return unittest.skip("Not online")
    return unittest._id

class MyTestCase(unittest.TestCase):
  @unittest.skipWhenOffline()
  def test_xyz(self):
    # do a test that relies on being online

However if this isn't possible for you, then there isn't a more elegant solution than to somehow use skipTest().

skipIf and skipUnless are evaluated at class declaration time (they set a __unittest_skip__ attribute on your method to indicate it shouldn't run, which is later looked at prior to running the test). Your setUp method just hasn't run yet at that point.