Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python, importing modules for testing

Tags:

python

import

I am having a very hard time trying to set up a simple test.

My project structure is as follows:

project:
   models:
      __init__.py
      user.py
      constants.py
      test:
         test.py

I want to test user.py py running test.py.

user.py

from sqlalchemy import Column, Integer, String, Text
from sqlalchemy.orm import relationship
from .models.constants import *
from .models import Base

class User(Base):
    __tablename__ = 'users'

    uid = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String, nullable=False)
    email = Column(String, nullable=False)
    picPath = Column(String, unique=True)
    description = Column(Text)

    def __repr__(self):
        return "<User(uid=%s, name=%s)>" %(self.uid, self.name)

test.py

from ..user import User, Group

def _TestUser():
    TEST_DB_URI = "postgresql://project:password@localhost:5432/projectdbtest"
    SessionMaker = sessionmaker()
    engine = create_engine(TEST_DB_URI)
    SessionMaker.configure(bind=engine)

    session = SessionMaker()
    user = User("test subject", "[email protected]", "~/testsubject.jpg", "I am a test subject")
    session.add(user)
    session.commit()

However, I am getting the following error when I run python3 -m test.py:

SystemError: Parent module '' not loaded, cannot perform relative import

I think I might have to add the modules package to the python path?

like image 329
mrQWERTY Avatar asked Feb 25 '16 19:02

mrQWERTY


People also ask

How do I import a test module in Python?

You should import the module normally in the test_module.py (e.g. from package import module ). Then run the tests by running nosetests in the project folder. You can also run specific tests by doing nosetests tests/test_module.py .

How do you import module in Python?

Importing Modules To make use of the functions in a module, you'll need to import the module with an import statement. An import statement is made up of the import keyword along with the name of the module. In a Python file, this will be declared at the top of the code, under any shebang lines or general comments.

Do you need to import Pytest?

pytest looks for a conftest.py module in each directory. If you add your general-purpose fixtures to the conftest.py module, then you'll be able to use that fixture throughout the module's parent directory and in any subdirectories without having to import it.


1 Answers

Here is few things, which have simplified my testing and which work for me very well.

Always test from project root

Initially I was assuming, my test cases shall be usable from whatever directory.

In fact, there is no reason to make test cases flexible in this way and decision to run all tests from project root only strongly simplify the solution.

It might be obvious to many programmers, but to me it was big step towards simplified testing.

Keep test directory separate from package code

Mixing production code with test code seems logical, but soon becomes messy.

Finally I have decided to use separate tests (in plural) directory in the project and it works very well for me.

Advantages are:

  • tests are "close" to pick (see next part related to py.test) and use manually or from other tools like tox.
  • no need to hunt for test directories somewhere in the package directories, they are simply living in separate place
  • feel safe to experiment with tests - because you are out from main code.

Note: try to use always name tests, do not use test. Keeping this simple rule will simplify your work as you will always know the real name of your test directory.

Use pytest testing framework

There are multiple testing frameworks (unittest, nose, nose2, pytest) and in fact all provide the basics you need.

Anyway, I have found pytest (with py.test command) being real fun to use for couple of reasons:

  • can run most tests written in other framework (unittest, nose...)
  • very easy to create first test function.
  • test functions can be kept very simple and excellent fixtures will inject needed values into it. Once you try it, you will not use other methods.
  • allows naturally extending the test suite
  • very good to start prototyping your code and evolve to production one:
    • start in test function
    • move out of test function to independent function in the same test file
    • move to external module (and most of your testing code does not change)

Avoid using __init__.py in test suite dir

See Choosing a test layout/import rules for explanation and follow the advice to avoid using __init__.py.

In short, things will be simpler.

Note, that other approaches will work too and are not wrong - I just wanted to share what works very well for me.

like image 173
Jan Vlcinsky Avatar answered Oct 18 '22 21:10

Jan Vlcinsky