Python unit test that uses an external data file

I have a Python project that I am working on in Eclipse and I have the following file structure:

/Project
    /projectname
        module1.py
        module2.py 
        # etc.
    /test
        testModule1.py
        # etc.
        testdata.csv

In one of my tests, I instantiate one of my classes, providing 'testdata.csv'as a parameter. This object executes open('testdata.csv')and reads the contents.

If I run only one test file with unittest, everything works and the file will be found and read correctly. However, if I try to run all my unit tests (for example, by right-clicking on a directory testand not a separate test file), I get an error that the file was not found.

Is there any way around this (other than providing an absolute path that I would rather not do)?

+15
4

THIS_DIR = os.path.dirname(os.path.abspath(__file__))

. , : , .

- ( ):

my_data_path = os.path.join(THIS_DIR, os.pardir, 'data_folder/data.csv')

, :

my_data_path = os.path.join(THIS_DIR, 'testdata.csv')
+19

Unit test, , , . , , , csv .

open - .

from unittest import TestCase
from unittest.mock import patch, mock_open

from textwrap import dedent

class OpenTest(TestCase):
    DATA = dedent("""
        a,b,c
        x,y,z
        """).strip()

    @patch("builtins.open", mock_open(read_data=DATA))
    def test_open(self):

        # Due to how the patching is done, any module accessing `open' for the 
        # duration of this test get access to a mock instead (not just the test 
        # module).
        with open("filename", "r") as f:
            result = f.read()

        open.assert_called_once_with("filename", "r")
        self.assertEqual(self.DATA, result)
        self.assertEqual("a,b,c\nx,y,z", result)
+11

, - .

, . .

, . .

( )

, open std python.

class UsesOpen(object):
  def some_method(self, path):
    with open(path) as f:
      process(f)

# how the class is being used in the open
def main():
  uses_open = UsesOpen()
  uses_open.some_method('/my/path')

open , - () test mocking-framework, Dunes. :

: ( )

-:

class UsesOpen(object):
  def __init__(self, myopen):
    self.__open = myopen

  def some_method(self, path):
    with self.__open(path) as f:
      process(f)

# how the class is being used in the open
def main():
  uses_open = UsesOpen(open)
  uses_open.some_method('/my/path')

open (Constructor Dependency Injection).

open :

EXAMPLE_CONTENT = """my file content
as an example
this can be anything"""

TEST_FILES = {
  '/my/long/fake/path/to/a/file.conf': EXAMPLE_CONTENT
}

class MockFile(object):
  def __init__(self, content):
    self.__content = content
  def read(self):
    return self.__content

  def __enter__(self):
    return self
  def __exit__(self, type, value, tb):
    pass

class MockFileOpener(object):
  def __init__(self, test_files):
    self.__test_files = test_files

  def open(self, path, *args, **kwargs):
    return MockFile(self.__test_files[path])

class TestUsesOpen(object):
  def test_some_method(self):
    test_opener = MockFileOpener(TEST_FILES)

    uses_open = UsesOpen(test_opener.open)

    # assert that uses_open.some_method('/my/long/fake/path/to/a/file.conf')
    # does the right thing

Pro/Con

Pro Dependency Injection

Con Dependency Injection

  • ,
  • , @patch
  • - -
0

, .

-3
source

Source: https://habr.com/ru/post/1606991/


All Articles