I just encountered a problem with @unittest.skipIf(expression). Well, the problem is that if I use variable in decorator that is declared and assigned a value before starting the test, and during the test the value of this variable is changed the effect is such that decorator includes the old value. For example:
class Settings(object):
flag=False
class TestCase(object):
# during the test variable is changed (in this module or another)
Settings.flag=True
@unittest.skipIf(Settings.flag==True)
def test_something(self):
...
Value of Settings.flag can be changed in another module or this module (this doesn’t matter). In both cases condition Setting.flag==True during call test_something still takes the ‘False’ value although it was already changed to ‘True’ value. It is very strange and I admit that I don’t understand how this mechanism works. It seems that the value used in this decorator can’t be changed during the test. Maybe there is some other interesting way to skip the test at the time of a particular condition, which may change during the test. Does anyone have an idea how to approach this problem?
Yes, this is expected behavior. Function arguments are evaluated when the function is called. The decorator is a function that’s called when the function being decorated is defined. Therefore, the flag is tested when the decorated function is defined. The decorator has no way to know what the test even was; it only sees
TrueorFalse(or more likely, truthiness or falsiness) so it can’t store the condition away for later evaluation.For
skipIf()to work as you want, it would need to take a function (e.g.lambda: Settings.flag==True) rather than a Boolean value. Then it would be able to evaluate this condition later, when the decorated function is actually called. But it doesn’t actually work that way. (This would probably be an easy enhancement to add, though.)You may be able to work around this by not importing the module containing your unit tests until after the value of
Settings.flaghas been established. This will defer the definition (and thus the decoration) of your test functions until then, and the decorator will have access to the desired value of the flag. Not knowing how your code is structured, I don’t know whether this is practical for you.Additionally, something looks fishy about
Settings.flag==True… can’t quite put my finger on it… 😉