pytest - Override a test funciton defaullt value - pytest

i have a pytest testconf and a test function
i want that when running:
pytest -q -option="choose_a"
it would pass A
and when running
pytest
it would pass B
the problem is that it does not see 'my_param' in fixtures since it has a default parameter. what can I do to make this working and elegant?
my current temp solution (which I don't like) is removing the default value and assign it with an "if" statement in conftest.pytest_generate_tests....pls give me a better one :)
conftest.py:
def pytest_addoption(parser):
parser.addoption("--myoption", action="append", default=[], help="list of choices")
def pytest_generate_tests(metafunc):
if 'my_param' in metafunc.fixturenames:
if 'choose_a' in metafunc.config.option.myoption:
metafunc.parametrize("my_param", ["A"])
mytest.py:
def test_my(my_param='B'):
do_stuff(my_param)

Related

pytest get command line options

I have couple of questions regarding commandline options of pytest
If it is possible to use long names and short names for the same option, for example
parser.addoption('--server', '-srv', dest = 'SERVER')
How to access to commandline option by name, like :
config.option.NAME
def environment_options(parser):
parser.addoption('--server', dest= "SERVER")
#pytest.fixture()
def enfironment_set_up():
if config.option.SERVER == 'some value':
actions
pycharm shows reference unresolved 'config'. Do I need to import something ?
As far as I know (haven't found that in the documentation), it is possible to add a short name, but only one with one upper case letter, e.g.:
def environment_options(parser):
parser.addoption('-S', '--server', dest= "SERVER")
Lowercase letters are reserved for pytest itself, and longer abbreviations are not supported. See also my somewhat related answer.
You can access the option via config in the request fixture:
#pytest.fixture
def enfironment_set_up(request):
if request.config.getoption("SERVER") == 'some value':
actions

py.test: How to avoid naming every test? Generate the test name dynamically

Occasionally I name tests like test_X1, test_X2,...
because
it is always about feature X and
the tests are small and
I don't want a descriptive name that is longer than the test
Especially when things still change a lot I don't want to think of a name at all.
The line where the test resides defines the test in the file.
So how to use the line for the test name?
Here is a way to name the tests dynamically test_<line>.
from inspect import currentframe
def namebyline(f):
line = currentframe().f_back.f_lineno
globals()['test_' + str(line)] = f
#namebyline
def _(): # becomes test_6
assert True
#namebyline
def _(): #becomes test_9
assert False

python click passing multiple key values as options

I am using python-click and I would like to pass values with a format like this
myprogram mycommand --parameter param1=value1 --parameter param2=value2
I was looking at click option documentation but I can't find any construct that could help with this, the only solution I can find is invoking a callback function and check that the string is properly constructed <key>=<value>, then elaborate the values properly.
Nothing bad in that solution, but I was wondering if there is a more elegant way to handle this since the pattern looks to be common enough.
So, I've had a go at it. I've managed to do it the following ways.
Firstly, I've tried this, though it doesn't satisfy the --parameter criteria.
#click.command("test")
#click.argument("args", nargs=-1)
def test(args):
args = dict([arg.split("=") for arg in args])
print(args)
so when invoking like test param1=test1 param2=test the output is:
{'param1': 'test1', 'param2': 'test2' }
Secondly, I thought about a multiple option, combined with a variadic argument, which seems to be closer to your requirements:
test -p param1=test -p param2=test
#click.command("test")
#click.option('-p', '--parameter', multiple=True)
#click.argument("args", nargs=-1)
def test(*args, **kwargs):
param_args = kwargs['parameter']
param_args = dict([p.split('=') for p in param_args])
print(param_args)
if __name__ == '__main__':
test()
The output will be the same as the previous case.
If you were to print(kwargs['parameter']), you'd get
('param1=test', 'param2=test')
It sounds a bit more cleaner than using a callback, but not by much. Still, hope it helps.

Test name as given with collect-only

I would like to access the name of the current test as a string in my tests to write some VCD log-files.
Is the name as given when I run pytest --collect-only available as a fixture or equivalent?
Example:
Running pytest --collect-only yields (shorted):
<Class TestFooBar>
<Function test_30_foobar[1-A]>
In my test I would like to access the above string test_30_foobar[1-A].
Is there a (simple) way?
I've found an answer for my own question. It's hidden in the request fixture. See the following thereof derived fixture:
#pytest.fixture
def name_test(request):
"""Make name of test available as string and escaped as filename"""
import types
i = types.SimpleNamespace()
i.name = request.node.name
i.filename = i.name.replace('[', '_').replace(']', '')
return i
The filename variable is a clumsily escaped string that should be a valid filename. However, only tested on POSIX so far.

pytest function without return value

I'm trying to do a pytest on a function without return value, but obviously value is None in pytets. I was wondering if there is a solution for that?
here is function which I'm trying to test:
def print_top_movies_url():
for item in movie_link[:100]:
print item.contents[1]
The best thing to do would be to separate getting the top movies and printing them.
For example, you could have a top_movie_urls which looks like this:
def top_movie_urls():
urls = []
for item in movie_link[:100]:
urls.append(item.contents[1])
return urls
(or make it a generator function)
That's easy to test, and wherever you call it, you can now just do something like print('\n'.join(top_movie_urls())).
If you really want to test the output instead, you can use pytest's output capturing to access the output of the tested function and check that.