How does pytest_plugin Global variable works? - python

I was trying to define bunch fixtures in one file say redis.py (abc\plgfix\redis.py) and use them in my test cases (abc\common\test_file.py) via pytest_plugin. While doing that I notice test cases couldn't see fixtures I defined.
My Folder structure is as follows
abc
|
common
|
config.py ( I have defined pytest_plugin=["plgfix.redis"]
test_file.py
plgfix
|
redis.py ( I have defined bunch of fixtures here)
__init__.py
From above illustration
-> plgfix (folder) has my desired file(redis.py) and __init__.py file to
make folder as package.
-> In abc\common\config.py. I have defined pytest_plugin global variable
pytest_plugins = ["plgfix.redis"] #assuming all fixtures in
#redis.py file , available for test cases
-> Now I have created abc\common\test_file.py where I'm using one of the
defined fixture in redis.py (abc\plgfix\redis.py) as follows.
def test_fixtu(fix1):
print ("Hi")
pass
I was getting error as fix1 is not found
Note : I can able to import config file and see contents as 'package', 'spec', 'pytest_plugins'....... (confirming it is not path issue)

According to the pytest docs, the global var is supposed to be either a str or a Sequence[str]. You seem to have assigned a list to it.

Related

Is it right to import variables from __init__ into a unit-test script?

Let's say that we have a directory with the following structure:
tests/
|-- __init__.py
|-- test_foo.py
where package foo is tested. In test_foo.py, variable bar is defined (and modified) to later be used.
Now imagine that instead of one file, we have around 20 test_fooX.py, where bar is initialized in every test.
Is it good practice to initiate bar in __init__.py and import it directly in every test? E.g.
from __init__ import bar
The Zen of python mentions that:
Explicit is better than implicit.
Defining bar in every single script would be what the explicit way. However, importing variables improves the structure of the tests/project.
A real scenario would be a logger (imported from foo), whose logging level needs to be changed; or the location of a specific directory instead of defining it every time.
There's nothing really implicit about __init__.py. A package is a module. Because a package is implemented by a directory containing a file named __init__.py, that file contains the contents of the module tests, with other files implementing submodules belonging to the same package.

Declare a variable across all files in Python

I have a set of Python files as follows:
py-app/
main.py
module1.py
Inside main.py I declare a variable config as follows
config = {"param1": "value1", "param2":"value2"}
How can I make config variable global in order for it to be accessed in module1.py as follows:
Inside module1.py
def foo()
print(config["param1"])
Please see this from the official website:
https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules
What you can do is - create a special module to store all the global variables there and access them by importing the module.
This singleton design pattern is followed and if you modify the state in one file it will be reflected everywhere. It basically works like a session object.
If required, you can initialize the values as well.

What is the scope of imports defined in the package __init__.py file?

For a project I had to switch from C++ to python but I'm having some trouble fully understanding the __init__.py file. I found the following documentation on the __init__.py file:
https://docs.python.org/3/tutorial/modules.html
https://www.pythoncentral.io/how-to-create-a-python-package/
http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html
To get more familiar with the way the __init__.py file works I did some tests in both python 2.7 and 3.6.5. I used the "PythonCentral" test pacakge (see link 2) for this:
Now I understand the following about the __init__.py file:
The __init__.py file executes when a module or subpackage module is imported.
The __init__.py can be used to overload the package __all__ method.
The __init__.py can be used to define the import order
The __init__.py can be used to make classes available on package and subpackage level.
Using the different modules and classes from the scope of my main file seems to go as explained in the documentation. However when trying to use a class that is defined in another subpackage module I run into troubles. In python 2.7 created the following __init__.py file in the subanimals subpackage:
from Mammals import Mammals
print "subpackage __init__.py executed"
Following I created the following code inside the Bird.py module:
class Birds:
def __init__(self):
''' Constructor for this class. '''
# Create some member animals
self.members = ['Sparrow', 'Robin', 'Duck']
def printMembers(self):
print('Printing members of the Birds class')
for member in self.members:
print('\t%s ' % member)
test = Mammals()
test.printMembers
When running the main following main script:
from animals.subanimals import Birds
test = Birds()
test.printMembers()
I keep getting the global name Mammals not defined. I can solve this in python 2.7 by adding from Mammals import Mammals to the top of the Birds.py.
Does the __init__.py only import packages and classes on the scope level of the main script and therefore not inside the Birds.py module or am I doing something else wrong?
Answer to my question can be found in #jonrsharpe 's comment.
Each individual file must be valid on its own, defining all
appropriate imports. init.py is for aggregating multiple files in
a directory into a single module; think of it as grouping and passing
attributes up to the parent, not down to the other files in that
directory.

cross-refence link to a function/class in a different submodule

As a simple example, in the following code of 2 submodules (a.py and b.py in the same directory). The link to the same submodule function :func:`hook` works but not the link cross-referencing to a different moduel, ie, :func:`foo`. I also tried the syntax of :func:`.a.foo` - still does not work. How can I cross reference to a.foo()?
# script a.py
def foo():
'''foo func'''
# script b.py
def hook():
'''hook func'''
def spam():
'''spam func.
:func:`foo`
:func:`hook`
'''
As described in the docs:
Normally, names in these roles are searched first without any further
qualification, then with the current module name prepended, then with
the current module and class name (if any) prepended. If you prefix
the name with a dot, this order is reversed.
In that case, :func:`.a.foo` means an object named a inside of the module b. It will look for b.a.foo function.
You should try :func:`..a.foo`, which will point to b..a.foo, or just a.foo (cannot check that locally now, sorry; but I remember I was using that syntax before).
But note, that a.py & b.py should be the modules, i.e. importable under their name. If they are just the scripts, and located not in a package (no __init__.py files up to the root of the project), there is no way to cross-reference with these roles.
You can try to use :any: role — :any:`foo` — and hope that it will find the object in the general index of the described objects.

How can I uncache imported module in python?

This is really freaking me out. My project looks like this
.
|-- main.py
|-- classes
| |-- __init__.py
| |-- exceptions.py
In those exceptions.py, I initally created one exception called SecurityError:
class SecurityError(Exception):
pass
I included the file in main.py using from classes.exceptions import * and SecurityError normally works when I just raise it.
Afterwards, I also added FilesystemError, but whenever using it, I get:
global name 'FilesystemError' is not defined
I tried to delete *.pyc files in classes directory but it has no effect. Any changes to the exceptions.py take no effect, including any ridiculous ones that make the file invalid:
class FileFOO BAR BAZ systemError(Exception):
pass
class SecurityErr foo bar bazor(Exception):
pass
The program still behaves as if the file never changed since the first run. I don't think this behaviour has anything to do with intuitive programming - if there's cache, it should be in that directory.
I am running the python directly from command line:
C:\programing\python\MyProject>py -2 main.py
Confusing errors of the form global name 'XXX' is not defined typically mean that you are shadowing a standard library module. You must rename your exceptions module.

Categories