0

I'm trying to use pytest to check a function—here is my code:

# src/return_self.py
def return_self(n):
    return n


# tests/return_self_test.py
import pytest

def test_1():
    value = return_self(1)
    assert value == 1

How do I require in my src file so that I can test it with pytest? I have tried a few things:

1. import return_self
2. from src.return_self import *
3. import sys
   sys.path.append('../src')
4. import imp
   return_self = imp.load_source('return_self', '/source/return_self.py')

I have also tried them with and without __init__.py files in the root and src directories. But each time, I get some variation on the error E ModuleNotFoundError: No module named 'return_self'. How can I require in my file?

achalk
  • 3,229
  • 3
  • 17
  • 37

3 Answers3

3

You can try this approach:

# tests/return_self_test.py

import os
import sys
import pytest

sys.path.insert(1, os.path.join(sys.path[0], '..'))

from src.return_self import return_self

def test_1():
    value = return_self(1)
    assert value == 1
pythad
  • 4,241
  • 2
  • 19
  • 41
  • Thanks, it works! I'm confused though—why does python require 5 lines to import a file? – achalk Jul 08 '17 at 23:01
  • 1
    @adc17, you can import things from directories on the system path, or the current directory, or subdirectories within a package. That why you need to add outer path to your system path in order to make python see your other folders – pythad Jul 08 '17 at 23:05
  • Thank you, so is my way of organising tests unusual? If I'm not following the right conventions please let me know. – achalk Jul 08 '17 at 23:07
  • 1
    @adc17, no, it's a good practice to place all tests in the `tests/` folder and until your module becomes a package, this importing is a little gotcha you need to know – pythad Jul 08 '17 at 23:13
  • Thanks @pythad, one last question. Do you know how this code imports the functions it needs without additional lines? https://github.com/AndyLPK247/automation-panda/tree/master/python-testing-101/example-py-pytest – achalk Jul 08 '17 at 23:29
  • @adc17, yes, they use `python -m ...` to run module inside the package. Take a look at https://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python for a discussion on this topic. – pythad Jul 08 '17 at 23:33
  • Thanks, `python -m pytest` is a great solution. – achalk Jul 09 '17 at 15:55
2

First, you must check that src/ and tests/ are in the same directory, I checked the function importing return_self in return_self_test.py and this is how:

Testpy search for files with test_[prefix] so I recommend changing return_self_test.py to test_return_self.py

# src/return_self.py
def return_self(n):
    return n


# tests/test_return_self.py
import return_self

def test_1():
    value = return_self.return_self(1)
    assert value == 1

Finally, test in cmd (in the correct path) or Pycharm terminal with the following command: py.test -v and voila! It's done (:

I'l Follio
  • 573
  • 1
  • 7
  • 19
2

I will suggest you the setuptools approach (which makes your package distributable :D)

Project files' structure:

.
├── sample
│   ├── __init__.py
│   └── return_self.py
├── setup.cfg
├── setup.py
└── tests
    └── test_return_self.py

where the sample/ directory matches the package's name and also must contain the source.

Minimal setup.py file content:

from setuptools import setup

setup(
    setup_requires=['pytest-runner'],
    tests_require=['pytest'],
    name='sample'
)

Here we are configuring our test environment (you can extend the tests_require variable to include more testing requirements).

setup.cfg file content:

[aliases]
test=pytest

And here we specify we want to run the command pytest every time the developer does: python setup.py test

tests/test_return_self.py

from pytest import *

from sample.return_self import return_self

def test_return_self():
     assert return_self(4) == 4

sample/return_self.py

def return_self(n):
    return n

So, the next thing to do is to run:

python setup.py develop

to make your package available (while running the tests). If you're having problems with permission denied issues: append the --user option to the previous command to instruct python you wanna use the package without root permissions --in short the package will be installed into userland directories.

And finally run the tests using:

python setup.py test

Notes:

  • By using this approach, you'll be able to alter your project code on the fly (python setup.py develop needs to be run just once)
  • No ugly statements to inject the source directory into the current python path.

References:

Integrating with setuptools / python setup.py test / pytest-runner

Building and Distributing Packages with Setuptools

slackmart
  • 4,754
  • 3
  • 25
  • 39