Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --overwrite-ini ININAME=INIVALUE cli option #1667

Merged
merged 1 commit into from
Jun 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ Samuele Pedroni
Steffen Allner
Stephan Obermann
Tareq Alayan
Ted Xiao
Simon Gomizelj
Stefano Taschini
Stefan Farmbauer
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
finalizer and has access to the fixture's result cache.
Thanks `@d6e`_, `@sallner`_

* New cli flag ``--override-ini`` or ``-o`` that overrides values from the ini file.
Example '-o xfail_strict=True'. A complete ini-options can be viewed
by py.test --help. Thanks `@blueyed`_ and `@fengxx`_ for the PR


**Changes**

Expand Down Expand Up @@ -155,6 +159,8 @@
.. _@nikratio: https://github.com/nikratio
.. _@RedBeardCode: https://github.com/RedBeardCode
.. _@Vogtinator: https://github.com/Vogtinator
.. _@blueyed: https://github.com/blueyed
.. _@fengxx: https://github.com/fengxx

* Fix `#1421`_: Exit tests if a collection error occurs and add
``--continue-on-collection-errors`` option to restore previous behaviour.
Expand Down
32 changes: 24 additions & 8 deletions _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1003,14 +1003,16 @@ def _getini(self, name):
description, type, default = self._parser._inidict[name]
except KeyError:
raise ValueError("unknown configuration value: %r" %(name,))
try:
value = self.inicfg[name]
except KeyError:
if default is not None:
return default
if type is None:
return ''
return []
value = self._get_override_ini_value(name)
if value is None:
try:
value = self.inicfg[name]
except KeyError:
if default is not None:
return default
if type is None:
return ''
return []
if type == "pathlist":
dp = py.path.local(self.inicfg.config.path).dirpath()
l = []
Expand Down Expand Up @@ -1041,6 +1043,20 @@ def _getconftest_pathlist(self, name, path):
l.append(relroot)
return l

def _get_override_ini_value(self, name):
value = None
# override_ini is a list of list, to support both -o foo1=bar1 foo2=bar2 and
# and -o foo1=bar1 -o foo2=bar2 options
# always use the last item if multiple value set for same ini-name,
# e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
if self.getoption("override_ini", None):
for ini_config_list in self.option.override_ini:
for ini_config in ini_config_list:
(key, user_ini_value) = ini_config.split("=", 1)
if key == name:
value = user_ini_value
return value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply return None here and remove the value = None above?


def getoption(self, name, default=notset, skip=False):
""" return command line option value.

Expand Down
4 changes: 4 additions & 0 deletions _pytest/helpconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ def pytest_addoption(parser):
group.addoption('--debug',
action="store_true", dest="debug", default=False,
help="store internal tracing debug information in 'pytestdebug.log'.")
# support for "--overwrite-ini ININAME=INIVALUE" to override values from the ini file
# Example '-o xfail_strict=True'.
group._addoption('-o', '--override-ini', nargs='*', dest="override_ini", action="append",
help="overrides ini values which do not have a separate command-line flag")


@pytest.hookimpl(hookwrapper=True)
Expand Down
89 changes: 89 additions & 0 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,92 @@ def test_with_specific_inifile(self, tmpdir):
inifile = tmpdir.ensure("pytest.ini")
rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir])
assert rootdir == tmpdir

class TestOverrideIniArgs:
""" test --override-ini """
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
def test_override_ini_names(self, testdir, name):
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
[pytest]
custom = 1.0
"""))
testdir.makeconftest("""
def pytest_addoption(parser):
parser.addini("custom", "")
""")
testdir.makepyfile("""
def test_pass(pytestconfig):
ini_val = pytestconfig.getini("custom")
print('\\ncustom_option:%s\\n' % ini_val)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad style because of using global state: better just accept pytestconfig as a fixture into the test.

""")

result = testdir.runpytest("--override-ini", "custom=2.0", "-s")
assert result.ret == 0
result.stdout.fnmatch_lines([
"custom_option:2.0"
])

result = testdir.runpytest("--override-ini", "custom=2.0",
"--override-ini=custom=3.0", "-s")
assert result.ret == 0
result.stdout.fnmatch_lines([
"custom_option:3.0"
])


def test_override_ini_pathlist(self, testdir):
testdir.makeconftest("""
def pytest_addoption(parser):
parser.addini("paths", "my new ini value", type="pathlist")
""")
testdir.makeini("""
[pytest]
paths=blah.py
""")
testdir.makepyfile("""
import py.path
def test_pathlist(pytestconfig):
config_paths = pytestconfig.getini("paths")
print(config_paths)
for cpf in config_paths:
print('\\nuser_path:%s' % cpf.basename)
""")
result = testdir.runpytest("--override-ini", 'paths=foo/bar1.py foo/bar2.py', "-s")
result.stdout.fnmatch_lines([
"user_path:bar1.py",
"user_path:bar2.py"
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a test which sets two different options (say, custom_option_1 and custom_option_2 via --override-ini?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


def test_override_multiple_and_default(self, testdir):
testdir.makeconftest("""
def pytest_addoption(parser):
parser.addini("custom_option_1", "", default="o1")
parser.addini("custom_option_2", "", default="o2")
parser.addini("custom_option_3", "", default=False, type="bool")
parser.addini("custom_option_4", "", default=True, type="bool")

""")
testdir.makeini("""
[pytest]
custom_option_1=custom_option_1
custom_option_2=custom_option_2
""")
testdir.makepyfile("""
def test_multiple_options(pytestconfig):
prefix="custom_option"
for x in range(1,5):
ini_value=pytestconfig.getini("%s_%d" % (prefix, x))
print('\\nini%d:%s' % (x, ini_value))
""")
result = testdir.runpytest("--override-ini",
'custom_option_1=fulldir=/tmp/user1',
'custom_option_2=url=/tmp/user2?a=b&d=e',
"-o", 'custom_option_3=True',
"-o", 'custom_option_4=no',
"-s")
result.stdout.fnmatch_lines([
"ini1:fulldir=/tmp/user1",
"ini2:url=/tmp/user2?a=b&d=e",
"ini3:True",
"ini4:False"
])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we also need a test for multiple -o options -- they all should get applied. So e.g.
-o custom_option1=yes -o custom_option2=no.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrited the testcase to use multiple -o