1

First of all let me put you in context. My main background is Java and I'm working in Python since 2 months ago. I don't know if the approach it's wrong due to my Java background and in Python has a different solution or it's just a technical ignorance problem.

In Java often you have a packaging structure like:

project
   |___src
        |___main
        |     |___java/MyClass.java
        |     |___resources/properties.file 
        |
        |___test 
              |___java/MyClassTest.java
              |___resources/properties.file 

Thus, when you execute this from tests (with Maven or IDE):

this.getClass().getResourceAsStream(resourcePath);

Either Maven or IDE loads the test path in the classpath, making test resources available rather than the ones within the main package. Conversely, when previous line is executed as main, only the resources within the main path are loaded to the classpath.

My question is: Is there any mechanism in Python to simulate this feature? Does Python have other ways to manage resources depending on the execution path?

Pau Trepat
  • 697
  • 1
  • 6
  • 24
  • So you want the class to behave differently when being tested vs. when it is being run without the test framework? – Alan Hoover Apr 05 '18 at 16:50
  • Not exactly, I want the same behavior. I just want to load the file from different folders depending on if it's run by tests or as "main" – Pau Trepat Apr 05 '18 at 16:52

3 Answers3

2

I think mock might be what you are looking for. It allows for 'mock'ing out external functions to limit the test to strictly the unit under test.

This could mean changing some of the philosophy around some of it. For example, if you want to test that a function is reading a file correctly the filename would get passed to the method as a parameter. In your unit test for the function, pass in a different filename from your test folder.

In another test mock out the open call to the os to check that the method responds as expected when the file is not there, or cannot be opened, or whatever other mis-behaviors you want to test for.

Alan Hoover
  • 1,430
  • 2
  • 9
  • 13
  • We've already considered this workaround, however, due to its increased complexity we though that there might exist another easier approach. – Pau Trepat Apr 05 '18 at 17:14
  • @PauTrepat If your program is structured so that the determination of what file/folder to read is in its own function/method, then just `mock` out that function/method and tell `mock` to return the one that contains your test data. – Alan Hoover Apr 05 '18 at 17:33
  • Thanks! I know how to mock. But mocking implies coupling to implementation and coming from Java we thought maybe could exists an easy (and no coupling) way – Pau Trepat Apr 05 '18 at 17:40
0

No, Python has no deployable like Java has (WAR, JAR, etc...). You will run your code directly from the source, so, just read the file.

In the Java context, you do not have the code when it is deployed. So every resource should be package inside a file (JAR or WAR).

If you want to find the file in the current folder, look this question.

Victor
  • 8,309
  • 14
  • 80
  • 129
  • 2
    I think that the question is how to separate applicative source/resources from test source/resources. Packaging doesn't have any relation with. – davidxxx Apr 05 '18 at 16:46
  • 2
    Sorry but I was actually wondering about any mechanisms to dynamically modify the classpath (or it's equivalent in Python) depending if the code is run by tests or as "main". – Pau Trepat Apr 05 '18 at 16:47
  • You can read the folder based on your environment. I believe this concept os **classpath** does not exists on Python. – Victor Apr 05 '18 at 16:49
  • @davidxxx, the folder structure of a Java project reflects the packaging method form Java. The question is about the differences from Java to Python – Victor Apr 05 '18 at 17:02
  • @Victor Not only the packaging. It reflects the build more generally and the build is not only the packaging of the application. It may be filtering resource, documentation generation, test executing and so for. – davidxxx Apr 05 '18 at 17:06
-1

I don't know very well Python but you are right to ask yourself the question as separating test and application code makes part of good practice to have a robust/reliable application and tests.

The pytest (a known test framework for Python) documentation explains in its best practice guide the two ways (separating and not separating the test code from the application).
Here is the part referencing the isolated layout :

Choosing a test layout / import rules

pytest supports two common test layouts:

Tests outside application code

Putting tests into an extra directory outside your actual application code might be useful if you have many functional tests or for other reasons want to keep tests separate from actual application code (often a good idea):

setup.py
mypkg/
    init.py
    app.py
    view.py 
tests/
    test_app.py
    test_view.py
    ... 

This way your tests can run easily against an installed version of mypkg.

Note that using this scheme your test files must have unique names, because pytest will import them as top-level modules since there are no packages to derive a full package name from. In other words, the test files in the example above will be imported as test_app and test_view top-level modules by adding tests/ to sys.path.

If you need to have test modules with the same name, you might add init.py files to your tests folder and subfolders, changing them to packages:

setup.py 
mypkg/
    ... 
tests/
    init.py
    foo/
        init.py
        test_view.py
    bar/
        init.py
        test_view.py 

Now pytest will load the modules as tests.foo.test_view and tests.bar.test_view, allowing you to have modules with the same name. But now this introduces a subtle problem: in order to load the test modules from the tests directory, pytest prepends the root of the repository to sys.path, which adds the side-effect that now mypkg is also importable. This is problematic if you are using a tool like tox to test your package in a virtual environment, because you want to test the installed version of your package, not the local code from the repository.

In this situation, it is strongly suggested to use a src layout where application root package resides in a sub-directory of your root:

setup.py 
src/
    mypkg/
        init.py
        app.py
        view.py 
tests/
    init.py
    foo/
        init.py
        test_view.py
    bar/
        init.py
        test_view.py 
This layout prevents a lot of common pitfalls and has many benefits, which are better explained in this excellent blog post by Ionel Cristian Mărieș.

https://docs.pytest.org/en/latest/goodpractices.html

davidxxx
  • 125,838
  • 23
  • 214
  • 215