2

I have a module A who looks like the following:

import unittest2

def check_function():
    # performs actions and returns True or False
    return smth

CHECK = check_function()

class A(unittest2.TestCase):

    @unittest2.skipIf(CHECK, "skip message 1")
    def test_1(self):
        # test check

    @unittest2.skipIf(CHECK, "skip message 2")
    def test_2(self):
        # test check

Module A is being imported by another module, called B. When is the global variable CHECK initialized? At import? At class instantiation?

I need to have the CHECK variable set each time class A is called. How can I achieve this?

EDIT: I have tried the following (which might be what I am looking for), but CHECK is not set at all inside setUpClass (it stays False, no matter what check_function() returns).

import unittest2

def check_function():
    # performs actions and returns True or False
    return smth

CHECK = False

class A(unittest2.TestCase):

    global CHECK

    @classmethod
    def setUpClass(cls):
        CHECK = check_function()

    @unittest2.skipIf(CHECK, "skip message 1")
    def test_1(self):
        # test check

    @unittest2.skipIf(CHECK, "skip message 2")
    def test_2(self):
        # test check

Any ideas of how to set CHECK once, each time the test is invoked?

EDIT: check_function() is certainly called once, but I don't understand why unittest2.skipIf does not "see" the value set in setUpClass, and sticks to the False value set at declaration?

SOLUTION:

The final skeletopn of the code looks like this:

import unittest2

def check_function():
    # performs checks and returns True or False
    return smth

class A(unittest2.TestCase):

    CHECK = check_function()

    @unittest2.skipIf(CHECK, "skip message 1")
    def test_1(self):
        # do tests
        self.assertTrue(True)

    @unittest2.skipIf(CHECK, "skip message 1")
    def test_2(self):
        # do tests
        self.assertTrue(True)
Alex
  • 681
  • 2
  • 9
  • 18
  • 1
    The variable is available immediately after the line was interpreted. A program usually runs from top to bottom. – Niklas R Oct 11 '12 at 11:09
  • Why don't you use a debugger to step through the code and see for yourself? Also, as a matter of terminology, you do not "call" a class (unless it has a `__call__` method). You call methods, functions, lambdas, and [other callables](http://stackoverflow.com/questions/111234/what-is-a-callable-in-python). – Matt Ball Oct 11 '12 at 11:09
  • True, no class can be called. But in this case A is instantiated and since ALL its methods are called (using nose let's say), can't we extend this terminology to the whole class? – Alex Oct 11 '12 at 11:17
  • @Alex Nope, not unless you define what you mean by that, and at that point you can just use the definition instead of abusing a well-defined term. So when precisely do you want the CHECK variable to be set? Every time a test is invoked? –  Oct 11 '12 at 11:24
  • Yes, exactly. I want to have CHECK variable set each time a test is invoked. – Alex Oct 11 '12 at 11:27
  • @Matt Ball ok, I misused the term 'call' and I admit this is a bad choice on internet since it can be misinterpreted – Alex Oct 11 '12 at 11:30
  • @MattBall Having a `__call__` enables to call the instances, not the class. – glglgl Oct 11 '12 at 11:41

3 Answers3

2

You CHECK variable initialized when you module import first time.

See example. I have module mymodule.py which contains:

print "i am mymodule"

And some anothermodule.py:

print "first"

import mymodule

print "second"

import mymodule

print "third"

When I run another module.py I get:

first
i am mymodule
second
third

Invitialization variables in python is the same command as print and will be performed line-by-line at the time of the interpreter will be the first time in your module.

More clear example.

mymodule.py:

def get_a():
    print 'init a'
    return 42

def get_b():
    print 'init b'
    return 20

a = get_a()
b = get_b()

anothermodule.py

from mymodule import a
print "a =", a
print "b =", b

Result:

init a
init b
a = 42
Traceback (most recent call last):
  File "anothermodule.py", line 3, in <module>
    print b
NameError: name 'b' is not defined
defuz
  • 26,721
  • 10
  • 38
  • 60
  • So global variables are "known" and global within multiple modules, right? – Alex Oct 11 '12 at 11:20
  • 1
    They are only 'global' to the module in which they are written, they don't automatically become global everywhere else. – Burhan Khalid Oct 11 '12 at 11:22
  • 1
    @Alex There's actually no such thing as a global variable, there are only module-level variables. But since any module can import any other module and thus get access to stuff in that module, it's practically like you describe, except that using the same name in multiple modules doesn't cause problems -- praise namespaces. –  Oct 11 '12 at 11:23
  • I forgot to mention that they become "known" after the module in which they are declared is imported into the other(s). – Alex Oct 11 '12 at 11:25
1

Your 2nd approach looks like a starting point. But you are running into timing problems.

On one hand, you want that value to be present on applying the decorators (that's VERY early), on the other hand, you setting it when calling setUpClass(). That is probably quite late.

The only option seems to me to do

class A(unittest2.TestCase):
    CHECK = check_function()

    @unittest2.skipIf(CHECK, "skip message 1")
    def test_1(self):
        # test check

    @unittest2.skipIf(CHECK, "skip message 2")
    def test_2(self):
        # test check

where CHECK is initialized earlier than used.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • if I do what you said and declare it outside the class, it keeps that value when unittest2.skipIf is called; if I do what you said and do not declare it outside the class, I get this error: NameError: name 'CHECK' is not defined. Either way it does not work. – Alex Oct 11 '12 at 12:05
  • 1
    @Alex Updated the answer because of timing issues. – glglgl Oct 11 '12 at 12:13
  • thanks a million! It was a timing issue indeed. Looks like check_function() is called only once, before calling the decorators. – Alex Oct 11 '12 at 12:19
0

What about this:

import unittest2

def check_function():
  # performs actions and returns True or False
  return smth

CHECK = None

class A(unittest2.TestCase):
    def __init__(self,*args,**kwargs):
        CHECK=check_funtion
        super(A,self).__init__(*args,**kwargs)

    @unittest2.skipIf(CHECK, "skip message 1")
    def test_1(self):
        # test check

    @unittest2.skipIf(CHECK, "skip message 2")
    def test_2(self):
        # test check
schacki
  • 9,401
  • 5
  • 29
  • 32