1

Background: I'm trying to reduce the time it takes for my tests to complete running.

I learned recently that when the Python interpreter loads a file, it executes all the code it finds therein. (Ref: https://stackoverflow.com/questions/419163/what-does-if-name-main-do)

Is there a way to prevent certain parts of the file from being executed by the interpreter ? Reason is, I have a script that creates a session and assigns that to a class attribute. The script looks something like this.

 def login():
     // Gets auth session from an api. This takes some seconds.
     return // session

 class Something(object):
     class_session = login()

Now I tried to mock this login process but then, when I run my unit tests (I'm using nose btw), I think Python reads, immediately executes this script and then tries to create a session before it gets to mock the method. This takes a couple of seconds and my tests subsequently take longer to complete running (Please correct me if this is not the flow).

  • Is there a way I can prevent Python from executing the script when it reads it (without wrapping the code in a function)?
  • If so, what is the most Pythonic way to handle this?
  • Also, how long should a well written test take to run by default. I think this should be less than 1 second (Not sure where I got that impression from tho).

Please share some insights, thanks.

Community
  • 1
  • 1
mfalade
  • 1,647
  • 2
  • 17
  • 16

2 Answers2

2

You need to write your code in such a manner that it does not do too much upon simply declaring things. Only when you explicitly call a function or instantiate a class should your code do "actual work".

class Something(object):
    class_session = login()

This creates a class property class_session, which obviously must happen at the time the class gets defined, else it wouldn't be a class property. This necessitates the execution of login() at this time.

To do this properly only when a new object is instantiated, move this code into the constructor and make it an instance property:

class Something(object):
    def __init__(self):
        self.class_session = login()

Whether it makes more sense to have something be a class property or an instance property is impossible to say without knowing what this code is supposed to do. However, you really should delay all "real work" until a function is explicitly called; triggering a login upon importing the module is madness.

deceze
  • 510,633
  • 85
  • 743
  • 889
1

To keep login() from being hit when the file is imported it will need to be moved out of the class attribute space. You can do this by placing it in a method like below:

def login():
    // Gets auth session from an api. This takes some seconds.
    return // session

class Something(object):
    class_session = None

    def __init__(self):
        if Something.class_session is None:   # or self.__class__.class_session
            Something.class_session = login()

Something.class_session = login() needs to be within a function or method to prevent it from being run on import. The way it is written above, login() will be executed the first time a Something() is created.

See answers here for a little more about what is run when the module is imported.

MrAlexBailey
  • 5,219
  • 19
  • 30