3

Got 2 files :

new_project
├── Main.py
└── testing.py

I run:

$ cd new_project
$ python -m unittest testing.py

My whole testing file is :

import unittest
from Main import Square


class TestSquare(unittest.TestCase):

    def test_init(self):
        self.assertEqual(Square(0,0).center, Point(50,50))
        print("test")

With Square being the first class in my Main.py file. Main.py is composed like below :

import sys
import math
import random


def d_print(message):
    print(message, file=sys.stderr)


class Square:
    # on découpe le terrain en square et on les marque avec top right corner of square
    def __init__(self, x, y):
        self.xtr = x
        self.ytr = y
        self.size = 100
        self.explored = False
        self.center = Point(x+50, y+50)

while True:
    # do stuff every turn
    x, y, value = [int(j) for j in input().split()]

The code inside the while loop will be called every turn by a game simulator. The simulator provides inputs.

When I run the unittest command line, it actually waits for inputs

If I remove the import Main and the TestFixture on Square, the unittest passes. I tried several configurations and I can't manage to import Square for the test without having the while loop being start.

So when I import only a class from Main.py, it still runs the code outside the class. It's boggling my mind. Here is the link to import mechanism and I don't get why it runs the code and how to prevent it https://docs.python.org/3/reference/import.html

Since the game simulation is not in my control, I can't change much about the way Main.py is written. My only idea is to split the loop and the classes in two files for dev and testing ; when submitting I would have to concatenate the files back into one.

So (thanks for reading so far ;) :

  • why are unittest/import working that way ?
  • any idea on how to solve it ? (I am trying the split files idea right now, will report back)
Poutrathor
  • 1,990
  • 2
  • 20
  • 44

1 Answers1

3

To avoid running the loop, when the file is imported as a module, write it this way:

if __name__ == "__main__":
    while True:
        # do stuff every turn
        x, y, value = [int(j) for j in input().split()]

The answer is simple, when you import the module the code on that file will be executed, which will cause the loop to run and the execution to be blocked on the input(). For more details about how it works please read this answer with a detailed explanation

dethos
  • 3,336
  • 1
  • 15
  • 15
  • Why does import execute the code ? Isn't it dangerous ? if someone add code to a module for example ? – Poutrathor Nov 10 '18 at 18:54
  • it does work ! thanks for the tip :) I tried to us `if != main: sys.exit()` to avoid having a lot of code at an indentation of 1 but that failed since it's executed before the tests. Any syntax I could use to avoid the dread indent many code lines ? – Poutrathor Nov 10 '18 at 19:35
  • This condition on the module level is the standard way of doing the separation between the cases when a file is executed vs when it is imported in python. I did not understand what you tried to achieve with that line. – dethos Nov 11 '18 at 19:08